Live video on the AT Protocol

Compare changes

Choose any two refs to compare.

+9628 -9517
+6
.prettierrc
··· 6 "options": { 7 "proseWrap": "preserve" 8 } 9 } 10 ], 11 "plugins": ["prettier-plugin-organize-imports"]
··· 6 "options": { 7 "proseWrap": "preserve" 8 } 9 + }, 10 + { 11 + "files": "*.md", 12 + "options": { 13 + "proseWrap": "preserve" 14 + } 15 } 16 ], 17 "plugins": ["prettier-plugin-organize-imports"]
+681 -1879
Cargo.lock
··· 37 38 [[package]] 39 name = "addr2line" 40 - version = "0.25.1" 41 source = "registry+https://github.com/rust-lang/crates.io-index" 42 - checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" 43 dependencies = [ 44 "gimli", 45 ] ··· 62 ] 63 64 [[package]] 65 - name = "ahash" 66 - version = "0.8.12" 67 - source = "registry+https://github.com/rust-lang/crates.io-index" 68 - checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" 69 - dependencies = [ 70 - "cfg-if", 71 - "once_cell", 72 - "version_check", 73 - "zerocopy", 74 - ] 75 - 76 - [[package]] 77 name = "aho-corasick" 78 - version = "1.1.4" 79 source = "registry+https://github.com/rust-lang/crates.io-index" 80 - checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" 81 dependencies = [ 82 "memchr", 83 ] ··· 99 100 [[package]] 101 name = "anyhow" 102 - version = "1.0.100" 103 source = "registry+https://github.com/rust-lang/crates.io-index" 104 - checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" 105 dependencies = [ 106 "backtrace", 107 ] ··· 117 118 [[package]] 119 name = "archery" 120 - version = "1.2.2" 121 source = "registry+https://github.com/rust-lang/crates.io-index" 122 - checksum = "70e0a5f99dfebb87bb342d0f53bb92c81842e100bbb915223e38349580e5441d" 123 dependencies = [ 124 "triomphe", 125 ] ··· 159 "proc-macro2", 160 "quote", 161 "serde", 162 - "syn 2.0.114", 163 ] 164 165 [[package]] ··· 201 dependencies = [ 202 "proc-macro2", 203 "quote", 204 - "syn 2.0.114", 205 "synstructure", 206 ] 207 ··· 213 dependencies = [ 214 "proc-macro2", 215 "quote", 216 - "syn 2.0.114", 217 ] 218 219 [[package]] 220 name = "async-compat" 221 - version = "0.2.5" 222 source = "registry+https://github.com/rust-lang/crates.io-index" 223 - checksum = "a1ba85bc55464dcbf728b56d97e119d673f4cf9062be330a9a26f3acf504a590" 224 dependencies = [ 225 "futures-core", 226 "futures-io", ··· 237 dependencies = [ 238 "proc-macro2", 239 "quote", 240 - "syn 2.0.114", 241 ] 242 243 [[package]] ··· 248 dependencies = [ 249 "proc-macro2", 250 "quote", 251 - "syn 2.0.114", 252 - ] 253 - 254 - [[package]] 255 - name = "async-stream" 256 - version = "0.3.6" 257 - source = "registry+https://github.com/rust-lang/crates.io-index" 258 - checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" 259 - dependencies = [ 260 - "async-stream-impl", 261 - "futures-core", 262 - "pin-project-lite", 263 ] 264 265 [[package]] 266 - name = "async-stream-impl" 267 - version = "0.3.6" 268 source = "registry+https://github.com/rust-lang/crates.io-index" 269 - checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" 270 - dependencies = [ 271 - "proc-macro2", 272 - "quote", 273 - "syn 2.0.114", 274 - ] 275 276 [[package]] 277 name = "async-trait" ··· 281 dependencies = [ 282 "proc-macro2", 283 "quote", 284 - "syn 2.0.114", 285 ] 286 287 [[package]] ··· 293 "futures", 294 "pharos", 295 "rustc_version", 296 - ] 297 - 298 - [[package]] 299 - name = "atomic" 300 - version = "0.6.1" 301 - source = "registry+https://github.com/rust-lang/crates.io-index" 302 - checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" 303 - dependencies = [ 304 - "bytemuck", 305 ] 306 307 [[package]] ··· 344 checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 345 346 [[package]] 347 - name = "aws-lc-rs" 348 - version = "1.15.3" 349 - source = "registry+https://github.com/rust-lang/crates.io-index" 350 - checksum = "e84ce723ab67259cfeb9877c6a639ee9eb7a27b28123abd71db7f0d5d0cc9d86" 351 - dependencies = [ 352 - "aws-lc-sys", 353 - "zeroize", 354 - ] 355 - 356 - [[package]] 357 - name = "aws-lc-sys" 358 - version = "0.36.0" 359 - source = "registry+https://github.com/rust-lang/crates.io-index" 360 - checksum = "43a442ece363113bd4bd4c8b18977a7798dd4d3c3383f34fb61936960e8f4ad8" 361 - dependencies = [ 362 - "cc", 363 - "cmake", 364 - "dunce", 365 - "fs_extra", 366 - ] 367 - 368 - [[package]] 369 - name = "axum" 370 - version = "0.7.9" 371 - source = "registry+https://github.com/rust-lang/crates.io-index" 372 - checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" 373 - dependencies = [ 374 - "async-trait", 375 - "axum-core", 376 - "bytes", 377 - "futures-util", 378 - "http", 379 - "http-body", 380 - "http-body-util", 381 - "itoa", 382 - "matchit", 383 - "memchr", 384 - "mime", 385 - "percent-encoding", 386 - "pin-project-lite", 387 - "rustversion", 388 - "serde", 389 - "sync_wrapper", 390 - "tower 0.5.3", 391 - "tower-layer", 392 - "tower-service", 393 - ] 394 - 395 - [[package]] 396 - name = "axum-core" 397 - version = "0.4.5" 398 - source = "registry+https://github.com/rust-lang/crates.io-index" 399 - checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" 400 - dependencies = [ 401 - "async-trait", 402 - "bytes", 403 - "futures-util", 404 - "http", 405 - "http-body", 406 - "http-body-util", 407 - "mime", 408 - "pin-project-lite", 409 - "rustversion", 410 - "sync_wrapper", 411 - "tower-layer", 412 - "tower-service", 413 - ] 414 - 415 - [[package]] 416 name = "backon" 417 - version = "1.6.0" 418 source = "registry+https://github.com/rust-lang/crates.io-index" 419 - checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" 420 dependencies = [ 421 "fastrand", 422 "gloo-timers", ··· 425 426 [[package]] 427 name = "backtrace" 428 - version = "0.3.76" 429 source = "registry+https://github.com/rust-lang/crates.io-index" 430 - checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" 431 dependencies = [ 432 "addr2line", 433 "cfg-if", ··· 435 "miniz_oxide", 436 "object", 437 "rustc-demangle", 438 - "windows-link 0.2.1", 439 ] 440 441 [[package]] 442 name = "base16ct" 443 - version = "1.0.0" 444 source = "registry+https://github.com/rust-lang/crates.io-index" 445 - checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" 446 447 [[package]] 448 name = "base32" ··· 464 465 [[package]] 466 name = "base64ct" 467 - version = "1.8.3" 468 source = "registry+https://github.com/rust-lang/crates.io-index" 469 - checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" 470 471 [[package]] 472 name = "basic-toml" ··· 498 499 [[package]] 500 name = "bitflags" 501 - version = "1.3.2" 502 - source = "registry+https://github.com/rust-lang/crates.io-index" 503 - checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 504 - 505 - [[package]] 506 - name = "bitflags" 507 - version = "2.10.0" 508 source = "registry+https://github.com/rust-lang/crates.io-index" 509 - checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" 510 dependencies = [ 511 - "serde_core", 512 ] 513 514 [[package]] ··· 535 536 [[package]] 537 name = "blake3" 538 - version = "1.8.3" 539 source = "registry+https://github.com/rust-lang/crates.io-index" 540 - checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d" 541 dependencies = [ 542 "arrayref", 543 "arrayvec", 544 "cc", 545 "cfg-if", 546 "constant_time_eq", 547 - "cpufeatures", 548 ] 549 550 [[package]] ··· 558 559 [[package]] 560 name = "block-buffer" 561 - version = "0.11.0" 562 source = "registry+https://github.com/rust-lang/crates.io-index" 563 - checksum = "96eb4cdd6cf1b31d671e9efe75c5d1ec614776856cefbe109ca373554a6d514f" 564 dependencies = [ 565 "hybrid-array", 566 "zeroize", 567 ] 568 569 [[package]] 570 - name = "bollard" 571 - version = "0.18.1" 572 - source = "registry+https://github.com/rust-lang/crates.io-index" 573 - checksum = "97ccca1260af6a459d75994ad5acc1651bcabcbdbc41467cc9786519ab854c30" 574 - dependencies = [ 575 - "base64 0.22.1", 576 - "bollard-stubs", 577 - "bytes", 578 - "futures-core", 579 - "futures-util", 580 - "hex", 581 - "home", 582 - "http", 583 - "http-body-util", 584 - "hyper", 585 - "hyper-named-pipe", 586 - "hyper-rustls", 587 - "hyper-util", 588 - "hyperlocal", 589 - "log", 590 - "pin-project-lite", 591 - "rustls", 592 - "rustls-native-certs", 593 - "rustls-pemfile", 594 - "rustls-pki-types", 595 - "serde", 596 - "serde_derive", 597 - "serde_json", 598 - "serde_repr", 599 - "serde_urlencoded", 600 - "thiserror 2.0.17", 601 - "tokio", 602 - "tokio-util", 603 - "tower-service", 604 - "url", 605 - "winapi", 606 - ] 607 - 608 - [[package]] 609 - name = "bollard-stubs" 610 - version = "1.47.1-rc.27.3.1" 611 - source = "registry+https://github.com/rust-lang/crates.io-index" 612 - checksum = "3f179cfbddb6e77a5472703d4b30436bff32929c0aa8a9008ecf23d1d3cdd0da" 613 - dependencies = [ 614 - "serde", 615 - "serde_repr", 616 - "serde_with", 617 - ] 618 - 619 - [[package]] 620 name = "bounded-integer" 621 version = "0.5.8" 622 source = "registry+https://github.com/rust-lang/crates.io-index" 623 checksum = "102dbef1187b1893e6dfe05a774e79fd52265f49f214f6879c8ff49f52c8188b" 624 625 [[package]] 626 - name = "bstr" 627 - version = "1.12.1" 628 - source = "registry+https://github.com/rust-lang/crates.io-index" 629 - checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" 630 - dependencies = [ 631 - "memchr", 632 - ] 633 - 634 - [[package]] 635 name = "btparse" 636 version = "0.2.0" 637 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 663 664 [[package]] 665 name = "bumpalo" 666 - version = "3.19.1" 667 - source = "registry+https://github.com/rust-lang/crates.io-index" 668 - checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" 669 - 670 - [[package]] 671 - name = "bytemuck" 672 - version = "1.24.0" 673 source = "registry+https://github.com/rust-lang/crates.io-index" 674 - checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" 675 676 [[package]] 677 name = "byteorder" ··· 690 691 [[package]] 692 name = "bytes" 693 - version = "1.11.0" 694 source = "registry+https://github.com/rust-lang/crates.io-index" 695 - checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" 696 dependencies = [ 697 "serde", 698 ] ··· 724 "ed25519-dalek 2.2.0", 725 "env_logger", 726 "extfmt", 727 - "getrandom 0.2.17", 728 "hex", 729 "hex-literal", 730 "http", ··· 749 "quick-xml", 750 "rand 0.8.5", 751 "rand_chacha 0.3.1", 752 - "rand_core 0.9.5", 753 "range-set", 754 "rasn", 755 "rasn-cms", ··· 774 "spki 0.7.3", 775 "static-iref", 776 "tempfile", 777 - "thiserror 2.0.17", 778 "toml 0.8.23", 779 "treeline", 780 "ureq", ··· 784 "wasm-bindgen-futures", 785 "web-sys", 786 "web-time", 787 - "windows-core 0.61.2", 788 "wstd", 789 "x509-certificate", 790 "x509-parser", ··· 819 "ed25519-dalek 2.2.0", 820 "env_logger", 821 "extfmt", 822 - "getrandom 0.2.17", 823 "hex", 824 "hex-literal", 825 "http", ··· 844 "quick-xml", 845 "rand 0.8.5", 846 "rand_chacha 0.3.1", 847 - "rand_core 0.9.5", 848 "range-set", 849 "rasn", 850 "rasn-cms", ··· 868 "spki 0.7.3", 869 "static-iref", 870 "tempfile", 871 - "thiserror 2.0.17", 872 "toml 0.8.23", 873 "treeline", 874 "ureq", ··· 878 "wasm-bindgen-futures", 879 "web-sys", 880 "web-time", 881 - "windows-core 0.61.2", 882 "wstd", 883 "x509-certificate", 884 "x509-parser", ··· 888 889 [[package]] 890 name = "camino" 891 - version = "1.2.2" 892 source = "registry+https://github.com/rust-lang/crates.io-index" 893 - checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" 894 dependencies = [ 895 - "serde_core", 896 ] 897 898 [[package]] ··· 920 921 [[package]] 922 name = "cc" 923 - version = "1.2.52" 924 source = "registry+https://github.com/rust-lang/crates.io-index" 925 - checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3" 926 dependencies = [ 927 - "find-msvc-tools", 928 - "jobserver", 929 - "libc", 930 "shlex", 931 ] 932 ··· 941 942 [[package]] 943 name = "cfg-if" 944 - version = "1.0.4" 945 source = "registry+https://github.com/rust-lang/crates.io-index" 946 - checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 947 948 [[package]] 949 name = "cfg_aliases" ··· 965 966 [[package]] 967 name = "chrono" 968 - version = "0.4.43" 969 source = "registry+https://github.com/rust-lang/crates.io-index" 970 - checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" 971 dependencies = [ 972 "iana-time-zone", 973 "js-sys", 974 "num-traits", 975 "serde", 976 "wasm-bindgen", 977 - "windows-link 0.2.1", 978 ] 979 980 [[package]] ··· 1001 checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 1002 dependencies = [ 1003 "ciborium-io", 1004 - "half 2.7.1", 1005 ] 1006 1007 [[package]] ··· 1010 source = "registry+https://github.com/rust-lang/crates.io-index" 1011 checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" 1012 dependencies = [ 1013 - "block-buffer 0.11.0", 1014 "crypto-common 0.2.0-rc.4", 1015 "inout", 1016 "zeroize", 1017 ] 1018 1019 [[package]] 1020 - name = "cityhash-rs" 1021 - version = "1.0.1" 1022 - source = "registry+https://github.com/rust-lang/crates.io-index" 1023 - checksum = "93a719913643003b84bd13022b4b7e703c09342cd03b679c4641c7d2e50dc34d" 1024 - 1025 - [[package]] 1026 - name = "clickhouse" 1027 - version = "0.13.3" 1028 - source = "registry+https://github.com/rust-lang/crates.io-index" 1029 - checksum = "9a9a81a1dffadd762ee662635ce409232258ce9beebd7cc0fa227df0b5e7efc0" 1030 - dependencies = [ 1031 - "bstr", 1032 - "bytes", 1033 - "chrono", 1034 - "cityhash-rs", 1035 - "clickhouse-derive", 1036 - "futures", 1037 - "futures-channel", 1038 - "http-body-util", 1039 - "hyper", 1040 - "hyper-util", 1041 - "lz4_flex", 1042 - "replace_with", 1043 - "sealed", 1044 - "serde", 1045 - "static_assertions", 1046 - "thiserror 1.0.69", 1047 - "tokio", 1048 - "url", 1049 - "uuid", 1050 - ] 1051 - 1052 - [[package]] 1053 - name = "clickhouse-derive" 1054 - version = "0.2.0" 1055 - source = "registry+https://github.com/rust-lang/crates.io-index" 1056 - checksum = "d70f3e2893f7d3e017eeacdc9a708fbc29a10488e3ebca21f9df6a5d2b616dbb" 1057 - dependencies = [ 1058 - "proc-macro2", 1059 - "quote", 1060 - "serde_derive_internals", 1061 - "syn 2.0.114", 1062 - ] 1063 - 1064 - [[package]] 1065 - name = "cmake" 1066 - version = "0.1.57" 1067 - source = "registry+https://github.com/rust-lang/crates.io-index" 1068 - checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" 1069 - dependencies = [ 1070 - "cc", 1071 - ] 1072 - 1073 - [[package]] 1074 name = "cobs" 1075 version = "0.3.0" 1076 source = "registry+https://github.com/rust-lang/crates.io-index" 1077 checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" 1078 dependencies = [ 1079 - "thiserror 2.0.17", 1080 ] 1081 1082 [[package]] 1083 name = "color-backtrace" 1084 - version = "0.7.2" 1085 source = "registry+https://github.com/rust-lang/crates.io-index" 1086 - checksum = "308329d5d62e877ba02943db3a8e8c052de9fde7ab48283395ba0e6494efbabd" 1087 dependencies = [ 1088 "backtrace", 1089 "btparse", ··· 1119 1120 [[package]] 1121 name = "const-hex" 1122 - version = "1.17.0" 1123 source = "registry+https://github.com/rust-lang/crates.io-index" 1124 - checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" 1125 dependencies = [ 1126 "cfg-if", 1127 "cpufeatures", ··· 1137 1138 [[package]] 1139 name = "const-oid" 1140 - version = "0.10.2" 1141 source = "registry+https://github.com/rust-lang/crates.io-index" 1142 - checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" 1143 1144 [[package]] 1145 name = "const-random" ··· 1156 source = "registry+https://github.com/rust-lang/crates.io-index" 1157 checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 1158 dependencies = [ 1159 - "getrandom 0.2.17", 1160 "once_cell", 1161 "tiny-keccak", 1162 ] 1163 1164 [[package]] 1165 name = "constant_time_eq" 1166 - version = "0.4.2" 1167 source = "registry+https://github.com/rust-lang/crates.io-index" 1168 - checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" 1169 1170 [[package]] 1171 name = "conv" ··· 1177 ] 1178 1179 [[package]] 1180 - name = "convert_case" 1181 - version = "0.10.0" 1182 - source = "registry+https://github.com/rust-lang/crates.io-index" 1183 - checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" 1184 - dependencies = [ 1185 - "unicode-segmentation", 1186 - ] 1187 - 1188 - [[package]] 1189 name = "cordyceps" 1190 version = "0.3.4" 1191 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1206 ] 1207 1208 [[package]] 1209 - name = "core-foundation" 1210 - version = "0.10.1" 1211 - source = "registry+https://github.com/rust-lang/crates.io-index" 1212 - checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" 1213 - dependencies = [ 1214 - "core-foundation-sys", 1215 - "libc", 1216 - ] 1217 - 1218 - [[package]] 1219 name = "core-foundation-sys" 1220 version = "0.8.7" 1221 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1242 1243 [[package]] 1244 name = "crc" 1245 - version = "3.4.0" 1246 source = "registry+https://github.com/rust-lang/crates.io-index" 1247 - checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" 1248 dependencies = [ 1249 "crc-catalog", 1250 ] ··· 1302 1303 [[package]] 1304 name = "crypto-common" 1305 - version = "0.1.7" 1306 source = "registry+https://github.com/rust-lang/crates.io-index" 1307 - checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" 1308 dependencies = [ 1309 "generic-array", 1310 "typenum", ··· 1317 checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" 1318 dependencies = [ 1319 "hybrid-array", 1320 - "rand_core 0.9.5", 1321 ] 1322 1323 [[package]] ··· 1379 "curve25519-dalek-derive", 1380 "digest 0.11.0-rc.3", 1381 "fiat-crypto 0.3.0", 1382 - "rand_core 0.9.5", 1383 "rustc_version", 1384 "serde", 1385 "subtle", ··· 1394 dependencies = [ 1395 "proc-macro2", 1396 "quote", 1397 - "syn 2.0.114", 1398 ] 1399 1400 [[package]] ··· 1424 "proc-macro2", 1425 "quote", 1426 "strsim", 1427 - "syn 2.0.114", 1428 ] 1429 1430 [[package]] ··· 1435 dependencies = [ 1436 "darling_core", 1437 "quote", 1438 - "syn 2.0.114", 1439 ] 1440 1441 [[package]] 1442 name = "data-encoding" 1443 - version = "2.10.0" 1444 source = "registry+https://github.com/rust-lang/crates.io-index" 1445 - checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" 1446 1447 [[package]] 1448 name = "delegate" ··· 1468 1469 [[package]] 1470 name = "der" 1471 - version = "0.8.0-rc.10" 1472 source = "registry+https://github.com/rust-lang/crates.io-index" 1473 - checksum = "02c1d73e9668ea6b6a28172aa55f3ebec38507131ce179051c8033b5c6037653" 1474 dependencies = [ 1475 - "const-oid 0.10.2", 1476 "der_derive", 1477 - "pem-rfc7468 1.0.0", 1478 "zeroize", 1479 ] 1480 ··· 1500 dependencies = [ 1501 "proc-macro2", 1502 "quote", 1503 - "syn 2.0.114", 1504 ] 1505 1506 [[package]] 1507 name = "deranged" 1508 - version = "0.5.5" 1509 source = "registry+https://github.com/rust-lang/crates.io-index" 1510 - checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" 1511 dependencies = [ 1512 "powerfmt", 1513 - "serde_core", 1514 ] 1515 1516 [[package]] ··· 1521 dependencies = [ 1522 "proc-macro2", 1523 "quote", 1524 - "syn 2.0.114", 1525 ] 1526 1527 [[package]] ··· 1535 1536 [[package]] 1537 name = "derive_more" 1538 - version = "2.1.1" 1539 source = "registry+https://github.com/rust-lang/crates.io-index" 1540 - checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" 1541 dependencies = [ 1542 - "derive_more-impl 2.1.1", 1543 ] 1544 1545 [[package]] ··· 1550 dependencies = [ 1551 "proc-macro2", 1552 "quote", 1553 - "syn 2.0.114", 1554 "unicode-xid", 1555 ] 1556 1557 [[package]] 1558 name = "derive_more-impl" 1559 - version = "2.1.1" 1560 source = "registry+https://github.com/rust-lang/crates.io-index" 1561 - checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" 1562 dependencies = [ 1563 - "convert_case", 1564 "proc-macro2", 1565 "quote", 1566 - "rustc_version", 1567 - "syn 2.0.114", 1568 "unicode-xid", 1569 ] 1570 ··· 1582 dependencies = [ 1583 "block-buffer 0.10.4", 1584 "const-oid 0.9.6", 1585 - "crypto-common 0.1.7", 1586 "subtle", 1587 ] 1588 ··· 1592 source = "registry+https://github.com/rust-lang/crates.io-index" 1593 checksum = "dac89f8a64533a9b0eaa73a68e424db0fb1fd6271c74cc0125336a05f090568d" 1594 dependencies = [ 1595 - "block-buffer 0.11.0", 1596 "crypto-common 0.2.0-rc.4", 1597 ] 1598 ··· 1604 dependencies = [ 1605 "proc-macro2", 1606 "quote", 1607 - "syn 2.0.114", 1608 ] 1609 1610 [[package]] ··· 1628 ] 1629 1630 [[package]] 1631 - name = "docker_credential" 1632 - version = "1.3.2" 1633 - source = "registry+https://github.com/rust-lang/crates.io-index" 1634 - checksum = "1d89dfcba45b4afad7450a99b39e751590463e45c04728cf555d36bb66940de8" 1635 - dependencies = [ 1636 - "base64 0.21.7", 1637 - "serde", 1638 - "serde_json", 1639 - ] 1640 - 1641 - [[package]] 1642 name = "document-features" 1643 - version = "0.2.12" 1644 source = "registry+https://github.com/rust-lang/crates.io-index" 1645 - checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" 1646 dependencies = [ 1647 "litrs", 1648 ] 1649 1650 [[package]] 1651 - name = "dotenvy" 1652 - version = "0.15.7" 1653 - source = "registry+https://github.com/rust-lang/crates.io-index" 1654 - checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" 1655 - 1656 - [[package]] 1657 - name = "dunce" 1658 - version = "1.0.5" 1659 - source = "registry+https://github.com/rust-lang/crates.io-index" 1660 - checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" 1661 - 1662 - [[package]] 1663 name = "dyn-clone" 1664 version = "1.0.20" 1665 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1677 1678 [[package]] 1679 name = "ed25519" 1680 - version = "3.0.0-rc.2" 1681 source = "registry+https://github.com/rust-lang/crates.io-index" 1682 - checksum = "594435fe09e345ee388e4e8422072ff7dfeca8729389fbd997b3f5504c44cd47" 1683 dependencies = [ 1684 - "pkcs8 0.11.0-rc.8", 1685 "serde", 1686 - "signature 3.0.0-rc.6", 1687 ] 1688 1689 [[package]] ··· 1709 checksum = "ad207ed88a133091f83224265eac21109930db09bedcad05d5252f2af2de20a1" 1710 dependencies = [ 1711 "curve25519-dalek 5.0.0-pre.1", 1712 - "ed25519 3.0.0-rc.2", 1713 - "rand_core 0.9.5", 1714 "serde", 1715 "sha2 0.11.0-rc.2", 1716 - "signature 3.0.0-rc.6", 1717 "subtle", 1718 "zeroize", 1719 ] ··· 1745 "heck", 1746 "proc-macro2", 1747 "quote", 1748 - "syn 2.0.114", 1749 ] 1750 1751 [[package]] ··· 1765 dependencies = [ 1766 "proc-macro2", 1767 "quote", 1768 - "syn 2.0.114", 1769 ] 1770 1771 [[package]] ··· 1794 checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" 1795 dependencies = [ 1796 "libc", 1797 - "windows-sys 0.61.2", 1798 - ] 1799 - 1800 - [[package]] 1801 - name = "etcetera" 1802 - version = "0.8.0" 1803 - source = "registry+https://github.com/rust-lang/crates.io-index" 1804 - checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" 1805 - dependencies = [ 1806 - "cfg-if", 1807 - "home", 1808 - "windows-sys 0.48.0", 1809 ] 1810 1811 [[package]] ··· 1851 checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" 1852 1853 [[package]] 1854 - name = "figment" 1855 - version = "0.10.19" 1856 - source = "registry+https://github.com/rust-lang/crates.io-index" 1857 - checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" 1858 - dependencies = [ 1859 - "atomic", 1860 - "pear", 1861 - "serde", 1862 - "toml 0.8.23", 1863 - "uncased", 1864 - "version_check", 1865 - ] 1866 - 1867 - [[package]] 1868 - name = "filetime" 1869 - version = "0.2.26" 1870 - source = "registry+https://github.com/rust-lang/crates.io-index" 1871 - checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" 1872 - dependencies = [ 1873 - "cfg-if", 1874 - "libc", 1875 - "libredox", 1876 - "windows-sys 0.60.2", 1877 - ] 1878 - 1879 - [[package]] 1880 - name = "find-msvc-tools" 1881 - version = "0.1.7" 1882 - source = "registry+https://github.com/rust-lang/crates.io-index" 1883 - checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41" 1884 - 1885 - [[package]] 1886 name = "fixedbitset" 1887 version = "0.5.7" 1888 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1890 1891 [[package]] 1892 name = "flate2" 1893 - version = "1.1.8" 1894 source = "registry+https://github.com/rust-lang/crates.io-index" 1895 - checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" 1896 dependencies = [ 1897 "crc32fast", 1898 "miniz_oxide", ··· 1906 1907 [[package]] 1908 name = "foldhash" 1909 - version = "0.1.5" 1910 - source = "registry+https://github.com/rust-lang/crates.io-index" 1911 - checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 1912 - 1913 - [[package]] 1914 - name = "foldhash" 1915 version = "0.2.0" 1916 source = "registry+https://github.com/rust-lang/crates.io-index" 1917 checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" ··· 1933 1934 [[package]] 1935 name = "form_urlencoded" 1936 - version = "1.2.2" 1937 source = "registry+https://github.com/rust-lang/crates.io-index" 1938 - checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" 1939 dependencies = [ 1940 "percent-encoding", 1941 ] ··· 1950 ] 1951 1952 [[package]] 1953 - name = "fs_extra" 1954 - version = "1.3.0" 1955 - source = "registry+https://github.com/rust-lang/crates.io-index" 1956 - checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" 1957 - 1958 - [[package]] 1959 name = "funty" 1960 version = "2.0.0" 1961 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2001 2002 [[package]] 2003 name = "futures-concurrency" 2004 - version = "7.7.0" 2005 source = "registry+https://github.com/rust-lang/crates.io-index" 2006 - checksum = "69a9561702beff46b705a8ac9c0803ec4c7fc5d01330a99b1feaf86e206e92ba" 2007 dependencies = [ 2008 "fixedbitset", 2009 "futures-core", 2010 "futures-lite", 2011 "pin-project", 2012 "smallvec", 2013 ] 2014 ··· 2056 dependencies = [ 2057 "proc-macro2", 2058 "quote", 2059 - "syn 2.0.114", 2060 ] 2061 2062 [[package]] ··· 2091 2092 [[package]] 2093 name = "generator" 2094 - version = "0.8.8" 2095 source = "registry+https://github.com/rust-lang/crates.io-index" 2096 - checksum = "52f04ae4152da20c76fe800fa48659201d5cf627c5149ca0b707b69d7eef6cf9" 2097 dependencies = [ 2098 "cc", 2099 "cfg-if", 2100 "libc", 2101 "log", 2102 "rustversion", 2103 - "windows-link 0.2.1", 2104 - "windows-result 0.4.1", 2105 ] 2106 2107 [[package]] ··· 2116 2117 [[package]] 2118 name = "getrandom" 2119 - version = "0.2.17" 2120 source = "registry+https://github.com/rust-lang/crates.io-index" 2121 - checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" 2122 dependencies = [ 2123 "cfg-if", 2124 "js-sys", ··· 2129 2130 [[package]] 2131 name = "getrandom" 2132 - version = "0.3.4" 2133 source = "registry+https://github.com/rust-lang/crates.io-index" 2134 - checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" 2135 dependencies = [ 2136 "cfg-if", 2137 "js-sys", 2138 "libc", 2139 "r-efi", 2140 - "wasip2", 2141 "wasm-bindgen", 2142 ] 2143 2144 [[package]] 2145 name = "gimli" 2146 - version = "0.32.3" 2147 source = "registry+https://github.com/rust-lang/crates.io-index" 2148 - checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" 2149 2150 [[package]] 2151 name = "glob" ··· 2178 2179 [[package]] 2180 name = "h2" 2181 - version = "0.4.13" 2182 source = "registry+https://github.com/rust-lang/crates.io-index" 2183 - checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" 2184 dependencies = [ 2185 "atomic-waker", 2186 "bytes", ··· 2188 "futures-core", 2189 "futures-sink", 2190 "http", 2191 - "indexmap 2.13.0", 2192 "slab", 2193 "tokio", 2194 "tokio-util", ··· 2203 2204 [[package]] 2205 name = "half" 2206 - version = "2.7.1" 2207 source = "registry+https://github.com/rust-lang/crates.io-index" 2208 - checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" 2209 dependencies = [ 2210 "cfg-if", 2211 "crunchy", 2212 - "zerocopy", 2213 ] 2214 2215 [[package]] ··· 2238 version = "0.15.5" 2239 source = "registry+https://github.com/rust-lang/crates.io-index" 2240 checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" 2241 - dependencies = [ 2242 - "foldhash 0.1.5", 2243 - ] 2244 2245 [[package]] 2246 name = "hashbrown" 2247 - version = "0.16.1" 2248 source = "registry+https://github.com/rust-lang/crates.io-index" 2249 - checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" 2250 dependencies = [ 2251 "allocator-api2", 2252 "equivalent", 2253 - "foldhash 0.2.0", 2254 ] 2255 2256 [[package]] ··· 2319 "rand 0.9.2", 2320 "ring", 2321 "rustls", 2322 - "thiserror 2.0.17", 2323 "tinyvec", 2324 "tokio", 2325 "tokio-rustls", ··· 2344 "resolv-conf", 2345 "rustls", 2346 "smallvec", 2347 - "thiserror 2.0.17", 2348 "tokio", 2349 "tokio-rustls", 2350 "tracing", ··· 2376 checksum = "ad6880c8d4a9ebf39c6e8b77007ce223f646a4d21ce29d99f70cb16420545425" 2377 2378 [[package]] 2379 - name = "home" 2380 - version = "0.5.11" 2381 - source = "registry+https://github.com/rust-lang/crates.io-index" 2382 - checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" 2383 - dependencies = [ 2384 - "windows-sys 0.59.0", 2385 - ] 2386 - 2387 - [[package]] 2388 name = "hostname-validator" 2389 version = "1.1.1" 2390 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2392 2393 [[package]] 2394 name = "http" 2395 - version = "1.4.0" 2396 source = "registry+https://github.com/rust-lang/crates.io-index" 2397 - checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" 2398 dependencies = [ 2399 "bytes", 2400 "itoa", 2401 ] 2402 ··· 2453 2454 [[package]] 2455 name = "hyper" 2456 - version = "1.8.1" 2457 source = "registry+https://github.com/rust-lang/crates.io-index" 2458 - checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" 2459 dependencies = [ 2460 - "atomic-waker", 2461 "bytes", 2462 "futures-channel", 2463 - "futures-core", 2464 "h2", 2465 "http", 2466 "http-body", ··· 2468 "httpdate", 2469 "itoa", 2470 "pin-project-lite", 2471 - "pin-utils", 2472 "smallvec", 2473 "tokio", 2474 "want", 2475 ] 2476 2477 [[package]] 2478 - name = "hyper-named-pipe" 2479 - version = "0.1.0" 2480 - source = "registry+https://github.com/rust-lang/crates.io-index" 2481 - checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" 2482 - dependencies = [ 2483 - "hex", 2484 - "hyper", 2485 - "hyper-util", 2486 - "pin-project-lite", 2487 - "tokio", 2488 - "tower-service", 2489 - "winapi", 2490 - ] 2491 - 2492 - [[package]] 2493 name = "hyper-rustls" 2494 version = "0.27.7" 2495 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2499 "hyper", 2500 "hyper-util", 2501 "rustls", 2502 - "rustls-native-certs", 2503 "rustls-pki-types", 2504 "tokio", 2505 "tokio-rustls", ··· 2508 ] 2509 2510 [[package]] 2511 - name = "hyper-timeout" 2512 - version = "0.5.2" 2513 - source = "registry+https://github.com/rust-lang/crates.io-index" 2514 - checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" 2515 - dependencies = [ 2516 - "hyper", 2517 - "hyper-util", 2518 - "pin-project-lite", 2519 - "tokio", 2520 - "tower-service", 2521 - ] 2522 - 2523 - [[package]] 2524 name = "hyper-util" 2525 - version = "0.1.19" 2526 source = "registry+https://github.com/rust-lang/crates.io-index" 2527 - checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" 2528 dependencies = [ 2529 "base64 0.22.1", 2530 "bytes", ··· 2538 "libc", 2539 "percent-encoding", 2540 "pin-project-lite", 2541 - "socket2 0.6.1", 2542 "tokio", 2543 "tower-service", 2544 "tracing", 2545 ] 2546 2547 [[package]] 2548 - name = "hyperlocal" 2549 - version = "0.9.1" 2550 - source = "registry+https://github.com/rust-lang/crates.io-index" 2551 - checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7" 2552 - dependencies = [ 2553 - "hex", 2554 - "http-body-util", 2555 - "hyper", 2556 - "hyper-util", 2557 - "pin-project-lite", 2558 - "tokio", 2559 - "tower-service", 2560 - ] 2561 - 2562 - [[package]] 2563 name = "iana-time-zone" 2564 - version = "0.1.64" 2565 source = "registry+https://github.com/rust-lang/crates.io-index" 2566 - checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" 2567 dependencies = [ 2568 "android_system_properties", 2569 "core-foundation-sys", ··· 2571 "js-sys", 2572 "log", 2573 "wasm-bindgen", 2574 - "windows-core 0.62.2", 2575 ] 2576 2577 [[package]] ··· 2585 2586 [[package]] 2587 name = "icu_collections" 2588 - version = "2.1.1" 2589 source = "registry+https://github.com/rust-lang/crates.io-index" 2590 - checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" 2591 dependencies = [ 2592 "displaydoc", 2593 "potential_utf", ··· 2598 2599 [[package]] 2600 name = "icu_locale_core" 2601 - version = "2.1.1" 2602 source = "registry+https://github.com/rust-lang/crates.io-index" 2603 - checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" 2604 dependencies = [ 2605 "displaydoc", 2606 "litemap", ··· 2611 2612 [[package]] 2613 name = "icu_normalizer" 2614 - version = "2.1.1" 2615 source = "registry+https://github.com/rust-lang/crates.io-index" 2616 - checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" 2617 dependencies = [ 2618 "icu_collections", 2619 "icu_normalizer_data", 2620 "icu_properties", ··· 2625 2626 [[package]] 2627 name = "icu_normalizer_data" 2628 - version = "2.1.1" 2629 source = "registry+https://github.com/rust-lang/crates.io-index" 2630 - checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" 2631 2632 [[package]] 2633 name = "icu_properties" 2634 - version = "2.1.2" 2635 source = "registry+https://github.com/rust-lang/crates.io-index" 2636 - checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" 2637 dependencies = [ 2638 "icu_collections", 2639 "icu_locale_core", 2640 "icu_properties_data", 2641 "icu_provider", 2642 "zerotrie", 2643 "zerovec", 2644 ] 2645 2646 [[package]] 2647 name = "icu_properties_data" 2648 - version = "2.1.2" 2649 source = "registry+https://github.com/rust-lang/crates.io-index" 2650 - checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" 2651 2652 [[package]] 2653 name = "icu_provider" 2654 - version = "2.1.1" 2655 source = "registry+https://github.com/rust-lang/crates.io-index" 2656 - checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" 2657 dependencies = [ 2658 "displaydoc", 2659 "icu_locale_core", 2660 "writeable", 2661 "yoke", 2662 "zerofrom", ··· 2670 source = "registry+https://github.com/rust-lang/crates.io-index" 2671 checksum = "872718dfcd3a6f4601a3fb413365ee5e1d3ec050316ff79e690c98658a6738ef" 2672 dependencies = [ 2673 - "bitflags 2.10.0", 2674 "byteorder", 2675 "flate2", 2676 ] ··· 2683 2684 [[package]] 2685 name = "idna" 2686 - version = "1.1.0" 2687 source = "registry+https://github.com/rust-lang/crates.io-index" 2688 - checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" 2689 dependencies = [ 2690 "idna_adapter", 2691 "smallvec", ··· 2747 2748 [[package]] 2749 name = "indexmap" 2750 - version = "2.13.0" 2751 source = "registry+https://github.com/rust-lang/crates.io-index" 2752 - checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" 2753 dependencies = [ 2754 "equivalent", 2755 - "hashbrown 0.16.1", 2756 "serde", 2757 - "serde_core", 2758 ] 2759 2760 [[package]] 2761 name = "indoc" 2762 - version = "2.0.7" 2763 - source = "registry+https://github.com/rust-lang/crates.io-index" 2764 - checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" 2765 - dependencies = [ 2766 - "rustversion", 2767 - ] 2768 - 2769 - [[package]] 2770 - name = "inlinable_string" 2771 - version = "0.1.15" 2772 source = "registry+https://github.com/rust-lang/crates.io-index" 2773 - checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" 2774 2775 [[package]] 2776 name = "inout" 2777 - version = "0.2.2" 2778 source = "registry+https://github.com/rust-lang/crates.io-index" 2779 - checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" 2780 dependencies = [ 2781 "hybrid-array", 2782 ] ··· 2794 ] 2795 2796 [[package]] 2797 name = "ipconfig" 2798 version = "0.3.2" 2799 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2835 2836 [[package]] 2837 name = "iri-string" 2838 - version = "0.7.10" 2839 source = "registry+https://github.com/rust-lang/crates.io-index" 2840 - checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" 2841 dependencies = [ 2842 "memchr", 2843 "serde", ··· 2855 "cfg_aliases", 2856 "crypto_box", 2857 "data-encoding", 2858 - "der 0.8.0-rc.10", 2859 - "derive_more 2.1.1", 2860 "ed25519-dalek 3.0.0-pre.1", 2861 "futures-buffered", 2862 "futures-util", 2863 - "getrandom 0.3.4", 2864 "hickory-resolver", 2865 "http", 2866 "igd-next", ··· 2876 "n0-watcher", 2877 "nested_enum_utils", 2878 "netdev 0.36.0", 2879 - "netwatch 0.9.0", 2880 "pin-project", 2881 "pkarr", 2882 - "pkcs8 0.11.0-rc.8", 2883 "portmapper", 2884 "rand 0.9.2", 2885 "reqwest", ··· 2913 dependencies = [ 2914 "curve25519-dalek 5.0.0-pre.1", 2915 "data-encoding", 2916 - "derive_more 2.1.1", 2917 "ed25519-dalek 3.0.0-pre.1", 2918 "n0-snafu", 2919 "nested_enum_utils", 2920 "postcard", 2921 - "rand_core 0.9.5", 2922 "serde", 2923 "snafu", 2924 "url", ··· 2933 "blake3", 2934 "bytes", 2935 "data-encoding", 2936 - "derive_more 2.1.1", 2937 "ed25519-dalek 3.0.0-pre.1", 2938 "futures-concurrency", 2939 "futures-lite", 2940 "futures-util", 2941 "hex", 2942 - "indexmap 2.13.0", 2943 "iroh", 2944 "iroh-base", 2945 "iroh-metrics", ··· 2958 2959 [[package]] 2960 name = "iroh-metrics" 2961 - version = "0.36.2" 2962 source = "registry+https://github.com/rust-lang/crates.io-index" 2963 - checksum = "c84c167b59ae22f940e78eb347ca5f02aa25608e994cb5a7cc016ac2d5eada18" 2964 dependencies = [ 2965 "iroh-metrics-derive", 2966 "itoa", ··· 2973 2974 [[package]] 2975 name = "iroh-metrics-derive" 2976 - version = "0.3.1" 2977 source = "registry+https://github.com/rust-lang/crates.io-index" 2978 - checksum = "748d380f26f7c25307c0a7acd181b84b977ddc2a1b7beece1e5998623c323aa1" 2979 dependencies = [ 2980 "heck", 2981 "proc-macro2", 2982 "quote", 2983 - "syn 2.0.114", 2984 ] 2985 2986 [[package]] ··· 2997 "rustc-hash", 2998 "rustls", 2999 "socket2 0.5.10", 3000 - "thiserror 2.0.17", 3001 "tokio", 3002 "tracing", 3003 "web-time", ··· 3010 checksum = "929d5d8fa77d5c304d3ee7cae9aede31f13908bd049f9de8c7c0094ad6f7c535" 3011 dependencies = [ 3012 "bytes", 3013 - "getrandom 0.2.17", 3014 "rand 0.8.5", 3015 "ring", 3016 "rustc-hash", 3017 "rustls", 3018 "rustls-pki-types", 3019 "slab", 3020 - "thiserror 2.0.17", 3021 "tinyvec", 3022 "tracing", 3023 "web-time", ··· 3047 "bytes", 3048 "cfg_aliases", 3049 "data-encoding", 3050 - "derive_more 2.1.1", 3051 - "getrandom 0.3.4", 3052 "hickory-resolver", 3053 "http", 3054 "http-body-util", ··· 3058 "iroh-metrics", 3059 "iroh-quinn", 3060 "iroh-quinn-proto", 3061 - "lru", 3062 "n0-future 0.2.0", 3063 "n0-snafu", 3064 "nested_enum_utils", ··· 3137 "serde_json", 3138 "snafu", 3139 "testresult", 3140 - "thiserror 2.0.17", 3141 "tokio", 3142 "tracing", 3143 "tracing-subscriber", ··· 3162 "rustls", 3163 "serde", 3164 "smallvec", 3165 - "thiserror 2.0.17", 3166 "tokio", 3167 "tokio-util", 3168 "tracing", ··· 3186 checksum = "80e06eb3077e16299f86816ca5f5d795abccf6e5c58340d701ecc4166bdcf2ea" 3187 dependencies = [ 3188 "anyhow", 3189 - "getrandom 0.3.4", 3190 "iroh", 3191 "iroh-base", 3192 "irpc", ··· 3199 3200 [[package]] 3201 name = "is-terminal" 3202 - version = "0.4.17" 3203 source = "registry+https://github.com/rust-lang/crates.io-index" 3204 - checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" 3205 dependencies = [ 3206 "hermit-abi", 3207 "libc", 3208 - "windows-sys 0.61.2", 3209 ] 3210 3211 [[package]] ··· 3218 ] 3219 3220 [[package]] 3221 - name = "itertools" 3222 - version = "0.14.0" 3223 - source = "registry+https://github.com/rust-lang/crates.io-index" 3224 - checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" 3225 - dependencies = [ 3226 - "either", 3227 - ] 3228 - 3229 - [[package]] 3230 name = "itoa" 3231 - version = "1.0.17" 3232 source = "registry+https://github.com/rust-lang/crates.io-index" 3233 - checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" 3234 3235 [[package]] 3236 name = "jfifdump" ··· 3239 checksum = "68cf72bc7b75b6615ffd06bfe6840f3c57e7e4ea615558a2a452f458ebf5551e" 3240 3241 [[package]] 3242 - name = "jobserver" 3243 - version = "0.1.34" 3244 - source = "registry+https://github.com/rust-lang/crates.io-index" 3245 - checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" 3246 - dependencies = [ 3247 - "getrandom 0.3.4", 3248 - "libc", 3249 - ] 3250 - 3251 - [[package]] 3252 name = "js-sys" 3253 - version = "0.3.83" 3254 source = "registry+https://github.com/rust-lang/crates.io-index" 3255 - checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" 3256 dependencies = [ 3257 "once_cell", 3258 "wasm-bindgen", ··· 3280 3281 [[package]] 3282 name = "libc" 3283 - version = "0.2.180" 3284 source = "registry+https://github.com/rust-lang/crates.io-index" 3285 - checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" 3286 3287 [[package]] 3288 name = "libm" ··· 3291 checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" 3292 3293 [[package]] 3294 - name = "libredox" 3295 - version = "0.1.12" 3296 - source = "registry+https://github.com/rust-lang/crates.io-index" 3297 - checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" 3298 - dependencies = [ 3299 - "bitflags 2.10.0", 3300 - "libc", 3301 - "redox_syscall 0.7.0", 3302 - ] 3303 - 3304 - [[package]] 3305 name = "linux-raw-sys" 3306 version = "0.4.15" 3307 source = "registry+https://github.com/rust-lang/crates.io-index" 3308 checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" 3309 3310 [[package]] 3311 - name = "linux-raw-sys" 3312 - version = "0.11.0" 3313 - source = "registry+https://github.com/rust-lang/crates.io-index" 3314 - checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" 3315 - 3316 - [[package]] 3317 name = "litemap" 3318 - version = "0.8.1" 3319 source = "registry+https://github.com/rust-lang/crates.io-index" 3320 - checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" 3321 3322 [[package]] 3323 name = "litrs" 3324 - version = "1.0.0" 3325 source = "registry+https://github.com/rust-lang/crates.io-index" 3326 - checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" 3327 3328 [[package]] 3329 name = "lock_api" 3330 - version = "0.4.14" 3331 source = "registry+https://github.com/rust-lang/crates.io-index" 3332 - checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" 3333 dependencies = [ 3334 "scopeguard", 3335 ] 3336 3337 [[package]] 3338 name = "log" 3339 - version = "0.4.29" 3340 source = "registry+https://github.com/rust-lang/crates.io-index" 3341 - checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" 3342 3343 [[package]] 3344 name = "loom" ··· 3355 3356 [[package]] 3357 name = "lru" 3358 - version = "0.16.3" 3359 source = "registry+https://github.com/rust-lang/crates.io-index" 3360 - checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" 3361 dependencies = [ 3362 - "hashbrown 0.16.1", 3363 ] 3364 3365 [[package]] ··· 3369 checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" 3370 3371 [[package]] 3372 - name = "lz4_flex" 3373 - version = "0.11.5" 3374 - source = "registry+https://github.com/rust-lang/crates.io-index" 3375 - checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" 3376 - 3377 - [[package]] 3378 name = "matchers" 3379 - version = "0.2.0" 3380 source = "registry+https://github.com/rust-lang/crates.io-index" 3381 - checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" 3382 dependencies = [ 3383 - "regex-automata", 3384 ] 3385 - 3386 - [[package]] 3387 - name = "matchit" 3388 - version = "0.7.3" 3389 - source = "registry+https://github.com/rust-lang/crates.io-index" 3390 - checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" 3391 3392 [[package]] 3393 name = "md5" ··· 3397 3398 [[package]] 3399 name = "memchr" 3400 - version = "2.7.6" 3401 - source = "registry+https://github.com/rust-lang/crates.io-index" 3402 - checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" 3403 - 3404 - [[package]] 3405 - name = "metrics" 3406 - version = "0.24.3" 3407 - source = "registry+https://github.com/rust-lang/crates.io-index" 3408 - checksum = "5d5312e9ba3771cfa961b585728215e3d972c950a3eed9252aa093d6301277e8" 3409 - dependencies = [ 3410 - "ahash", 3411 - "portable-atomic", 3412 - ] 3413 - 3414 - [[package]] 3415 - name = "metrics-exporter-prometheus" 3416 - version = "0.16.2" 3417 - source = "registry+https://github.com/rust-lang/crates.io-index" 3418 - checksum = "dd7399781913e5393588a8d8c6a2867bf85fb38eaf2502fdce465aad2dc6f034" 3419 - dependencies = [ 3420 - "base64 0.22.1", 3421 - "http-body-util", 3422 - "hyper", 3423 - "hyper-rustls", 3424 - "hyper-util", 3425 - "indexmap 2.13.0", 3426 - "ipnet", 3427 - "metrics", 3428 - "metrics-util", 3429 - "quanta", 3430 - "thiserror 1.0.69", 3431 - "tokio", 3432 - "tracing", 3433 - ] 3434 - 3435 - [[package]] 3436 - name = "metrics-util" 3437 - version = "0.19.1" 3438 source = "registry+https://github.com/rust-lang/crates.io-index" 3439 - checksum = "b8496cc523d1f94c1385dd8f0f0c2c480b2b8aeccb5b7e4485ad6365523ae376" 3440 - dependencies = [ 3441 - "crossbeam-epoch", 3442 - "crossbeam-utils", 3443 - "hashbrown 0.15.5", 3444 - "metrics", 3445 - "quanta", 3446 - "rand 0.9.2", 3447 - "rand_xoshiro", 3448 - "sketches-ddsketch", 3449 - ] 3450 3451 [[package]] 3452 name = "mime" ··· 3482 3483 [[package]] 3484 name = "mio" 3485 - version = "1.1.1" 3486 source = "registry+https://github.com/rust-lang/crates.io-index" 3487 - checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" 3488 dependencies = [ 3489 "libc", 3490 "wasi 0.11.1+wasi-snapshot-preview1", 3491 - "windows-sys 0.61.2", 3492 ] 3493 3494 [[package]] 3495 name = "moka" 3496 - version = "0.12.12" 3497 source = "registry+https://github.com/rust-lang/crates.io-index" 3498 - checksum = "a3dec6bd31b08944e08b58fd99373893a6c17054d6f3ea5006cc894f4f4eee2a" 3499 dependencies = [ 3500 "crossbeam-channel", 3501 "crossbeam-epoch", 3502 "crossbeam-utils", 3503 - "equivalent", 3504 "parking_lot", 3505 "portable-atomic", 3506 "smallvec", 3507 "tagptr", 3508 "uuid", 3509 ] 3510 ··· 3521 "serde_json", 3522 "thiserror 1.0.69", 3523 ] 3524 - 3525 - [[package]] 3526 - name = "multimap" 3527 - version = "0.10.1" 3528 - source = "registry+https://github.com/rust-lang/crates.io-index" 3529 - checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" 3530 3531 [[package]] 3532 name = "n0-future" ··· 3596 3597 [[package]] 3598 name = "nested_enum_utils" 3599 - version = "0.2.3" 3600 source = "registry+https://github.com/rust-lang/crates.io-index" 3601 - checksum = "b1d5475271bdd36a4a2769eac1ef88df0f99428ea43e52dfd8b0ee5cb674695f" 3602 dependencies = [ 3603 "proc-macro-crate", 3604 "proc-macro2", 3605 "quote", 3606 - "syn 2.0.114", 3607 ] 3608 3609 [[package]] ··· 3615 "dlopen2", 3616 "ipnet", 3617 "libc", 3618 - "netlink-packet-core 0.7.0", 3619 "netlink-packet-route 0.22.0", 3620 "netlink-sys", 3621 "once_cell", ··· 3632 "dlopen2", 3633 "ipnet", 3634 "libc", 3635 - "netlink-packet-core 0.7.0", 3636 "netlink-packet-route 0.22.0", 3637 "netlink-sys", 3638 "once_cell", ··· 3641 ] 3642 3643 [[package]] 3644 - name = "netdev" 3645 - version = "0.38.2" 3646 - source = "registry+https://github.com/rust-lang/crates.io-index" 3647 - checksum = "67ab878b4c90faf36dab10ea51d48c69ae9019bcca47c048a7c9b273d5d7a823" 3648 - dependencies = [ 3649 - "dlopen2", 3650 - "ipnet", 3651 - "libc", 3652 - "netlink-packet-core 0.8.1", 3653 - "netlink-packet-route 0.25.1", 3654 - "netlink-sys", 3655 - "once_cell", 3656 - "system-configuration", 3657 - "windows-sys 0.59.0", 3658 - ] 3659 - 3660 - [[package]] 3661 name = "netlink-packet-core" 3662 version = "0.7.0" 3663 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3669 ] 3670 3671 [[package]] 3672 - name = "netlink-packet-core" 3673 - version = "0.8.1" 3674 - source = "registry+https://github.com/rust-lang/crates.io-index" 3675 - checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4" 3676 - dependencies = [ 3677 - "paste", 3678 - ] 3679 - 3680 - [[package]] 3681 name = "netlink-packet-route" 3682 version = "0.22.0" 3683 source = "registry+https://github.com/rust-lang/crates.io-index" 3684 checksum = "fc0e7987b28514adf555dc1f9a5c30dfc3e50750bbaffb1aec41ca7b23dcd8e4" 3685 dependencies = [ 3686 "anyhow", 3687 - "bitflags 2.10.0", 3688 "byteorder", 3689 "libc", 3690 "log", 3691 - "netlink-packet-core 0.7.0", 3692 "netlink-packet-utils", 3693 ] 3694 ··· 3699 checksum = "56d83370a96813d7c977f8b63054f1162df6e5784f1c598d689236564fb5a6f2" 3700 dependencies = [ 3701 "anyhow", 3702 - "bitflags 2.10.0", 3703 "byteorder", 3704 "libc", 3705 "log", 3706 - "netlink-packet-core 0.7.0", 3707 "netlink-packet-utils", 3708 ] 3709 3710 [[package]] 3711 - name = "netlink-packet-route" 3712 - version = "0.25.1" 3713 - source = "registry+https://github.com/rust-lang/crates.io-index" 3714 - checksum = "3ec2f5b6839be2a19d7fa5aab5bc444380f6311c2b693551cb80f45caaa7b5ef" 3715 - dependencies = [ 3716 - "bitflags 2.10.0", 3717 - "libc", 3718 - "log", 3719 - "netlink-packet-core 0.8.1", 3720 - ] 3721 - 3722 - [[package]] 3723 name = "netlink-packet-utils" 3724 version = "0.5.2" 3725 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3740 "bytes", 3741 "futures", 3742 "log", 3743 - "netlink-packet-core 0.7.0", 3744 - "netlink-sys", 3745 - "thiserror 2.0.17", 3746 - ] 3747 - 3748 - [[package]] 3749 - name = "netlink-proto" 3750 - version = "0.12.0" 3751 - source = "registry+https://github.com/rust-lang/crates.io-index" 3752 - checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128" 3753 - dependencies = [ 3754 - "bytes", 3755 - "futures", 3756 - "log", 3757 - "netlink-packet-core 0.8.1", 3758 "netlink-sys", 3759 - "thiserror 2.0.17", 3760 ] 3761 3762 [[package]] ··· 3781 "atomic-waker", 3782 "bytes", 3783 "cfg_aliases", 3784 - "derive_more 2.1.1", 3785 "iroh-quinn-udp", 3786 "js-sys", 3787 "libc", ··· 3789 "n0-watcher", 3790 "nested_enum_utils", 3791 "netdev 0.37.3", 3792 - "netlink-packet-core 0.7.0", 3793 "netlink-packet-route 0.24.0", 3794 - "netlink-proto 0.11.5", 3795 - "netlink-sys", 3796 - "pin-project-lite", 3797 - "serde", 3798 - "snafu", 3799 - "socket2 0.6.1", 3800 - "time", 3801 - "tokio", 3802 - "tokio-util", 3803 - "tracing", 3804 - "web-sys", 3805 - "windows 0.61.3", 3806 - "windows-result 0.3.4", 3807 - "wmi", 3808 - ] 3809 - 3810 - [[package]] 3811 - name = "netwatch" 3812 - version = "0.10.0" 3813 - source = "registry+https://github.com/rust-lang/crates.io-index" 3814 - checksum = "29acc9361df4a91bde6d2ec1ce110de7c826e574eeb3662ec1f574af00b96c48" 3815 - dependencies = [ 3816 - "atomic-waker", 3817 - "bytes", 3818 - "cfg_aliases", 3819 - "derive_more 2.1.1", 3820 - "iroh-quinn-udp", 3821 - "js-sys", 3822 - "libc", 3823 - "n0-future 0.2.0", 3824 - "n0-watcher", 3825 - "nested_enum_utils", 3826 - "netdev 0.38.2", 3827 - "netlink-packet-core 0.8.1", 3828 - "netlink-packet-route 0.25.1", 3829 - "netlink-proto 0.12.0", 3830 "netlink-sys", 3831 "pin-project-lite", 3832 "serde", 3833 "snafu", 3834 - "socket2 0.6.1", 3835 "time", 3836 "tokio", 3837 "tokio-util", 3838 "tracing", 3839 "web-sys", 3840 - "windows 0.62.2", 3841 - "windows-result 0.4.1", 3842 "wmi", 3843 ] 3844 ··· 3885 dependencies = [ 3886 "base32", 3887 "document-features", 3888 - "getrandom 0.2.17", 3889 "httpdate", 3890 "js-sys", 3891 "once_cell", ··· 3894 3895 [[package]] 3896 name = "nu-ansi-term" 3897 - version = "0.50.3" 3898 source = "registry+https://github.com/rust-lang/crates.io-index" 3899 - checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" 3900 dependencies = [ 3901 - "windows-sys 0.61.2", 3902 ] 3903 3904 [[package]] ··· 3913 3914 [[package]] 3915 name = "num-bigint-dig" 3916 - version = "0.8.6" 3917 source = "registry+https://github.com/rust-lang/crates.io-index" 3918 - checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" 3919 dependencies = [ 3920 "lazy_static", 3921 "libm", 3922 "num-integer", ··· 3978 3979 [[package]] 3980 name = "num_enum" 3981 - version = "0.7.5" 3982 source = "registry+https://github.com/rust-lang/crates.io-index" 3983 - checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" 3984 dependencies = [ 3985 "num_enum_derive", 3986 "rustversion", ··· 3988 3989 [[package]] 3990 name = "num_enum_derive" 3991 - version = "0.7.5" 3992 source = "registry+https://github.com/rust-lang/crates.io-index" 3993 - checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" 3994 dependencies = [ 3995 "proc-macro-crate", 3996 "proc-macro2", 3997 "quote", 3998 - "syn 2.0.114", 3999 ] 4000 4001 [[package]] 4002 name = "object" 4003 - version = "0.37.3" 4004 source = "registry+https://github.com/rust-lang/crates.io-index" 4005 - checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" 4006 dependencies = [ 4007 "memchr", 4008 ] ··· 4028 4029 [[package]] 4030 name = "openssl" 4031 - version = "0.10.75" 4032 source = "registry+https://github.com/rust-lang/crates.io-index" 4033 - checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" 4034 dependencies = [ 4035 - "bitflags 2.10.0", 4036 "cfg-if", 4037 "foreign-types", 4038 "libc", ··· 4049 dependencies = [ 4050 "proc-macro2", 4051 "quote", 4052 - "syn 2.0.114", 4053 ] 4054 4055 [[package]] 4056 - name = "openssl-probe" 4057 - version = "0.2.0" 4058 - source = "registry+https://github.com/rust-lang/crates.io-index" 4059 - checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" 4060 - 4061 - [[package]] 4062 name = "openssl-src" 4063 - version = "300.5.4+3.5.4" 4064 source = "registry+https://github.com/rust-lang/crates.io-index" 4065 - checksum = "a507b3792995dae9b0df8a1c1e3771e8418b7c2d9f0baeba32e6fe8b06c7cb72" 4066 dependencies = [ 4067 "cc", 4068 ] 4069 4070 [[package]] 4071 name = "openssl-sys" 4072 - version = "0.9.111" 4073 source = "registry+https://github.com/rust-lang/crates.io-index" 4074 - checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" 4075 dependencies = [ 4076 "cc", 4077 "libc", ··· 4091 ] 4092 4093 [[package]] 4094 name = "parking" 4095 version = "2.2.1" 4096 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4098 4099 [[package]] 4100 name = "parking_lot" 4101 - version = "0.12.5" 4102 source = "registry+https://github.com/rust-lang/crates.io-index" 4103 - checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" 4104 dependencies = [ 4105 "lock_api", 4106 "parking_lot_core", ··· 4108 4109 [[package]] 4110 name = "parking_lot_core" 4111 - version = "0.9.12" 4112 source = "registry+https://github.com/rust-lang/crates.io-index" 4113 - checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" 4114 dependencies = [ 4115 "cfg-if", 4116 "libc", 4117 - "redox_syscall 0.5.18", 4118 "smallvec", 4119 - "windows-link 0.2.1", 4120 - ] 4121 - 4122 - [[package]] 4123 - name = "parse-display" 4124 - version = "0.9.1" 4125 - source = "registry+https://github.com/rust-lang/crates.io-index" 4126 - checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a" 4127 - dependencies = [ 4128 - "parse-display-derive", 4129 - "regex", 4130 - "regex-syntax", 4131 - ] 4132 - 4133 - [[package]] 4134 - name = "parse-display-derive" 4135 - version = "0.9.1" 4136 - source = "registry+https://github.com/rust-lang/crates.io-index" 4137 - checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281" 4138 - dependencies = [ 4139 - "proc-macro2", 4140 - "quote", 4141 - "regex", 4142 - "regex-syntax", 4143 - "structmeta", 4144 - "syn 2.0.114", 4145 ] 4146 4147 [[package]] ··· 4176 ] 4177 4178 [[package]] 4179 - name = "pear" 4180 - version = "0.2.9" 4181 - source = "registry+https://github.com/rust-lang/crates.io-index" 4182 - checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" 4183 - dependencies = [ 4184 - "inlinable_string", 4185 - "pear_codegen", 4186 - "yansi", 4187 - ] 4188 - 4189 - [[package]] 4190 - name = "pear_codegen" 4191 - version = "0.2.9" 4192 - source = "registry+https://github.com/rust-lang/crates.io-index" 4193 - checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" 4194 - dependencies = [ 4195 - "proc-macro2", 4196 - "proc-macro2-diagnostics", 4197 - "quote", 4198 - "syn 2.0.114", 4199 - ] 4200 - 4201 - [[package]] 4202 name = "peg" 4203 version = "0.8.5" 4204 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4227 4228 [[package]] 4229 name = "pem" 4230 - version = "3.0.6" 4231 source = "registry+https://github.com/rust-lang/crates.io-index" 4232 - checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" 4233 dependencies = [ 4234 "base64 0.22.1", 4235 - "serde_core", 4236 ] 4237 4238 [[package]] ··· 4246 4247 [[package]] 4248 name = "pem-rfc7468" 4249 - version = "1.0.0" 4250 source = "registry+https://github.com/rust-lang/crates.io-index" 4251 - checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" 4252 dependencies = [ 4253 "base64ct", 4254 ] 4255 4256 [[package]] 4257 name = "percent-encoding" 4258 - version = "2.3.2" 4259 source = "registry+https://github.com/rust-lang/crates.io-index" 4260 - checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" 4261 4262 [[package]] 4263 name = "pest" 4264 - version = "2.8.5" 4265 source = "registry+https://github.com/rust-lang/crates.io-index" 4266 - checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" 4267 dependencies = [ 4268 "memchr", 4269 "ucd-trie", 4270 ] 4271 4272 [[package]] 4273 name = "pest_derive" 4274 - version = "2.8.5" 4275 source = "registry+https://github.com/rust-lang/crates.io-index" 4276 - checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed" 4277 dependencies = [ 4278 "pest", 4279 "pest_generator", ··· 4281 4282 [[package]] 4283 name = "pest_generator" 4284 - version = "2.8.5" 4285 source = "registry+https://github.com/rust-lang/crates.io-index" 4286 - checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5" 4287 dependencies = [ 4288 "pest", 4289 "pest_meta", 4290 "proc-macro2", 4291 "quote", 4292 - "syn 2.0.114", 4293 ] 4294 4295 [[package]] 4296 name = "pest_meta" 4297 - version = "2.8.5" 4298 source = "registry+https://github.com/rust-lang/crates.io-index" 4299 - checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365" 4300 dependencies = [ 4301 "pest", 4302 "sha2 0.10.9", 4303 ] 4304 4305 [[package]] 4306 - name = "petgraph" 4307 - version = "0.7.1" 4308 - source = "registry+https://github.com/rust-lang/crates.io-index" 4309 - checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" 4310 - dependencies = [ 4311 - "fixedbitset", 4312 - "indexmap 2.13.0", 4313 - ] 4314 - 4315 - [[package]] 4316 name = "pharos" 4317 version = "0.5.3" 4318 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4339 dependencies = [ 4340 "proc-macro2", 4341 "quote", 4342 - "syn 2.0.114", 4343 ] 4344 4345 [[package]] ··· 4362 4363 [[package]] 4364 name = "pkarr" 4365 - version = "5.0.2" 4366 source = "registry+https://github.com/rust-lang/crates.io-index" 4367 - checksum = "e1d346b545765a0ef58b6a7e160e17ddaa7427f439b7b9a287df6c88c9e04bf2" 4368 dependencies = [ 4369 "async-compat", 4370 "base32", ··· 4375 "ed25519-dalek 3.0.0-pre.1", 4376 "futures-buffered", 4377 "futures-lite", 4378 - "getrandom 0.3.4", 4379 "log", 4380 - "lru", 4381 "ntimestamp", 4382 "reqwest", 4383 "self_cell", 4384 "serde", 4385 "sha1_smol", 4386 "simple-dns", 4387 - "thiserror 2.0.17", 4388 "tokio", 4389 "tracing", 4390 "url", ··· 4414 4415 [[package]] 4416 name = "pkcs8" 4417 - version = "0.11.0-rc.8" 4418 source = "registry+https://github.com/rust-lang/crates.io-index" 4419 - checksum = "77089aec8290d0b7bb01b671b091095cf1937670725af4fd73d47249f03b12c0" 4420 dependencies = [ 4421 - "der 0.8.0-rc.10", 4422 "spki 0.8.0-rc.4", 4423 ] 4424 ··· 4452 "proc-macro2", 4453 "quote", 4454 "regex", 4455 - "syn 2.0.114", 4456 ] 4457 4458 [[package]] ··· 4501 4502 [[package]] 4503 name = "portable-atomic" 4504 - version = "1.13.0" 4505 source = "registry+https://github.com/rust-lang/crates.io-index" 4506 - checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" 4507 4508 [[package]] 4509 name = "portmapper" 4510 - version = "0.10.1" 4511 source = "registry+https://github.com/rust-lang/crates.io-index" 4512 - checksum = "2b3a9274d533a9554cccbc791b8a016b6574aa68c2b2f9bda68463348791330e" 4513 dependencies = [ 4514 "base64 0.22.1", 4515 "bytes", 4516 - "derive_more 2.1.1", 4517 "futures-lite", 4518 "futures-util", 4519 "hyper-util", ··· 4521 "iroh-metrics", 4522 "libc", 4523 "nested_enum_utils", 4524 - "netwatch 0.10.0", 4525 "num_enum", 4526 "rand 0.9.2", 4527 "serde", 4528 "smallvec", 4529 "snafu", 4530 - "socket2 0.6.1", 4531 "time", 4532 "tokio", 4533 "tokio-util", ··· 4558 dependencies = [ 4559 "proc-macro2", 4560 "quote", 4561 - "syn 2.0.114", 4562 ] 4563 4564 [[package]] 4565 name = "potential_utf" 4566 - version = "0.1.4" 4567 source = "registry+https://github.com/rust-lang/crates.io-index" 4568 - checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" 4569 dependencies = [ 4570 "zerovec", 4571 ] ··· 4598 4599 [[package]] 4600 name = "precis-profiles" 4601 - version = "0.1.13" 4602 source = "registry+https://github.com/rust-lang/crates.io-index" 4603 - checksum = "31e2768890a47af73a032af9f0cedbddce3c9d06cf8de201d5b8f2436ded7674" 4604 dependencies = [ 4605 "lazy_static", 4606 "precis-core", ··· 4620 ] 4621 4622 [[package]] 4623 - name = "prettyplease" 4624 - version = "0.2.37" 4625 - source = "registry+https://github.com/rust-lang/crates.io-index" 4626 - checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" 4627 - dependencies = [ 4628 - "proc-macro2", 4629 - "syn 2.0.114", 4630 - ] 4631 - 4632 - [[package]] 4633 name = "proc-macro-crate" 4634 - version = "3.4.0" 4635 source = "registry+https://github.com/rust-lang/crates.io-index" 4636 - checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" 4637 dependencies = [ 4638 - "toml_edit 0.23.10+spec-1.0.0", 4639 ] 4640 4641 [[package]] ··· 4664 4665 [[package]] 4666 name = "proc-macro2" 4667 - version = "1.0.105" 4668 source = "registry+https://github.com/rust-lang/crates.io-index" 4669 - checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" 4670 dependencies = [ 4671 "unicode-ident", 4672 ] 4673 4674 [[package]] 4675 - name = "proc-macro2-diagnostics" 4676 - version = "0.10.1" 4677 - source = "registry+https://github.com/rust-lang/crates.io-index" 4678 - checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" 4679 - dependencies = [ 4680 - "proc-macro2", 4681 - "quote", 4682 - "syn 2.0.114", 4683 - "version_check", 4684 - "yansi", 4685 - ] 4686 - 4687 - [[package]] 4688 name = "proptest" 4689 - version = "1.9.0" 4690 source = "registry+https://github.com/rust-lang/crates.io-index" 4691 - checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" 4692 dependencies = [ 4693 - "bitflags 2.10.0", 4694 "num-traits", 4695 "rand 0.9.2", 4696 "rand_chacha 0.9.0", 4697 "rand_xorshift", 4698 - "regex-syntax", 4699 "unarray", 4700 ] 4701 4702 [[package]] 4703 - name = "prost" 4704 - version = "0.13.5" 4705 - source = "registry+https://github.com/rust-lang/crates.io-index" 4706 - checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" 4707 - dependencies = [ 4708 - "bytes", 4709 - "prost-derive", 4710 - ] 4711 - 4712 - [[package]] 4713 - name = "prost-build" 4714 - version = "0.13.5" 4715 - source = "registry+https://github.com/rust-lang/crates.io-index" 4716 - checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" 4717 - dependencies = [ 4718 - "heck", 4719 - "itertools 0.14.0", 4720 - "log", 4721 - "multimap", 4722 - "once_cell", 4723 - "petgraph", 4724 - "prettyplease", 4725 - "prost", 4726 - "prost-types", 4727 - "regex", 4728 - "syn 2.0.114", 4729 - "tempfile", 4730 - ] 4731 - 4732 - [[package]] 4733 - name = "prost-derive" 4734 - version = "0.13.5" 4735 - source = "registry+https://github.com/rust-lang/crates.io-index" 4736 - checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" 4737 - dependencies = [ 4738 - "anyhow", 4739 - "itertools 0.14.0", 4740 - "proc-macro2", 4741 - "quote", 4742 - "syn 2.0.114", 4743 - ] 4744 - 4745 - [[package]] 4746 - name = "prost-types" 4747 - version = "0.13.5" 4748 - source = "registry+https://github.com/rust-lang/crates.io-index" 4749 - checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" 4750 - dependencies = [ 4751 - "prost", 4752 - ] 4753 - 4754 - [[package]] 4755 - name = "quanta" 4756 - version = "0.12.6" 4757 - source = "registry+https://github.com/rust-lang/crates.io-index" 4758 - checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" 4759 - dependencies = [ 4760 - "crossbeam-utils", 4761 - "libc", 4762 - "once_cell", 4763 - "raw-cpuid", 4764 - "wasi 0.11.1+wasi-snapshot-preview1", 4765 - "web-sys", 4766 - "winapi", 4767 - ] 4768 - 4769 - [[package]] 4770 name = "quick-xml" 4771 version = "0.37.5" 4772 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4777 4778 [[package]] 4779 name = "quinn" 4780 - version = "0.11.9" 4781 source = "registry+https://github.com/rust-lang/crates.io-index" 4782 - checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" 4783 dependencies = [ 4784 "bytes", 4785 "cfg_aliases", ··· 4788 "quinn-udp", 4789 "rustc-hash", 4790 "rustls", 4791 - "socket2 0.6.1", 4792 - "thiserror 2.0.17", 4793 "tokio", 4794 "tracing", 4795 "web-time", ··· 4797 4798 [[package]] 4799 name = "quinn-proto" 4800 - version = "0.11.13" 4801 source = "registry+https://github.com/rust-lang/crates.io-index" 4802 - checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" 4803 dependencies = [ 4804 "bytes", 4805 - "getrandom 0.3.4", 4806 "lru-slab", 4807 "rand 0.9.2", 4808 "ring", ··· 4810 "rustls", 4811 "rustls-pki-types", 4812 "slab", 4813 - "thiserror 2.0.17", 4814 "tinyvec", 4815 "tracing", 4816 "web-time", ··· 4818 4819 [[package]] 4820 name = "quinn-udp" 4821 - version = "0.5.14" 4822 source = "registry+https://github.com/rust-lang/crates.io-index" 4823 - checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" 4824 dependencies = [ 4825 "cfg_aliases", 4826 "libc", 4827 "once_cell", 4828 - "socket2 0.6.1", 4829 "tracing", 4830 - "windows-sys 0.60.2", 4831 ] 4832 4833 [[package]] 4834 name = "quote" 4835 - version = "1.0.43" 4836 source = "registry+https://github.com/rust-lang/crates.io-index" 4837 - checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" 4838 dependencies = [ 4839 "proc-macro2", 4840 ] ··· 4879 checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" 4880 dependencies = [ 4881 "rand_chacha 0.9.0", 4882 - "rand_core 0.9.5", 4883 ] 4884 4885 [[package]] ··· 4899 checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 4900 dependencies = [ 4901 "ppv-lite86", 4902 - "rand_core 0.9.5", 4903 ] 4904 4905 [[package]] ··· 4908 source = "registry+https://github.com/rust-lang/crates.io-index" 4909 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 4910 dependencies = [ 4911 - "getrandom 0.2.17", 4912 ] 4913 4914 [[package]] 4915 name = "rand_core" 4916 - version = "0.9.5" 4917 source = "registry+https://github.com/rust-lang/crates.io-index" 4918 - checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" 4919 dependencies = [ 4920 - "getrandom 0.3.4", 4921 ] 4922 4923 [[package]] ··· 4926 source = "registry+https://github.com/rust-lang/crates.io-index" 4927 checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" 4928 dependencies = [ 4929 - "rand_core 0.9.5", 4930 - ] 4931 - 4932 - [[package]] 4933 - name = "rand_xoshiro" 4934 - version = "0.7.0" 4935 - source = "registry+https://github.com/rust-lang/crates.io-index" 4936 - checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" 4937 - dependencies = [ 4938 - "rand_core 0.9.5", 4939 ] 4940 4941 [[package]] ··· 4994 dependencies = [ 4995 "proc-macro2", 4996 "rasn-derive-impl", 4997 - "syn 2.0.114", 4998 ] 4999 5000 [[package]] ··· 5004 checksum = "f14454245fd76215b830d083b6b6c6842047e50cb7ee73ce1e769d4b099c89fd" 5005 dependencies = [ 5006 "either", 5007 - "itertools 0.13.0", 5008 "proc-macro2", 5009 "quote", 5010 - "syn 2.0.114", 5011 "uuid", 5012 ] 5013 ··· 5028 checksum = "0c902bfc1add6e7471323cdb879fe6a3c3122b1cb0247937c0940b28e2334252" 5029 dependencies = [ 5030 "rasn", 5031 - ] 5032 - 5033 - [[package]] 5034 - name = "raw-cpuid" 5035 - version = "11.6.0" 5036 - source = "registry+https://github.com/rust-lang/crates.io-index" 5037 - checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" 5038 - dependencies = [ 5039 - "bitflags 2.10.0", 5040 ] 5041 5042 [[package]] ··· 5053 ] 5054 5055 [[package]] 5056 - name = "redb" 5057 - version = "2.6.3" 5058 - source = "registry+https://github.com/rust-lang/crates.io-index" 5059 - checksum = "8eca1e9d98d5a7e9002d0013e18d5a9b000aee942eb134883a82f06ebffb6c01" 5060 - dependencies = [ 5061 - "libc", 5062 - ] 5063 - 5064 - [[package]] 5065 name = "redox_syscall" 5066 - version = "0.3.5" 5067 - source = "registry+https://github.com/rust-lang/crates.io-index" 5068 - checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 5069 - dependencies = [ 5070 - "bitflags 1.3.2", 5071 - ] 5072 - 5073 - [[package]] 5074 - name = "redox_syscall" 5075 - version = "0.5.18" 5076 - source = "registry+https://github.com/rust-lang/crates.io-index" 5077 - checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" 5078 - dependencies = [ 5079 - "bitflags 2.10.0", 5080 - ] 5081 - 5082 - [[package]] 5083 - name = "redox_syscall" 5084 - version = "0.7.0" 5085 source = "registry+https://github.com/rust-lang/crates.io-index" 5086 - checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" 5087 dependencies = [ 5088 - "bitflags 2.10.0", 5089 ] 5090 5091 [[package]] ··· 5105 dependencies = [ 5106 "proc-macro2", 5107 "quote", 5108 - "syn 2.0.114", 5109 ] 5110 5111 [[package]] 5112 name = "regex" 5113 - version = "1.12.2" 5114 source = "registry+https://github.com/rust-lang/crates.io-index" 5115 - checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" 5116 dependencies = [ 5117 "aho-corasick", 5118 "memchr", 5119 - "regex-automata", 5120 - "regex-syntax", 5121 ] 5122 5123 [[package]] 5124 name = "regex-automata" 5125 - version = "0.4.13" 5126 source = "registry+https://github.com/rust-lang/crates.io-index" 5127 - checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" 5128 dependencies = [ 5129 "aho-corasick", 5130 "memchr", 5131 - "regex-syntax", 5132 ] 5133 5134 [[package]] 5135 name = "regex-lite" 5136 - version = "0.1.8" 5137 source = "registry+https://github.com/rust-lang/crates.io-index" 5138 - checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da" 5139 5140 [[package]] 5141 name = "regex-syntax" 5142 - version = "0.8.8" 5143 source = "registry+https://github.com/rust-lang/crates.io-index" 5144 - checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" 5145 5146 [[package]] 5147 - name = "replace_with" 5148 - version = "0.1.8" 5149 source = "registry+https://github.com/rust-lang/crates.io-index" 5150 - checksum = "51743d3e274e2b18df81c4dc6caf8a5b8e15dbe799e0dca05c7617380094e884" 5151 5152 [[package]] 5153 name = "reqwest" 5154 - version = "0.12.28" 5155 source = "registry+https://github.com/rust-lang/crates.io-index" 5156 - checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" 5157 dependencies = [ 5158 "base64 0.22.1", 5159 "bytes", ··· 5179 "tokio", 5180 "tokio-rustls", 5181 "tokio-util", 5182 - "tower 0.5.3", 5183 "tower-http", 5184 "tower-service", 5185 "url", ··· 5192 5193 [[package]] 5194 name = "resolv-conf" 5195 - version = "0.7.6" 5196 source = "registry+https://github.com/rust-lang/crates.io-index" 5197 - checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" 5198 5199 [[package]] 5200 name = "riff" ··· 5210 dependencies = [ 5211 "cc", 5212 "cfg-if", 5213 - "getrandom 0.2.17", 5214 "libc", 5215 "untrusted", 5216 "windows-sys 0.52.0", ··· 5223 checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" 5224 dependencies = [ 5225 "base64 0.21.7", 5226 - "bitflags 2.10.0", 5227 "serde", 5228 "serde_derive", 5229 ] 5230 5231 [[package]] 5232 name = "rpds" 5233 - version = "1.2.0" 5234 source = "registry+https://github.com/rust-lang/crates.io-index" 5235 - checksum = "9e75f485e819d4d3015e6c0d55d02a4fd3db47c1993d9e603e0361fba2bffb34" 5236 dependencies = [ 5237 "archery", 5238 "serde", ··· 5240 5241 [[package]] 5242 name = "rsa" 5243 - version = "0.9.10" 5244 source = "registry+https://github.com/rust-lang/crates.io-index" 5245 - checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" 5246 dependencies = [ 5247 "const-oid 0.9.6", 5248 "digest 0.10.7", ··· 5305 source = "registry+https://github.com/rust-lang/crates.io-index" 5306 checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" 5307 dependencies = [ 5308 - "bitflags 2.10.0", 5309 "errno", 5310 "libc", 5311 - "linux-raw-sys 0.4.15", 5312 "windows-sys 0.59.0", 5313 ] 5314 5315 [[package]] 5316 - name = "rustix" 5317 - version = "1.1.3" 5318 - source = "registry+https://github.com/rust-lang/crates.io-index" 5319 - checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" 5320 - dependencies = [ 5321 - "bitflags 2.10.0", 5322 - "errno", 5323 - "libc", 5324 - "linux-raw-sys 0.11.0", 5325 - "windows-sys 0.61.2", 5326 - ] 5327 - 5328 - [[package]] 5329 name = "rustls" 5330 - version = "0.23.36" 5331 source = "registry+https://github.com/rust-lang/crates.io-index" 5332 - checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" 5333 dependencies = [ 5334 - "aws-lc-rs", 5335 "log", 5336 "once_cell", 5337 "ring", ··· 5342 ] 5343 5344 [[package]] 5345 - name = "rustls-native-certs" 5346 - version = "0.8.3" 5347 - source = "registry+https://github.com/rust-lang/crates.io-index" 5348 - checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" 5349 - dependencies = [ 5350 - "openssl-probe", 5351 - "rustls-pki-types", 5352 - "schannel", 5353 - "security-framework", 5354 - ] 5355 - 5356 - [[package]] 5357 name = "rustls-pemfile" 5358 version = "2.2.0" 5359 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5364 5365 [[package]] 5366 name = "rustls-pki-types" 5367 - version = "1.13.2" 5368 source = "registry+https://github.com/rust-lang/crates.io-index" 5369 - checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" 5370 dependencies = [ 5371 "web-time", 5372 "zeroize", ··· 5374 5375 [[package]] 5376 name = "rustls-webpki" 5377 - version = "0.103.8" 5378 source = "registry+https://github.com/rust-lang/crates.io-index" 5379 - checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" 5380 dependencies = [ 5381 - "aws-lc-rs", 5382 "ring", 5383 "rustls-pki-types", 5384 "untrusted", ··· 5392 5393 [[package]] 5394 name = "ryu" 5395 - version = "1.0.22" 5396 source = "registry+https://github.com/rust-lang/crates.io-index" 5397 - checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" 5398 5399 [[package]] 5400 name = "salsa20" ··· 5404 dependencies = [ 5405 "cfg-if", 5406 "cipher", 5407 - ] 5408 - 5409 - [[package]] 5410 - name = "schannel" 5411 - version = "0.1.28" 5412 - source = "registry+https://github.com/rust-lang/crates.io-index" 5413 - checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" 5414 - dependencies = [ 5415 - "windows-sys 0.61.2", 5416 ] 5417 5418 [[package]] ··· 5441 5442 [[package]] 5443 name = "schemars" 5444 - version = "1.2.0" 5445 source = "registry+https://github.com/rust-lang/crates.io-index" 5446 - checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" 5447 dependencies = [ 5448 "dyn-clone", 5449 "ref-cast", ··· 5460 "proc-macro2", 5461 "quote", 5462 "serde_derive_internals", 5463 - "syn 2.0.114", 5464 ] 5465 5466 [[package]] ··· 5492 dependencies = [ 5493 "proc-macro2", 5494 "quote", 5495 - "syn 2.0.114", 5496 - ] 5497 - 5498 - [[package]] 5499 - name = "sealed" 5500 - version = "0.6.0" 5501 - source = "registry+https://github.com/rust-lang/crates.io-index" 5502 - checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107" 5503 - dependencies = [ 5504 - "proc-macro2", 5505 - "quote", 5506 - "syn 2.0.114", 5507 - ] 5508 - 5509 - [[package]] 5510 - name = "security-framework" 5511 - version = "3.5.1" 5512 - source = "registry+https://github.com/rust-lang/crates.io-index" 5513 - checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" 5514 - dependencies = [ 5515 - "bitflags 2.10.0", 5516 - "core-foundation 0.10.1", 5517 - "core-foundation-sys", 5518 - "libc", 5519 - "security-framework-sys", 5520 - ] 5521 - 5522 - [[package]] 5523 - name = "security-framework-sys" 5524 - version = "2.15.0" 5525 - source = "registry+https://github.com/rust-lang/crates.io-index" 5526 - checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" 5527 - dependencies = [ 5528 - "core-foundation-sys", 5529 - "libc", 5530 ] 5531 5532 [[package]] 5533 name = "self_cell" 5534 - version = "1.2.2" 5535 source = "registry+https://github.com/rust-lang/crates.io-index" 5536 - checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" 5537 5538 [[package]] 5539 name = "semver" 5540 - version = "1.0.27" 5541 source = "registry+https://github.com/rust-lang/crates.io-index" 5542 - checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" 5543 dependencies = [ 5544 "serde", 5545 - "serde_core", 5546 ] 5547 5548 [[package]] ··· 5553 5554 [[package]] 5555 name = "serde" 5556 - version = "1.0.228" 5557 source = "registry+https://github.com/rust-lang/crates.io-index" 5558 - checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" 5559 dependencies = [ 5560 "serde_core", 5561 "serde_derive", ··· 5592 5593 [[package]] 5594 name = "serde_bytes" 5595 - version = "0.11.19" 5596 source = "registry+https://github.com/rust-lang/crates.io-index" 5597 - checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" 5598 dependencies = [ 5599 "serde", 5600 - "serde_core", 5601 ] 5602 5603 [[package]] ··· 5612 5613 [[package]] 5614 name = "serde_core" 5615 - version = "1.0.228" 5616 source = "registry+https://github.com/rust-lang/crates.io-index" 5617 - checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" 5618 dependencies = [ 5619 "serde_derive", 5620 ] 5621 5622 [[package]] 5623 name = "serde_derive" 5624 - version = "1.0.228" 5625 source = "registry+https://github.com/rust-lang/crates.io-index" 5626 - checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" 5627 dependencies = [ 5628 "proc-macro2", 5629 "quote", 5630 - "syn 2.0.114", 5631 ] 5632 5633 [[package]] ··· 5638 dependencies = [ 5639 "proc-macro2", 5640 "quote", 5641 - "syn 2.0.114", 5642 ] 5643 5644 [[package]] 5645 name = "serde_json" 5646 - version = "1.0.149" 5647 source = "registry+https://github.com/rust-lang/crates.io-index" 5648 - checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" 5649 dependencies = [ 5650 - "indexmap 2.13.0", 5651 "itoa", 5652 "memchr", 5653 "serde", 5654 "serde_core", 5655 - "zmij", 5656 - ] 5657 - 5658 - [[package]] 5659 - name = "serde_repr" 5660 - version = "0.1.20" 5661 - source = "registry+https://github.com/rust-lang/crates.io-index" 5662 - checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" 5663 - dependencies = [ 5664 - "proc-macro2", 5665 - "quote", 5666 - "syn 2.0.114", 5667 ] 5668 5669 [[package]] ··· 5689 5690 [[package]] 5691 name = "serde_with" 5692 - version = "3.16.1" 5693 source = "registry+https://github.com/rust-lang/crates.io-index" 5694 - checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" 5695 dependencies = [ 5696 "base64 0.22.1", 5697 "chrono", 5698 "hex", 5699 "indexmap 1.9.3", 5700 - "indexmap 2.13.0", 5701 "schemars 0.9.0", 5702 - "schemars 1.2.0", 5703 - "serde_core", 5704 "serde_json", 5705 "serde_with_macros", 5706 "time", ··· 5708 5709 [[package]] 5710 name = "serde_with_macros" 5711 - version = "3.16.1" 5712 source = "registry+https://github.com/rust-lang/crates.io-index" 5713 - checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" 5714 dependencies = [ 5715 "darling", 5716 "proc-macro2", 5717 "quote", 5718 - "syn 2.0.114", 5719 ] 5720 5721 [[package]] 5722 name = "serdect" 5723 - version = "0.4.2" 5724 source = "registry+https://github.com/rust-lang/crates.io-index" 5725 - checksum = "9af4a3e75ebd5599b30d4de5768e00b5095d518a79fefc3ecbaf77e665d1ec06" 5726 dependencies = [ 5727 "base16ct", 5728 "serde", ··· 5784 5785 [[package]] 5786 name = "signal-hook-registry" 5787 - version = "1.4.8" 5788 source = "registry+https://github.com/rust-lang/crates.io-index" 5789 - checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" 5790 dependencies = [ 5791 - "errno", 5792 "libc", 5793 ] 5794 ··· 5804 5805 [[package]] 5806 name = "signature" 5807 - version = "3.0.0-rc.6" 5808 source = "registry+https://github.com/rust-lang/crates.io-index" 5809 - checksum = "597a96996ccff7dfa16f052bd995b4cecc72af22c35138738dc029f0ead6608d" 5810 5811 [[package]] 5812 name = "simd-adler32" 5813 - version = "0.3.8" 5814 source = "registry+https://github.com/rust-lang/crates.io-index" 5815 - checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" 5816 5817 [[package]] 5818 name = "simdutf8" ··· 5826 source = "registry+https://github.com/rust-lang/crates.io-index" 5827 checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" 5828 dependencies = [ 5829 - "bitflags 2.10.0", 5830 ] 5831 5832 [[package]] ··· 5836 checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" 5837 5838 [[package]] 5839 - name = "sketches-ddsketch" 5840 - version = "0.3.0" 5841 - source = "registry+https://github.com/rust-lang/crates.io-index" 5842 - checksum = "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a" 5843 - 5844 - [[package]] 5845 name = "slab" 5846 version = "0.4.11" 5847 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5884 "heck", 5885 "proc-macro2", 5886 "quote", 5887 - "syn 2.0.114", 5888 ] 5889 5890 [[package]] ··· 5899 5900 [[package]] 5901 name = "socket2" 5902 - version = "0.6.1" 5903 source = "registry+https://github.com/rust-lang/crates.io-index" 5904 - checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" 5905 dependencies = [ 5906 "libc", 5907 - "windows-sys 0.60.2", 5908 - ] 5909 - 5910 - [[package]] 5911 - name = "sp-analytics" 5912 - version = "0.1.0" 5913 - dependencies = [ 5914 - "anyhow", 5915 - "chrono", 5916 - "clickhouse", 5917 - "dotenvy", 5918 - "figment", 5919 - "metrics", 5920 - "metrics-exporter-prometheus", 5921 - "prost", 5922 - "prost-types", 5923 - "redb", 5924 - "serde", 5925 - "serde_json", 5926 - "tempfile", 5927 - "testcontainers", 5928 - "thiserror 2.0.17", 5929 - "tokio", 5930 - "tonic", 5931 - "tonic-build", 5932 - "tracing", 5933 - "tracing-subscriber", 5934 - "uuid", 5935 ] 5936 5937 [[package]] ··· 5966 checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" 5967 dependencies = [ 5968 "base64ct", 5969 - "der 0.8.0-rc.10", 5970 ] 5971 5972 [[package]] 5973 name = "stable_deref_trait" 5974 - version = "1.2.1" 5975 source = "registry+https://github.com/rust-lang/crates.io-index" 5976 - checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" 5977 5978 [[package]] 5979 name = "static-iref" ··· 5983 dependencies = [ 5984 "iref", 5985 "quote", 5986 - "syn 2.0.114", 5987 ] 5988 5989 [[package]] ··· 6002 "quote", 6003 "serde", 6004 "sha2 0.10.9", 6005 - "syn 2.0.114", 6006 "thiserror 1.0.69", 6007 ] 6008 ··· 6019 checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 6020 6021 [[package]] 6022 - name = "structmeta" 6023 - version = "0.3.0" 6024 - source = "registry+https://github.com/rust-lang/crates.io-index" 6025 - checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329" 6026 - dependencies = [ 6027 - "proc-macro2", 6028 - "quote", 6029 - "structmeta-derive", 6030 - "syn 2.0.114", 6031 - ] 6032 - 6033 - [[package]] 6034 - name = "structmeta-derive" 6035 - version = "0.3.0" 6036 - source = "registry+https://github.com/rust-lang/crates.io-index" 6037 - checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" 6038 - dependencies = [ 6039 - "proc-macro2", 6040 - "quote", 6041 - "syn 2.0.114", 6042 - ] 6043 - 6044 - [[package]] 6045 name = "strum" 6046 version = "0.27.2" 6047 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6059 "heck", 6060 "proc-macro2", 6061 "quote", 6062 - "syn 2.0.114", 6063 ] 6064 6065 [[package]] ··· 6094 6095 [[package]] 6096 name = "surge-ping" 6097 - version = "0.8.4" 6098 source = "registry+https://github.com/rust-lang/crates.io-index" 6099 - checksum = "30498e9c9feba213c3df6ed675bdf75519ccbee493517e7225305898c86cac05" 6100 dependencies = [ 6101 "hex", 6102 "parking_lot", 6103 "pnet_packet", 6104 "rand 0.9.2", 6105 - "socket2 0.6.1", 6106 "thiserror 1.0.69", 6107 "tokio", 6108 "tracing", ··· 6110 6111 [[package]] 6112 name = "swarm-discovery" 6113 - version = "0.4.1" 6114 source = "registry+https://github.com/rust-lang/crates.io-index" 6115 - checksum = "790d8444f7db1e88f70aed3234cab8e42c48e05360bfc86ca7dce0d9a5d95d26" 6116 dependencies = [ 6117 "acto", 6118 "hickory-proto", 6119 "rand 0.9.2", 6120 "socket2 0.5.10", 6121 - "thiserror 2.0.17", 6122 "tokio", 6123 "tracing", 6124 ] ··· 6136 6137 [[package]] 6138 name = "syn" 6139 - version = "2.0.114" 6140 source = "registry+https://github.com/rust-lang/crates.io-index" 6141 - checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" 6142 dependencies = [ 6143 "proc-macro2", 6144 "quote", ··· 6162 dependencies = [ 6163 "proc-macro2", 6164 "quote", 6165 - "syn 2.0.114", 6166 ] 6167 6168 [[package]] ··· 6171 source = "registry+https://github.com/rust-lang/crates.io-index" 6172 checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 6173 dependencies = [ 6174 - "bitflags 2.10.0", 6175 - "core-foundation 0.9.4", 6176 "system-configuration-sys", 6177 ] 6178 ··· 6206 dependencies = [ 6207 "cfg-if", 6208 "fastrand", 6209 - "getrandom 0.2.17", 6210 "once_cell", 6211 - "rustix 0.38.44", 6212 "windows-sys 0.59.0", 6213 ] 6214 ··· 6222 ] 6223 6224 [[package]] 6225 - name = "testcontainers" 6226 - version = "0.23.3" 6227 - source = "registry+https://github.com/rust-lang/crates.io-index" 6228 - checksum = "59a4f01f39bb10fc2a5ab23eb0d888b1e2bb168c157f61a1b98e6c501c639c74" 6229 - dependencies = [ 6230 - "async-trait", 6231 - "bollard", 6232 - "bollard-stubs", 6233 - "bytes", 6234 - "docker_credential", 6235 - "either", 6236 - "etcetera", 6237 - "futures", 6238 - "log", 6239 - "memchr", 6240 - "parse-display", 6241 - "pin-project-lite", 6242 - "serde", 6243 - "serde_json", 6244 - "serde_with", 6245 - "thiserror 2.0.17", 6246 - "tokio", 6247 - "tokio-stream", 6248 - "tokio-tar", 6249 - "tokio-util", 6250 - "url", 6251 - ] 6252 - 6253 - [[package]] 6254 name = "testresult" 6255 version = "0.4.1" 6256 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6276 6277 [[package]] 6278 name = "thiserror" 6279 - version = "2.0.17" 6280 source = "registry+https://github.com/rust-lang/crates.io-index" 6281 - checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" 6282 dependencies = [ 6283 - "thiserror-impl 2.0.17", 6284 ] 6285 6286 [[package]] ··· 6291 dependencies = [ 6292 "proc-macro2", 6293 "quote", 6294 - "syn 2.0.114", 6295 ] 6296 6297 [[package]] 6298 name = "thiserror-impl" 6299 - version = "2.0.17" 6300 source = "registry+https://github.com/rust-lang/crates.io-index" 6301 - checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" 6302 dependencies = [ 6303 "proc-macro2", 6304 "quote", 6305 - "syn 2.0.114", 6306 ] 6307 6308 [[package]] ··· 6316 6317 [[package]] 6318 name = "time" 6319 - version = "0.3.45" 6320 source = "registry+https://github.com/rust-lang/crates.io-index" 6321 - checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" 6322 dependencies = [ 6323 "deranged", 6324 "itoa", 6325 "js-sys", 6326 "num-conv", 6327 "powerfmt", 6328 - "serde_core", 6329 "time-core", 6330 "time-macros", 6331 ] 6332 6333 [[package]] 6334 name = "time-core" 6335 - version = "0.1.7" 6336 source = "registry+https://github.com/rust-lang/crates.io-index" 6337 - checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" 6338 6339 [[package]] 6340 name = "time-macros" 6341 - version = "0.2.25" 6342 source = "registry+https://github.com/rust-lang/crates.io-index" 6343 - checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" 6344 dependencies = [ 6345 "num-conv", 6346 "time-core", ··· 6357 6358 [[package]] 6359 name = "tinystr" 6360 - version = "0.8.2" 6361 source = "registry+https://github.com/rust-lang/crates.io-index" 6362 - checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" 6363 dependencies = [ 6364 "displaydoc", 6365 "zerovec", ··· 6367 6368 [[package]] 6369 name = "tinyvec" 6370 - version = "1.10.0" 6371 source = "registry+https://github.com/rust-lang/crates.io-index" 6372 - checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" 6373 dependencies = [ 6374 "tinyvec_macros", 6375 ] ··· 6382 6383 [[package]] 6384 name = "tokio" 6385 - version = "1.49.0" 6386 source = "registry+https://github.com/rust-lang/crates.io-index" 6387 - checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" 6388 dependencies = [ 6389 "bytes", 6390 "libc", 6391 "mio", 6392 - "parking_lot", 6393 "pin-project-lite", 6394 "signal-hook-registry", 6395 - "socket2 0.6.1", 6396 "tokio-macros", 6397 - "windows-sys 0.61.2", 6398 ] 6399 6400 [[package]] 6401 name = "tokio-macros" 6402 - version = "2.6.0" 6403 source = "registry+https://github.com/rust-lang/crates.io-index" 6404 - checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" 6405 dependencies = [ 6406 "proc-macro2", 6407 "quote", 6408 - "syn 2.0.114", 6409 ] 6410 6411 [[package]] 6412 name = "tokio-rustls" 6413 - version = "0.26.4" 6414 source = "registry+https://github.com/rust-lang/crates.io-index" 6415 - checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" 6416 dependencies = [ 6417 "rustls", 6418 "tokio", ··· 6420 6421 [[package]] 6422 name = "tokio-stream" 6423 - version = "0.1.18" 6424 source = "registry+https://github.com/rust-lang/crates.io-index" 6425 - checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" 6426 dependencies = [ 6427 "futures-core", 6428 "pin-project-lite", ··· 6431 ] 6432 6433 [[package]] 6434 - name = "tokio-tar" 6435 - version = "0.3.1" 6436 - source = "registry+https://github.com/rust-lang/crates.io-index" 6437 - checksum = "9d5714c010ca3e5c27114c1cdeb9d14641ace49874aa5626d7149e47aedace75" 6438 - dependencies = [ 6439 - "filetime", 6440 - "futures-core", 6441 - "libc", 6442 - "redox_syscall 0.3.5", 6443 - "tokio", 6444 - "tokio-stream", 6445 - "xattr", 6446 - ] 6447 - 6448 - [[package]] 6449 name = "tokio-util" 6450 - version = "0.7.18" 6451 source = "registry+https://github.com/rust-lang/crates.io-index" 6452 - checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" 6453 dependencies = [ 6454 "bytes", 6455 "futures-core", ··· 6461 6462 [[package]] 6463 name = "tokio-websockets" 6464 - version = "0.12.3" 6465 source = "registry+https://github.com/rust-lang/crates.io-index" 6466 - checksum = "b1b6348ebfaaecd771cecb69e832961d277f59845d4220a584701f72728152b7" 6467 dependencies = [ 6468 "base64 0.22.1", 6469 "bytes", 6470 "futures-core", 6471 "futures-sink", 6472 - "getrandom 0.3.4", 6473 "http", 6474 "httparse", 6475 "rand 0.9.2", ··· 6498 dependencies = [ 6499 "serde", 6500 "serde_spanned", 6501 - "toml_datetime 0.6.11", 6502 - "toml_edit 0.22.27", 6503 ] 6504 6505 [[package]] ··· 6512 ] 6513 6514 [[package]] 6515 - name = "toml_datetime" 6516 - version = "0.7.5+spec-1.1.0" 6517 - source = "registry+https://github.com/rust-lang/crates.io-index" 6518 - checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" 6519 - dependencies = [ 6520 - "serde_core", 6521 - ] 6522 - 6523 - [[package]] 6524 name = "toml_edit" 6525 version = "0.22.27" 6526 source = "registry+https://github.com/rust-lang/crates.io-index" 6527 checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" 6528 dependencies = [ 6529 - "indexmap 2.13.0", 6530 "serde", 6531 "serde_spanned", 6532 - "toml_datetime 0.6.11", 6533 "toml_write", 6534 "winnow", 6535 ] 6536 6537 [[package]] 6538 - name = "toml_edit" 6539 - version = "0.23.10+spec-1.0.0" 6540 - source = "registry+https://github.com/rust-lang/crates.io-index" 6541 - checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" 6542 - dependencies = [ 6543 - "indexmap 2.13.0", 6544 - "toml_datetime 0.7.5+spec-1.1.0", 6545 - "toml_parser", 6546 - "winnow", 6547 - ] 6548 - 6549 - [[package]] 6550 - name = "toml_parser" 6551 - version = "1.0.6+spec-1.1.0" 6552 - source = "registry+https://github.com/rust-lang/crates.io-index" 6553 - checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" 6554 - dependencies = [ 6555 - "winnow", 6556 - ] 6557 - 6558 - [[package]] 6559 name = "toml_write" 6560 version = "0.1.2" 6561 source = "registry+https://github.com/rust-lang/crates.io-index" 6562 checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" 6563 6564 [[package]] 6565 - name = "tonic" 6566 - version = "0.12.3" 6567 - source = "registry+https://github.com/rust-lang/crates.io-index" 6568 - checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" 6569 - dependencies = [ 6570 - "async-stream", 6571 - "async-trait", 6572 - "axum", 6573 - "base64 0.22.1", 6574 - "bytes", 6575 - "h2", 6576 - "http", 6577 - "http-body", 6578 - "http-body-util", 6579 - "hyper", 6580 - "hyper-timeout", 6581 - "hyper-util", 6582 - "percent-encoding", 6583 - "pin-project", 6584 - "prost", 6585 - "socket2 0.5.10", 6586 - "tokio", 6587 - "tokio-stream", 6588 - "tower 0.4.13", 6589 - "tower-layer", 6590 - "tower-service", 6591 - "tracing", 6592 - ] 6593 - 6594 - [[package]] 6595 - name = "tonic-build" 6596 - version = "0.12.3" 6597 - source = "registry+https://github.com/rust-lang/crates.io-index" 6598 - checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" 6599 - dependencies = [ 6600 - "prettyplease", 6601 - "proc-macro2", 6602 - "prost-build", 6603 - "prost-types", 6604 - "quote", 6605 - "syn 2.0.114", 6606 - ] 6607 - 6608 - [[package]] 6609 name = "tower" 6610 - version = "0.4.13" 6611 - source = "registry+https://github.com/rust-lang/crates.io-index" 6612 - checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" 6613 - dependencies = [ 6614 - "futures-core", 6615 - "futures-util", 6616 - "indexmap 1.9.3", 6617 - "pin-project", 6618 - "pin-project-lite", 6619 - "rand 0.8.5", 6620 - "slab", 6621 - "tokio", 6622 - "tokio-util", 6623 - "tower-layer", 6624 - "tower-service", 6625 - "tracing", 6626 - ] 6627 - 6628 - [[package]] 6629 - name = "tower" 6630 - version = "0.5.3" 6631 source = "registry+https://github.com/rust-lang/crates.io-index" 6632 - checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" 6633 dependencies = [ 6634 "futures-core", 6635 "futures-util", ··· 6642 6643 [[package]] 6644 name = "tower-http" 6645 - version = "0.6.8" 6646 source = "registry+https://github.com/rust-lang/crates.io-index" 6647 - checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" 6648 dependencies = [ 6649 - "bitflags 2.10.0", 6650 "bytes", 6651 "futures-util", 6652 "http", 6653 "http-body", 6654 "iri-string", 6655 "pin-project-lite", 6656 - "tower 0.5.3", 6657 "tower-layer", 6658 "tower-service", 6659 ] ··· 6672 6673 [[package]] 6674 name = "tracing" 6675 - version = "0.1.44" 6676 source = "registry+https://github.com/rust-lang/crates.io-index" 6677 - checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" 6678 dependencies = [ 6679 "log", 6680 "pin-project-lite", ··· 6684 6685 [[package]] 6686 name = "tracing-attributes" 6687 - version = "0.1.31" 6688 source = "registry+https://github.com/rust-lang/crates.io-index" 6689 - checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" 6690 dependencies = [ 6691 "proc-macro2", 6692 "quote", 6693 - "syn 2.0.114", 6694 ] 6695 6696 [[package]] 6697 name = "tracing-core" 6698 - version = "0.1.36" 6699 source = "registry+https://github.com/rust-lang/crates.io-index" 6700 - checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" 6701 dependencies = [ 6702 "once_cell", 6703 "valuable", ··· 6726 6727 [[package]] 6728 name = "tracing-subscriber" 6729 - version = "0.3.22" 6730 source = "registry+https://github.com/rust-lang/crates.io-index" 6731 - checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" 6732 dependencies = [ 6733 "matchers", 6734 "nu-ansi-term", 6735 "once_cell", 6736 - "regex-automata", 6737 "sharded-slab", 6738 "smallvec", 6739 "thread_local", ··· 6750 dependencies = [ 6751 "proc-macro2", 6752 "quote", 6753 - "syn 2.0.114", 6754 ] 6755 6756 [[package]] ··· 6761 6762 [[package]] 6763 name = "triomphe" 6764 - version = "0.1.15" 6765 source = "registry+https://github.com/rust-lang/crates.io-index" 6766 - checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" 6767 6768 [[package]] 6769 name = "try-lock" ··· 6773 6774 [[package]] 6775 name = "typenum" 6776 - version = "1.19.0" 6777 source = "registry+https://github.com/rust-lang/crates.io-index" 6778 - checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" 6779 6780 [[package]] 6781 name = "ucd-parse" ··· 6799 checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" 6800 6801 [[package]] 6802 - name = "uncased" 6803 - version = "0.9.10" 6804 - source = "registry+https://github.com/rust-lang/crates.io-index" 6805 - checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" 6806 - dependencies = [ 6807 - "version_check", 6808 - ] 6809 - 6810 - [[package]] 6811 name = "unicase" 6812 - version = "2.9.0" 6813 source = "registry+https://github.com/rust-lang/crates.io-index" 6814 - checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" 6815 6816 [[package]] 6817 name = "unicode-ident" 6818 - version = "1.0.22" 6819 source = "registry+https://github.com/rust-lang/crates.io-index" 6820 - checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" 6821 6822 [[package]] 6823 name = "unicode-normalization" 6824 - version = "0.1.25" 6825 source = "registry+https://github.com/rust-lang/crates.io-index" 6826 - checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" 6827 dependencies = [ 6828 "tinyvec", 6829 ] 6830 6831 [[package]] 6832 - name = "unicode-segmentation" 6833 - version = "1.12.0" 6834 - source = "registry+https://github.com/rust-lang/crates.io-index" 6835 - checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" 6836 - 6837 - [[package]] 6838 name = "unicode-xid" 6839 version = "0.2.6" 6840 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6883 checksum = "802d2051a700e3ec894c79f80d2705b69d85844dafbbe5d1a92776f8f48b563a" 6884 dependencies = [ 6885 "quote", 6886 - "syn 2.0.114", 6887 ] 6888 6889 [[package]] ··· 6914 "proc-macro2", 6915 "quote", 6916 "serde", 6917 - "syn 2.0.114", 6918 "toml 0.5.11", 6919 "uniffi_meta", 6920 ] ··· 6975 6976 [[package]] 6977 name = "ureq" 6978 - version = "3.1.4" 6979 source = "registry+https://github.com/rust-lang/crates.io-index" 6980 - checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a" 6981 dependencies = [ 6982 "base64 0.22.1", 6983 "flate2", 6984 "log", 6985 "percent-encoding", 6986 "rustls", 6987 "rustls-pki-types", 6988 "ureq-proto", 6989 "utf-8", ··· 6992 6993 [[package]] 6994 name = "ureq-proto" 6995 - version = "0.5.3" 6996 source = "registry+https://github.com/rust-lang/crates.io-index" 6997 - checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" 6998 dependencies = [ 6999 "base64 0.22.1", 7000 "http", ··· 7004 7005 [[package]] 7006 name = "url" 7007 - version = "2.5.8" 7008 source = "registry+https://github.com/rust-lang/crates.io-index" 7009 - checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" 7010 dependencies = [ 7011 "form_urlencoded", 7012 "idna", 7013 "percent-encoding", 7014 "serde", 7015 - "serde_derive", 7016 ] 7017 7018 [[package]] ··· 7039 source = "registry+https://github.com/rust-lang/crates.io-index" 7040 checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" 7041 dependencies = [ 7042 - "getrandom 0.2.17", 7043 "serde", 7044 "wasm-bindgen", 7045 ] ··· 7079 7080 [[package]] 7081 name = "wasi" 7082 - version = "0.14.7+wasi-0.2.4" 7083 source = "registry+https://github.com/rust-lang/crates.io-index" 7084 - checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" 7085 dependencies = [ 7086 - "wasip2", 7087 ] 7088 7089 [[package]] ··· 7097 7098 [[package]] 7099 name = "wasm-bindgen" 7100 - version = "0.2.106" 7101 source = "registry+https://github.com/rust-lang/crates.io-index" 7102 - checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" 7103 dependencies = [ 7104 "cfg-if", 7105 "once_cell", 7106 "rustversion", 7107 "wasm-bindgen-macro", 7108 "wasm-bindgen-shared", 7109 ] 7110 7111 [[package]] 7112 name = "wasm-bindgen-futures" 7113 - version = "0.4.56" 7114 source = "registry+https://github.com/rust-lang/crates.io-index" 7115 - checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" 7116 dependencies = [ 7117 "cfg-if", 7118 "js-sys", ··· 7123 7124 [[package]] 7125 name = "wasm-bindgen-macro" 7126 - version = "0.2.106" 7127 source = "registry+https://github.com/rust-lang/crates.io-index" 7128 - checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" 7129 dependencies = [ 7130 "quote", 7131 "wasm-bindgen-macro-support", ··· 7133 7134 [[package]] 7135 name = "wasm-bindgen-macro-support" 7136 - version = "0.2.106" 7137 source = "registry+https://github.com/rust-lang/crates.io-index" 7138 - checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" 7139 dependencies = [ 7140 - "bumpalo", 7141 "proc-macro2", 7142 "quote", 7143 - "syn 2.0.114", 7144 "wasm-bindgen-shared", 7145 ] 7146 7147 [[package]] 7148 name = "wasm-bindgen-shared" 7149 - version = "0.2.106" 7150 source = "registry+https://github.com/rust-lang/crates.io-index" 7151 - checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" 7152 dependencies = [ 7153 "unicode-ident", 7154 ] ··· 7168 7169 [[package]] 7170 name = "web-sys" 7171 - version = "0.3.83" 7172 source = "registry+https://github.com/rust-lang/crates.io-index" 7173 - checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" 7174 dependencies = [ 7175 "js-sys", 7176 "wasm-bindgen", ··· 7188 7189 [[package]] 7190 name = "webpki-roots" 7191 - version = "1.0.5" 7192 source = "registry+https://github.com/rust-lang/crates.io-index" 7193 - checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" 7194 dependencies = [ 7195 "rustls-pki-types", 7196 ] ··· 7206 7207 [[package]] 7208 name = "widestring" 7209 - version = "1.2.1" 7210 source = "registry+https://github.com/rust-lang/crates.io-index" 7211 - checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" 7212 7213 [[package]] 7214 name = "winapi" ··· 7228 7229 [[package]] 7230 name = "winapi-util" 7231 - version = "0.1.11" 7232 source = "registry+https://github.com/rust-lang/crates.io-index" 7233 - checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" 7234 dependencies = [ 7235 - "windows-sys 0.61.2", 7236 ] 7237 7238 [[package]] ··· 7247 source = "registry+https://github.com/rust-lang/crates.io-index" 7248 checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" 7249 dependencies = [ 7250 - "windows-collections 0.2.0", 7251 - "windows-core 0.61.2", 7252 - "windows-future 0.2.1", 7253 "windows-link 0.1.3", 7254 - "windows-numerics 0.2.0", 7255 - ] 7256 - 7257 - [[package]] 7258 - name = "windows" 7259 - version = "0.62.2" 7260 - source = "registry+https://github.com/rust-lang/crates.io-index" 7261 - checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" 7262 - dependencies = [ 7263 - "windows-collections 0.3.2", 7264 - "windows-core 0.62.2", 7265 - "windows-future 0.3.2", 7266 - "windows-numerics 0.3.1", 7267 ] 7268 7269 [[package]] ··· 7272 source = "registry+https://github.com/rust-lang/crates.io-index" 7273 checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" 7274 dependencies = [ 7275 - "windows-core 0.61.2", 7276 - ] 7277 - 7278 - [[package]] 7279 - name = "windows-collections" 7280 - version = "0.3.2" 7281 - source = "registry+https://github.com/rust-lang/crates.io-index" 7282 - checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" 7283 - dependencies = [ 7284 - "windows-core 0.62.2", 7285 ] 7286 7287 [[package]] ··· 7293 "windows-implement", 7294 "windows-interface", 7295 "windows-link 0.1.3", 7296 - "windows-result 0.3.4", 7297 - "windows-strings 0.4.2", 7298 - ] 7299 - 7300 - [[package]] 7301 - name = "windows-core" 7302 - version = "0.62.2" 7303 - source = "registry+https://github.com/rust-lang/crates.io-index" 7304 - checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" 7305 - dependencies = [ 7306 - "windows-implement", 7307 - "windows-interface", 7308 - "windows-link 0.2.1", 7309 - "windows-result 0.4.1", 7310 - "windows-strings 0.5.1", 7311 ] 7312 7313 [[package]] ··· 7316 source = "registry+https://github.com/rust-lang/crates.io-index" 7317 checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" 7318 dependencies = [ 7319 - "windows-core 0.61.2", 7320 "windows-link 0.1.3", 7321 - "windows-threading 0.1.0", 7322 - ] 7323 - 7324 - [[package]] 7325 - name = "windows-future" 7326 - version = "0.3.2" 7327 - source = "registry+https://github.com/rust-lang/crates.io-index" 7328 - checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" 7329 - dependencies = [ 7330 - "windows-core 0.62.2", 7331 - "windows-link 0.2.1", 7332 - "windows-threading 0.2.1", 7333 ] 7334 7335 [[package]] 7336 name = "windows-implement" 7337 - version = "0.60.2" 7338 source = "registry+https://github.com/rust-lang/crates.io-index" 7339 - checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" 7340 dependencies = [ 7341 "proc-macro2", 7342 "quote", 7343 - "syn 2.0.114", 7344 ] 7345 7346 [[package]] 7347 name = "windows-interface" 7348 - version = "0.59.3" 7349 source = "registry+https://github.com/rust-lang/crates.io-index" 7350 - checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" 7351 dependencies = [ 7352 "proc-macro2", 7353 "quote", 7354 - "syn 2.0.114", 7355 ] 7356 7357 [[package]] ··· 7362 7363 [[package]] 7364 name = "windows-link" 7365 - version = "0.2.1" 7366 source = "registry+https://github.com/rust-lang/crates.io-index" 7367 - checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 7368 7369 [[package]] 7370 name = "windows-numerics" ··· 7372 source = "registry+https://github.com/rust-lang/crates.io-index" 7373 checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" 7374 dependencies = [ 7375 - "windows-core 0.61.2", 7376 "windows-link 0.1.3", 7377 ] 7378 7379 [[package]] 7380 - name = "windows-numerics" 7381 - version = "0.3.1" 7382 - source = "registry+https://github.com/rust-lang/crates.io-index" 7383 - checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" 7384 - dependencies = [ 7385 - "windows-core 0.62.2", 7386 - "windows-link 0.2.1", 7387 - ] 7388 - 7389 - [[package]] 7390 name = "windows-result" 7391 version = "0.3.4" 7392 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7396 ] 7397 7398 [[package]] 7399 - name = "windows-result" 7400 - version = "0.4.1" 7401 - source = "registry+https://github.com/rust-lang/crates.io-index" 7402 - checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" 7403 - dependencies = [ 7404 - "windows-link 0.2.1", 7405 - ] 7406 - 7407 - [[package]] 7408 name = "windows-strings" 7409 version = "0.4.2" 7410 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7414 ] 7415 7416 [[package]] 7417 - name = "windows-strings" 7418 - version = "0.5.1" 7419 - source = "registry+https://github.com/rust-lang/crates.io-index" 7420 - checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" 7421 - dependencies = [ 7422 - "windows-link 0.2.1", 7423 - ] 7424 - 7425 - [[package]] 7426 name = "windows-sys" 7427 version = "0.48.0" 7428 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7450 ] 7451 7452 [[package]] 7453 - name = "windows-sys" 7454 - version = "0.60.2" 7455 - source = "registry+https://github.com/rust-lang/crates.io-index" 7456 - checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 7457 - dependencies = [ 7458 - "windows-targets 0.53.5", 7459 - ] 7460 - 7461 - [[package]] 7462 - name = "windows-sys" 7463 - version = "0.61.2" 7464 - source = "registry+https://github.com/rust-lang/crates.io-index" 7465 - checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 7466 - dependencies = [ 7467 - "windows-link 0.2.1", 7468 - ] 7469 - 7470 - [[package]] 7471 name = "windows-targets" 7472 version = "0.48.5" 7473 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7491 "windows_aarch64_gnullvm 0.52.6", 7492 "windows_aarch64_msvc 0.52.6", 7493 "windows_i686_gnu 0.52.6", 7494 - "windows_i686_gnullvm 0.52.6", 7495 "windows_i686_msvc 0.52.6", 7496 "windows_x86_64_gnu 0.52.6", 7497 "windows_x86_64_gnullvm 0.52.6", ··· 7499 ] 7500 7501 [[package]] 7502 - name = "windows-targets" 7503 - version = "0.53.5" 7504 - source = "registry+https://github.com/rust-lang/crates.io-index" 7505 - checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" 7506 - dependencies = [ 7507 - "windows-link 0.2.1", 7508 - "windows_aarch64_gnullvm 0.53.1", 7509 - "windows_aarch64_msvc 0.53.1", 7510 - "windows_i686_gnu 0.53.1", 7511 - "windows_i686_gnullvm 0.53.1", 7512 - "windows_i686_msvc 0.53.1", 7513 - "windows_x86_64_gnu 0.53.1", 7514 - "windows_x86_64_gnullvm 0.53.1", 7515 - "windows_x86_64_msvc 0.53.1", 7516 - ] 7517 - 7518 - [[package]] 7519 name = "windows-threading" 7520 version = "0.1.0" 7521 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7525 ] 7526 7527 [[package]] 7528 - name = "windows-threading" 7529 - version = "0.2.1" 7530 - source = "registry+https://github.com/rust-lang/crates.io-index" 7531 - checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" 7532 - dependencies = [ 7533 - "windows-link 0.2.1", 7534 - ] 7535 - 7536 - [[package]] 7537 name = "windows_aarch64_gnullvm" 7538 version = "0.48.5" 7539 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7546 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 7547 7548 [[package]] 7549 - name = "windows_aarch64_gnullvm" 7550 - version = "0.53.1" 7551 - source = "registry+https://github.com/rust-lang/crates.io-index" 7552 - checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" 7553 - 7554 - [[package]] 7555 name = "windows_aarch64_msvc" 7556 version = "0.48.5" 7557 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7564 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 7565 7566 [[package]] 7567 - name = "windows_aarch64_msvc" 7568 - version = "0.53.1" 7569 - source = "registry+https://github.com/rust-lang/crates.io-index" 7570 - checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" 7571 - 7572 - [[package]] 7573 name = "windows_i686_gnu" 7574 version = "0.48.5" 7575 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7580 version = "0.52.6" 7581 source = "registry+https://github.com/rust-lang/crates.io-index" 7582 checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 7583 - 7584 - [[package]] 7585 - name = "windows_i686_gnu" 7586 - version = "0.53.1" 7587 - source = "registry+https://github.com/rust-lang/crates.io-index" 7588 - checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" 7589 7590 [[package]] 7591 name = "windows_i686_gnullvm" ··· 7594 checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 7595 7596 [[package]] 7597 - name = "windows_i686_gnullvm" 7598 - version = "0.53.1" 7599 - source = "registry+https://github.com/rust-lang/crates.io-index" 7600 - checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" 7601 - 7602 - [[package]] 7603 name = "windows_i686_msvc" 7604 version = "0.48.5" 7605 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7612 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 7613 7614 [[package]] 7615 - name = "windows_i686_msvc" 7616 - version = "0.53.1" 7617 - source = "registry+https://github.com/rust-lang/crates.io-index" 7618 - checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" 7619 - 7620 - [[package]] 7621 name = "windows_x86_64_gnu" 7622 version = "0.48.5" 7623 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7630 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 7631 7632 [[package]] 7633 - name = "windows_x86_64_gnu" 7634 - version = "0.53.1" 7635 - source = "registry+https://github.com/rust-lang/crates.io-index" 7636 - checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" 7637 - 7638 - [[package]] 7639 name = "windows_x86_64_gnullvm" 7640 version = "0.48.5" 7641 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7648 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 7649 7650 [[package]] 7651 - name = "windows_x86_64_gnullvm" 7652 - version = "0.53.1" 7653 - source = "registry+https://github.com/rust-lang/crates.io-index" 7654 - checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" 7655 - 7656 - [[package]] 7657 name = "windows_x86_64_msvc" 7658 version = "0.48.5" 7659 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7664 version = "0.52.6" 7665 source = "registry+https://github.com/rust-lang/crates.io-index" 7666 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 7667 - 7668 - [[package]] 7669 - name = "windows_x86_64_msvc" 7670 - version = "0.53.1" 7671 - source = "registry+https://github.com/rust-lang/crates.io-index" 7672 - checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" 7673 7674 [[package]] 7675 name = "winnow" 7676 - version = "0.7.14" 7677 source = "registry+https://github.com/rust-lang/crates.io-index" 7678 - checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" 7679 dependencies = [ 7680 "memchr", 7681 ] ··· 7696 source = "registry+https://github.com/rust-lang/crates.io-index" 7697 checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" 7698 dependencies = [ 7699 - "bitflags 2.10.0", 7700 ] 7701 7702 [[package]] 7703 name = "wmi" 7704 - version = "0.17.3" 7705 source = "registry+https://github.com/rust-lang/crates.io-index" 7706 - checksum = "120d8c2b6a7c96c27bf4a7947fd7f02d73ca7f5958b8bd72a696e46cb5521ee6" 7707 dependencies = [ 7708 "chrono", 7709 "futures", 7710 "log", 7711 "serde", 7712 - "thiserror 2.0.17", 7713 - "windows 0.62.2", 7714 - "windows-core 0.62.2", 7715 ] 7716 7717 [[package]] 7718 name = "writeable" 7719 - version = "0.6.2" 7720 source = "registry+https://github.com/rust-lang/crates.io-index" 7721 - checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" 7722 7723 [[package]] 7724 name = "ws_stream_wasm" ··· 7733 "pharos", 7734 "rustc_version", 7735 "send_wrapper", 7736 - "thiserror 2.0.17", 7737 "wasm-bindgen", 7738 "wasm-bindgen-futures", 7739 "web-sys", ··· 7741 7742 [[package]] 7743 name = "wstd" 7744 - version = "0.5.3" 7745 source = "registry+https://github.com/rust-lang/crates.io-index" 7746 - checksum = "6515b13373b9dfbbe62e4426972253a15b74d93b1e2e95f92bbb2801c239a1d3" 7747 dependencies = [ 7748 - "futures-core", 7749 "http", 7750 "itoa", 7751 "pin-project-lite", 7752 "serde", 7753 "serde_json", 7754 "slab", 7755 - "wasi 0.14.7+wasi-0.2.4", 7756 "wstd-macro", 7757 ] 7758 7759 [[package]] 7760 name = "wstd-macro" 7761 - version = "0.5.3" 7762 source = "registry+https://github.com/rust-lang/crates.io-index" 7763 - checksum = "23d1758ed5cdf081802c60bc000a9cb90db8bcdf140fa8a7251a22b32af37d7b" 7764 dependencies = [ 7765 "quote", 7766 - "syn 2.0.114", 7767 ] 7768 7769 [[package]] ··· 7812 ] 7813 7814 [[package]] 7815 - name = "xattr" 7816 - version = "1.6.1" 7817 - source = "registry+https://github.com/rust-lang/crates.io-index" 7818 - checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" 7819 - dependencies = [ 7820 - "libc", 7821 - "rustix 1.1.3", 7822 - ] 7823 - 7824 - [[package]] 7825 name = "xml-no-std" 7826 version = "0.8.26" 7827 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7829 7830 [[package]] 7831 name = "xml-rs" 7832 - version = "0.8.28" 7833 source = "registry+https://github.com/rust-lang/crates.io-index" 7834 - checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" 7835 7836 [[package]] 7837 name = "xmltree" ··· 7843 ] 7844 7845 [[package]] 7846 - name = "yansi" 7847 - version = "1.0.1" 7848 - source = "registry+https://github.com/rust-lang/crates.io-index" 7849 - checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" 7850 - 7851 - [[package]] 7852 name = "yasna" 7853 version = "0.5.2" 7854 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7859 7860 [[package]] 7861 name = "yoke" 7862 - version = "0.8.1" 7863 source = "registry+https://github.com/rust-lang/crates.io-index" 7864 - checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" 7865 dependencies = [ 7866 "stable_deref_trait", 7867 "yoke-derive", 7868 "zerofrom", ··· 7870 7871 [[package]] 7872 name = "yoke-derive" 7873 - version = "0.8.1" 7874 source = "registry+https://github.com/rust-lang/crates.io-index" 7875 - checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" 7876 dependencies = [ 7877 "proc-macro2", 7878 "quote", 7879 - "syn 2.0.114", 7880 "synstructure", 7881 ] 7882 ··· 7888 7889 [[package]] 7890 name = "zerocopy" 7891 - version = "0.8.33" 7892 source = "registry+https://github.com/rust-lang/crates.io-index" 7893 - checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" 7894 dependencies = [ 7895 "zerocopy-derive", 7896 ] 7897 7898 [[package]] 7899 name = "zerocopy-derive" 7900 - version = "0.8.33" 7901 source = "registry+https://github.com/rust-lang/crates.io-index" 7902 - checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" 7903 dependencies = [ 7904 "proc-macro2", 7905 "quote", 7906 - "syn 2.0.114", 7907 ] 7908 7909 [[package]] ··· 7923 dependencies = [ 7924 "proc-macro2", 7925 "quote", 7926 - "syn 2.0.114", 7927 "synstructure", 7928 ] 7929 7930 [[package]] 7931 name = "zeroize" 7932 - version = "1.8.2" 7933 source = "registry+https://github.com/rust-lang/crates.io-index" 7934 - checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" 7935 dependencies = [ 7936 "zeroize_derive", 7937 ] 7938 7939 [[package]] 7940 name = "zeroize_derive" 7941 - version = "1.4.3" 7942 source = "registry+https://github.com/rust-lang/crates.io-index" 7943 - checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" 7944 dependencies = [ 7945 "proc-macro2", 7946 "quote", 7947 - "syn 2.0.114", 7948 ] 7949 7950 [[package]] 7951 name = "zerotrie" 7952 - version = "0.2.3" 7953 source = "registry+https://github.com/rust-lang/crates.io-index" 7954 - checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" 7955 dependencies = [ 7956 "displaydoc", 7957 "yoke", ··· 7960 7961 [[package]] 7962 name = "zerovec" 7963 - version = "0.11.5" 7964 source = "registry+https://github.com/rust-lang/crates.io-index" 7965 - checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" 7966 dependencies = [ 7967 "yoke", 7968 "zerofrom", ··· 7971 7972 [[package]] 7973 name = "zerovec-derive" 7974 - version = "0.11.2" 7975 source = "registry+https://github.com/rust-lang/crates.io-index" 7976 - checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" 7977 dependencies = [ 7978 "proc-macro2", 7979 "quote", 7980 - "syn 2.0.114", 7981 ] 7982 7983 [[package]] ··· 7988 dependencies = [ 7989 "arbitrary", 7990 "crc32fast", 7991 - "indexmap 2.13.0", 7992 "memchr", 7993 ] 7994 - 7995 - [[package]] 7996 - name = "zmij" 7997 - version = "1.0.14" 7998 - source = "registry+https://github.com/rust-lang/crates.io-index" 7999 - checksum = "bd8f3f50b848df28f887acb68e41201b5aea6bc8a8dacc00fb40635ff9a72fea"
··· 37 38 [[package]] 39 name = "addr2line" 40 + version = "0.24.2" 41 source = "registry+https://github.com/rust-lang/crates.io-index" 42 + checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 43 dependencies = [ 44 "gimli", 45 ] ··· 62 ] 63 64 [[package]] 65 name = "aho-corasick" 66 + version = "1.1.3" 67 source = "registry+https://github.com/rust-lang/crates.io-index" 68 + checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 69 dependencies = [ 70 "memchr", 71 ] ··· 87 88 [[package]] 89 name = "anyhow" 90 + version = "1.0.99" 91 source = "registry+https://github.com/rust-lang/crates.io-index" 92 + checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" 93 dependencies = [ 94 "backtrace", 95 ] ··· 105 106 [[package]] 107 name = "archery" 108 + version = "1.2.1" 109 source = "registry+https://github.com/rust-lang/crates.io-index" 110 + checksum = "eae2ed21cd55021f05707a807a5fc85695dafb98832921f6cfa06db67ca5b869" 111 dependencies = [ 112 "triomphe", 113 ] ··· 147 "proc-macro2", 148 "quote", 149 "serde", 150 + "syn 2.0.105", 151 ] 152 153 [[package]] ··· 189 dependencies = [ 190 "proc-macro2", 191 "quote", 192 + "syn 2.0.105", 193 "synstructure", 194 ] 195 ··· 201 dependencies = [ 202 "proc-macro2", 203 "quote", 204 + "syn 2.0.105", 205 ] 206 207 [[package]] 208 name = "async-compat" 209 + version = "0.2.4" 210 source = "registry+https://github.com/rust-lang/crates.io-index" 211 + checksum = "7bab94bde396a3f7b4962e396fdad640e241ed797d4d8d77fc8c237d14c58fc0" 212 dependencies = [ 213 "futures-core", 214 "futures-io", ··· 225 dependencies = [ 226 "proc-macro2", 227 "quote", 228 + "syn 2.0.105", 229 ] 230 231 [[package]] ··· 236 dependencies = [ 237 "proc-macro2", 238 "quote", 239 + "syn 2.0.105", 240 ] 241 242 [[package]] 243 + name = "async-task" 244 + version = "4.7.1" 245 source = "registry+https://github.com/rust-lang/crates.io-index" 246 + checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" 247 248 [[package]] 249 name = "async-trait" ··· 253 dependencies = [ 254 "proc-macro2", 255 "quote", 256 + "syn 2.0.105", 257 ] 258 259 [[package]] ··· 265 "futures", 266 "pharos", 267 "rustc_version", 268 ] 269 270 [[package]] ··· 307 checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 308 309 [[package]] 310 name = "backon" 311 + version = "1.5.2" 312 source = "registry+https://github.com/rust-lang/crates.io-index" 313 + checksum = "592277618714fbcecda9a02ba7a8781f319d26532a88553bbacc77ba5d2b3a8d" 314 dependencies = [ 315 "fastrand", 316 "gloo-timers", ··· 319 320 [[package]] 321 name = "backtrace" 322 + version = "0.3.75" 323 source = "registry+https://github.com/rust-lang/crates.io-index" 324 + checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" 325 dependencies = [ 326 "addr2line", 327 "cfg-if", ··· 329 "miniz_oxide", 330 "object", 331 "rustc-demangle", 332 + "windows-targets 0.52.6", 333 ] 334 335 [[package]] 336 name = "base16ct" 337 + version = "0.3.0" 338 source = "registry+https://github.com/rust-lang/crates.io-index" 339 + checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" 340 341 [[package]] 342 name = "base32" ··· 358 359 [[package]] 360 name = "base64ct" 361 + version = "1.8.0" 362 source = "registry+https://github.com/rust-lang/crates.io-index" 363 + checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" 364 365 [[package]] 366 name = "basic-toml" ··· 392 393 [[package]] 394 name = "bitflags" 395 + version = "2.9.1" 396 source = "registry+https://github.com/rust-lang/crates.io-index" 397 + checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 398 dependencies = [ 399 + "serde", 400 ] 401 402 [[package]] ··· 423 424 [[package]] 425 name = "blake3" 426 + version = "1.8.2" 427 source = "registry+https://github.com/rust-lang/crates.io-index" 428 + checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" 429 dependencies = [ 430 "arrayref", 431 "arrayvec", 432 "cc", 433 "cfg-if", 434 "constant_time_eq", 435 ] 436 437 [[package]] ··· 445 446 [[package]] 447 name = "block-buffer" 448 + version = "0.11.0-rc.5" 449 source = "registry+https://github.com/rust-lang/crates.io-index" 450 + checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" 451 dependencies = [ 452 "hybrid-array", 453 "zeroize", 454 ] 455 456 [[package]] 457 name = "bounded-integer" 458 version = "0.5.8" 459 source = "registry+https://github.com/rust-lang/crates.io-index" 460 checksum = "102dbef1187b1893e6dfe05a774e79fd52265f49f214f6879c8ff49f52c8188b" 461 462 [[package]] 463 name = "btparse" 464 version = "0.2.0" 465 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 491 492 [[package]] 493 name = "bumpalo" 494 + version = "3.19.0" 495 source = "registry+https://github.com/rust-lang/crates.io-index" 496 + checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 497 498 [[package]] 499 name = "byteorder" ··· 512 513 [[package]] 514 name = "bytes" 515 + version = "1.10.1" 516 source = "registry+https://github.com/rust-lang/crates.io-index" 517 + checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 518 dependencies = [ 519 "serde", 520 ] ··· 546 "ed25519-dalek 2.2.0", 547 "env_logger", 548 "extfmt", 549 + "getrandom 0.2.16", 550 "hex", 551 "hex-literal", 552 "http", ··· 571 "quick-xml", 572 "rand 0.8.5", 573 "rand_chacha 0.3.1", 574 + "rand_core 0.9.3", 575 "range-set", 576 "rasn", 577 "rasn-cms", ··· 596 "spki 0.7.3", 597 "static-iref", 598 "tempfile", 599 + "thiserror 2.0.16", 600 "toml 0.8.23", 601 "treeline", 602 "ureq", ··· 606 "wasm-bindgen-futures", 607 "web-sys", 608 "web-time", 609 + "windows-core", 610 "wstd", 611 "x509-certificate", 612 "x509-parser", ··· 641 "ed25519-dalek 2.2.0", 642 "env_logger", 643 "extfmt", 644 + "getrandom 0.2.16", 645 "hex", 646 "hex-literal", 647 "http", ··· 666 "quick-xml", 667 "rand 0.8.5", 668 "rand_chacha 0.3.1", 669 + "rand_core 0.9.3", 670 "range-set", 671 "rasn", 672 "rasn-cms", ··· 690 "spki 0.7.3", 691 "static-iref", 692 "tempfile", 693 + "thiserror 2.0.16", 694 "toml 0.8.23", 695 "treeline", 696 "ureq", ··· 700 "wasm-bindgen-futures", 701 "web-sys", 702 "web-time", 703 + "windows-core", 704 "wstd", 705 "x509-certificate", 706 "x509-parser", ··· 710 711 [[package]] 712 name = "camino" 713 + version = "1.1.11" 714 source = "registry+https://github.com/rust-lang/crates.io-index" 715 + checksum = "5d07aa9a93b00c76f71bc35d598bed923f6d4f3a9ca5c24b7737ae1a292841c0" 716 dependencies = [ 717 + "serde", 718 ] 719 720 [[package]] ··· 742 743 [[package]] 744 name = "cc" 745 + version = "1.2.32" 746 source = "registry+https://github.com/rust-lang/crates.io-index" 747 + checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e" 748 dependencies = [ 749 "shlex", 750 ] 751 ··· 760 761 [[package]] 762 name = "cfg-if" 763 + version = "1.0.1" 764 source = "registry+https://github.com/rust-lang/crates.io-index" 765 + checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" 766 767 [[package]] 768 name = "cfg_aliases" ··· 784 785 [[package]] 786 name = "chrono" 787 + version = "0.4.42" 788 source = "registry+https://github.com/rust-lang/crates.io-index" 789 + checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" 790 dependencies = [ 791 "iana-time-zone", 792 "js-sys", 793 "num-traits", 794 "serde", 795 "wasm-bindgen", 796 + "windows-link 0.2.0", 797 ] 798 799 [[package]] ··· 820 checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 821 dependencies = [ 822 "ciborium-io", 823 + "half 2.6.0", 824 ] 825 826 [[package]] ··· 829 source = "registry+https://github.com/rust-lang/crates.io-index" 830 checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" 831 dependencies = [ 832 + "block-buffer 0.11.0-rc.5", 833 "crypto-common 0.2.0-rc.4", 834 "inout", 835 "zeroize", 836 ] 837 838 [[package]] 839 name = "cobs" 840 version = "0.3.0" 841 source = "registry+https://github.com/rust-lang/crates.io-index" 842 checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" 843 dependencies = [ 844 + "thiserror 2.0.16", 845 ] 846 847 [[package]] 848 name = "color-backtrace" 849 + version = "0.7.0" 850 source = "registry+https://github.com/rust-lang/crates.io-index" 851 + checksum = "2123a5984bd52ca861c66f66a9ab9883b27115c607f801f86c1bc2a84eb69f0f" 852 dependencies = [ 853 "backtrace", 854 "btparse", ··· 884 885 [[package]] 886 name = "const-hex" 887 + version = "1.16.0" 888 source = "registry+https://github.com/rust-lang/crates.io-index" 889 + checksum = "b6407bff74dea37e0fa3dc1c1c974e5d46405f0c987bf9997a0762adce71eda6" 890 dependencies = [ 891 "cfg-if", 892 "cpufeatures", ··· 902 903 [[package]] 904 name = "const-oid" 905 + version = "0.10.1" 906 source = "registry+https://github.com/rust-lang/crates.io-index" 907 + checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" 908 909 [[package]] 910 name = "const-random" ··· 921 source = "registry+https://github.com/rust-lang/crates.io-index" 922 checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 923 dependencies = [ 924 + "getrandom 0.2.16", 925 "once_cell", 926 "tiny-keccak", 927 ] 928 929 [[package]] 930 name = "constant_time_eq" 931 + version = "0.3.1" 932 source = "registry+https://github.com/rust-lang/crates.io-index" 933 + checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" 934 935 [[package]] 936 name = "conv" ··· 942 ] 943 944 [[package]] 945 name = "cordyceps" 946 version = "0.3.4" 947 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 962 ] 963 964 [[package]] 965 name = "core-foundation-sys" 966 version = "0.8.7" 967 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 988 989 [[package]] 990 name = "crc" 991 + version = "3.3.0" 992 source = "registry+https://github.com/rust-lang/crates.io-index" 993 + checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" 994 dependencies = [ 995 "crc-catalog", 996 ] ··· 1048 1049 [[package]] 1050 name = "crypto-common" 1051 + version = "0.1.6" 1052 source = "registry+https://github.com/rust-lang/crates.io-index" 1053 + checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 1054 dependencies = [ 1055 "generic-array", 1056 "typenum", ··· 1063 checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" 1064 dependencies = [ 1065 "hybrid-array", 1066 + "rand_core 0.9.3", 1067 ] 1068 1069 [[package]] ··· 1125 "curve25519-dalek-derive", 1126 "digest 0.11.0-rc.3", 1127 "fiat-crypto 0.3.0", 1128 + "rand_core 0.9.3", 1129 "rustc_version", 1130 "serde", 1131 "subtle", ··· 1140 dependencies = [ 1141 "proc-macro2", 1142 "quote", 1143 + "syn 2.0.105", 1144 ] 1145 1146 [[package]] ··· 1170 "proc-macro2", 1171 "quote", 1172 "strsim", 1173 + "syn 2.0.105", 1174 ] 1175 1176 [[package]] ··· 1181 dependencies = [ 1182 "darling_core", 1183 "quote", 1184 + "syn 2.0.105", 1185 ] 1186 1187 [[package]] 1188 name = "data-encoding" 1189 + version = "2.9.0" 1190 source = "registry+https://github.com/rust-lang/crates.io-index" 1191 + checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" 1192 1193 [[package]] 1194 name = "delegate" ··· 1214 1215 [[package]] 1216 name = "der" 1217 + version = "0.8.0-rc.9" 1218 source = "registry+https://github.com/rust-lang/crates.io-index" 1219 + checksum = "e9d8dd2f26c86b27a2a8ea2767ec7f9df7a89516e4794e54ac01ee618dda3aa4" 1220 dependencies = [ 1221 + "const-oid 0.10.1", 1222 "der_derive", 1223 + "pem-rfc7468 1.0.0-rc.3", 1224 "zeroize", 1225 ] 1226 ··· 1246 dependencies = [ 1247 "proc-macro2", 1248 "quote", 1249 + "syn 2.0.105", 1250 ] 1251 1252 [[package]] 1253 name = "deranged" 1254 + version = "0.4.0" 1255 source = "registry+https://github.com/rust-lang/crates.io-index" 1256 + checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" 1257 dependencies = [ 1258 "powerfmt", 1259 + "serde", 1260 ] 1261 1262 [[package]] ··· 1267 dependencies = [ 1268 "proc-macro2", 1269 "quote", 1270 + "syn 2.0.105", 1271 ] 1272 1273 [[package]] ··· 1281 1282 [[package]] 1283 name = "derive_more" 1284 + version = "2.0.1" 1285 source = "registry+https://github.com/rust-lang/crates.io-index" 1286 + checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" 1287 dependencies = [ 1288 + "derive_more-impl 2.0.1", 1289 ] 1290 1291 [[package]] ··· 1296 dependencies = [ 1297 "proc-macro2", 1298 "quote", 1299 + "syn 2.0.105", 1300 "unicode-xid", 1301 ] 1302 1303 [[package]] 1304 name = "derive_more-impl" 1305 + version = "2.0.1" 1306 source = "registry+https://github.com/rust-lang/crates.io-index" 1307 + checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" 1308 dependencies = [ 1309 "proc-macro2", 1310 "quote", 1311 + "syn 2.0.105", 1312 "unicode-xid", 1313 ] 1314 ··· 1326 dependencies = [ 1327 "block-buffer 0.10.4", 1328 "const-oid 0.9.6", 1329 + "crypto-common 0.1.6", 1330 "subtle", 1331 ] 1332 ··· 1336 source = "registry+https://github.com/rust-lang/crates.io-index" 1337 checksum = "dac89f8a64533a9b0eaa73a68e424db0fb1fd6271c74cc0125336a05f090568d" 1338 dependencies = [ 1339 + "block-buffer 0.11.0-rc.5", 1340 "crypto-common 0.2.0-rc.4", 1341 ] 1342 ··· 1348 dependencies = [ 1349 "proc-macro2", 1350 "quote", 1351 + "syn 2.0.105", 1352 ] 1353 1354 [[package]] ··· 1372 ] 1373 1374 [[package]] 1375 name = "document-features" 1376 + version = "0.2.11" 1377 source = "registry+https://github.com/rust-lang/crates.io-index" 1378 + checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" 1379 dependencies = [ 1380 "litrs", 1381 ] 1382 1383 [[package]] 1384 name = "dyn-clone" 1385 version = "1.0.20" 1386 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1398 1399 [[package]] 1400 name = "ed25519" 1401 + version = "3.0.0-rc.1" 1402 source = "registry+https://github.com/rust-lang/crates.io-index" 1403 + checksum = "9ef49c0b20c0ad088893ad2a790a29c06a012b3f05bcfc66661fd22a94b32129" 1404 dependencies = [ 1405 + "pkcs8 0.11.0-rc.7", 1406 "serde", 1407 + "signature 3.0.0-rc.4", 1408 ] 1409 1410 [[package]] ··· 1430 checksum = "ad207ed88a133091f83224265eac21109930db09bedcad05d5252f2af2de20a1" 1431 dependencies = [ 1432 "curve25519-dalek 5.0.0-pre.1", 1433 + "ed25519 3.0.0-rc.1", 1434 + "rand_core 0.9.3", 1435 "serde", 1436 "sha2 0.11.0-rc.2", 1437 + "signature 3.0.0-rc.4", 1438 "subtle", 1439 "zeroize", 1440 ] ··· 1466 "heck", 1467 "proc-macro2", 1468 "quote", 1469 + "syn 2.0.105", 1470 ] 1471 1472 [[package]] ··· 1486 dependencies = [ 1487 "proc-macro2", 1488 "quote", 1489 + "syn 2.0.105", 1490 ] 1491 1492 [[package]] ··· 1515 checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" 1516 dependencies = [ 1517 "libc", 1518 + "windows-sys 0.59.0", 1519 ] 1520 1521 [[package]] ··· 1561 checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" 1562 1563 [[package]] 1564 name = "fixedbitset" 1565 version = "0.5.7" 1566 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1568 1569 [[package]] 1570 name = "flate2" 1571 + version = "1.1.2" 1572 source = "registry+https://github.com/rust-lang/crates.io-index" 1573 + checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" 1574 dependencies = [ 1575 "crc32fast", 1576 "miniz_oxide", ··· 1584 1585 [[package]] 1586 name = "foldhash" 1587 version = "0.2.0" 1588 source = "registry+https://github.com/rust-lang/crates.io-index" 1589 checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" ··· 1605 1606 [[package]] 1607 name = "form_urlencoded" 1608 + version = "1.2.1" 1609 source = "registry+https://github.com/rust-lang/crates.io-index" 1610 + checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 1611 dependencies = [ 1612 "percent-encoding", 1613 ] ··· 1622 ] 1623 1624 [[package]] 1625 name = "funty" 1626 version = "2.0.0" 1627 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1667 1668 [[package]] 1669 name = "futures-concurrency" 1670 + version = "7.6.3" 1671 source = "registry+https://github.com/rust-lang/crates.io-index" 1672 + checksum = "0eb68017df91f2e477ed4bea586c59eaecaa47ed885a770d0444e21e62572cd2" 1673 dependencies = [ 1674 "fixedbitset", 1675 + "futures-buffered", 1676 "futures-core", 1677 "futures-lite", 1678 "pin-project", 1679 + "slab", 1680 "smallvec", 1681 ] 1682 ··· 1724 dependencies = [ 1725 "proc-macro2", 1726 "quote", 1727 + "syn 2.0.105", 1728 ] 1729 1730 [[package]] ··· 1759 1760 [[package]] 1761 name = "generator" 1762 + version = "0.8.5" 1763 source = "registry+https://github.com/rust-lang/crates.io-index" 1764 + checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" 1765 dependencies = [ 1766 "cc", 1767 "cfg-if", 1768 "libc", 1769 "log", 1770 "rustversion", 1771 + "windows", 1772 ] 1773 1774 [[package]] ··· 1783 1784 [[package]] 1785 name = "getrandom" 1786 + version = "0.2.16" 1787 source = "registry+https://github.com/rust-lang/crates.io-index" 1788 + checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 1789 dependencies = [ 1790 "cfg-if", 1791 "js-sys", ··· 1796 1797 [[package]] 1798 name = "getrandom" 1799 + version = "0.3.3" 1800 source = "registry+https://github.com/rust-lang/crates.io-index" 1801 + checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 1802 dependencies = [ 1803 "cfg-if", 1804 "js-sys", 1805 "libc", 1806 "r-efi", 1807 + "wasi 0.14.2+wasi-0.2.4", 1808 "wasm-bindgen", 1809 ] 1810 1811 [[package]] 1812 name = "gimli" 1813 + version = "0.31.1" 1814 source = "registry+https://github.com/rust-lang/crates.io-index" 1815 + checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 1816 1817 [[package]] 1818 name = "glob" ··· 1845 1846 [[package]] 1847 name = "h2" 1848 + version = "0.4.12" 1849 source = "registry+https://github.com/rust-lang/crates.io-index" 1850 + checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" 1851 dependencies = [ 1852 "atomic-waker", 1853 "bytes", ··· 1855 "futures-core", 1856 "futures-sink", 1857 "http", 1858 + "indexmap 2.10.0", 1859 "slab", 1860 "tokio", 1861 "tokio-util", ··· 1870 1871 [[package]] 1872 name = "half" 1873 + version = "2.6.0" 1874 source = "registry+https://github.com/rust-lang/crates.io-index" 1875 + checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" 1876 dependencies = [ 1877 "cfg-if", 1878 "crunchy", 1879 ] 1880 1881 [[package]] ··· 1904 version = "0.15.5" 1905 source = "registry+https://github.com/rust-lang/crates.io-index" 1906 checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" 1907 1908 [[package]] 1909 name = "hashbrown" 1910 + version = "0.16.0" 1911 source = "registry+https://github.com/rust-lang/crates.io-index" 1912 + checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" 1913 dependencies = [ 1914 "allocator-api2", 1915 "equivalent", 1916 + "foldhash", 1917 ] 1918 1919 [[package]] ··· 1982 "rand 0.9.2", 1983 "ring", 1984 "rustls", 1985 + "thiserror 2.0.16", 1986 "tinyvec", 1987 "tokio", 1988 "tokio-rustls", ··· 2007 "resolv-conf", 2008 "rustls", 2009 "smallvec", 2010 + "thiserror 2.0.16", 2011 "tokio", 2012 "tokio-rustls", 2013 "tracing", ··· 2039 checksum = "ad6880c8d4a9ebf39c6e8b77007ce223f646a4d21ce29d99f70cb16420545425" 2040 2041 [[package]] 2042 name = "hostname-validator" 2043 version = "1.1.1" 2044 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2046 2047 [[package]] 2048 name = "http" 2049 + version = "1.3.1" 2050 source = "registry+https://github.com/rust-lang/crates.io-index" 2051 + checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 2052 dependencies = [ 2053 "bytes", 2054 + "fnv", 2055 "itoa", 2056 ] 2057 ··· 2108 2109 [[package]] 2110 name = "hyper" 2111 + version = "1.6.0" 2112 source = "registry+https://github.com/rust-lang/crates.io-index" 2113 + checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 2114 dependencies = [ 2115 "bytes", 2116 "futures-channel", 2117 + "futures-util", 2118 "h2", 2119 "http", 2120 "http-body", ··· 2122 "httpdate", 2123 "itoa", 2124 "pin-project-lite", 2125 "smallvec", 2126 "tokio", 2127 "want", 2128 ] 2129 2130 [[package]] 2131 name = "hyper-rustls" 2132 version = "0.27.7" 2133 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2137 "hyper", 2138 "hyper-util", 2139 "rustls", 2140 "rustls-pki-types", 2141 "tokio", 2142 "tokio-rustls", ··· 2145 ] 2146 2147 [[package]] 2148 name = "hyper-util" 2149 + version = "0.1.16" 2150 source = "registry+https://github.com/rust-lang/crates.io-index" 2151 + checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" 2152 dependencies = [ 2153 "base64 0.22.1", 2154 "bytes", ··· 2162 "libc", 2163 "percent-encoding", 2164 "pin-project-lite", 2165 + "socket2 0.6.0", 2166 "tokio", 2167 "tower-service", 2168 "tracing", 2169 ] 2170 2171 [[package]] 2172 name = "iana-time-zone" 2173 + version = "0.1.63" 2174 source = "registry+https://github.com/rust-lang/crates.io-index" 2175 + checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" 2176 dependencies = [ 2177 "android_system_properties", 2178 "core-foundation-sys", ··· 2180 "js-sys", 2181 "log", 2182 "wasm-bindgen", 2183 + "windows-core", 2184 ] 2185 2186 [[package]] ··· 2194 2195 [[package]] 2196 name = "icu_collections" 2197 + version = "2.0.0" 2198 source = "registry+https://github.com/rust-lang/crates.io-index" 2199 + checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" 2200 dependencies = [ 2201 "displaydoc", 2202 "potential_utf", ··· 2207 2208 [[package]] 2209 name = "icu_locale_core" 2210 + version = "2.0.0" 2211 source = "registry+https://github.com/rust-lang/crates.io-index" 2212 + checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" 2213 dependencies = [ 2214 "displaydoc", 2215 "litemap", ··· 2220 2221 [[package]] 2222 name = "icu_normalizer" 2223 + version = "2.0.0" 2224 source = "registry+https://github.com/rust-lang/crates.io-index" 2225 + checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" 2226 dependencies = [ 2227 + "displaydoc", 2228 "icu_collections", 2229 "icu_normalizer_data", 2230 "icu_properties", ··· 2235 2236 [[package]] 2237 name = "icu_normalizer_data" 2238 + version = "2.0.0" 2239 source = "registry+https://github.com/rust-lang/crates.io-index" 2240 + checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" 2241 2242 [[package]] 2243 name = "icu_properties" 2244 + version = "2.0.1" 2245 source = "registry+https://github.com/rust-lang/crates.io-index" 2246 + checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" 2247 dependencies = [ 2248 + "displaydoc", 2249 "icu_collections", 2250 "icu_locale_core", 2251 "icu_properties_data", 2252 "icu_provider", 2253 + "potential_utf", 2254 "zerotrie", 2255 "zerovec", 2256 ] 2257 2258 [[package]] 2259 name = "icu_properties_data" 2260 + version = "2.0.1" 2261 source = "registry+https://github.com/rust-lang/crates.io-index" 2262 + checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" 2263 2264 [[package]] 2265 name = "icu_provider" 2266 + version = "2.0.0" 2267 source = "registry+https://github.com/rust-lang/crates.io-index" 2268 + checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" 2269 dependencies = [ 2270 "displaydoc", 2271 "icu_locale_core", 2272 + "stable_deref_trait", 2273 + "tinystr", 2274 "writeable", 2275 "yoke", 2276 "zerofrom", ··· 2284 source = "registry+https://github.com/rust-lang/crates.io-index" 2285 checksum = "872718dfcd3a6f4601a3fb413365ee5e1d3ec050316ff79e690c98658a6738ef" 2286 dependencies = [ 2287 + "bitflags", 2288 "byteorder", 2289 "flate2", 2290 ] ··· 2297 2298 [[package]] 2299 name = "idna" 2300 + version = "1.0.3" 2301 source = "registry+https://github.com/rust-lang/crates.io-index" 2302 + checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 2303 dependencies = [ 2304 "idna_adapter", 2305 "smallvec", ··· 2361 2362 [[package]] 2363 name = "indexmap" 2364 + version = "2.10.0" 2365 source = "registry+https://github.com/rust-lang/crates.io-index" 2366 + checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" 2367 dependencies = [ 2368 "equivalent", 2369 + "hashbrown 0.15.5", 2370 "serde", 2371 ] 2372 2373 [[package]] 2374 name = "indoc" 2375 + version = "2.0.6" 2376 source = "registry+https://github.com/rust-lang/crates.io-index" 2377 + checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" 2378 2379 [[package]] 2380 name = "inout" 2381 + version = "0.2.1" 2382 source = "registry+https://github.com/rust-lang/crates.io-index" 2383 + checksum = "c7357b6e7aa75618c7864ebd0634b115a7218b0615f4cb1df33ac3eca23943d4" 2384 dependencies = [ 2385 "hybrid-array", 2386 ] ··· 2398 ] 2399 2400 [[package]] 2401 + name = "io-uring" 2402 + version = "0.7.9" 2403 + source = "registry+https://github.com/rust-lang/crates.io-index" 2404 + checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" 2405 + dependencies = [ 2406 + "bitflags", 2407 + "cfg-if", 2408 + "libc", 2409 + ] 2410 + 2411 + [[package]] 2412 name = "ipconfig" 2413 version = "0.3.2" 2414 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2450 2451 [[package]] 2452 name = "iri-string" 2453 + version = "0.7.8" 2454 source = "registry+https://github.com/rust-lang/crates.io-index" 2455 + checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" 2456 dependencies = [ 2457 "memchr", 2458 "serde", ··· 2470 "cfg_aliases", 2471 "crypto_box", 2472 "data-encoding", 2473 + "der 0.8.0-rc.9", 2474 + "derive_more 2.0.1", 2475 "ed25519-dalek 3.0.0-pre.1", 2476 "futures-buffered", 2477 "futures-util", 2478 + "getrandom 0.3.3", 2479 "hickory-resolver", 2480 "http", 2481 "igd-next", ··· 2491 "n0-watcher", 2492 "nested_enum_utils", 2493 "netdev 0.36.0", 2494 + "netwatch", 2495 "pin-project", 2496 "pkarr", 2497 + "pkcs8 0.11.0-rc.7", 2498 "portmapper", 2499 "rand 0.9.2", 2500 "reqwest", ··· 2528 dependencies = [ 2529 "curve25519-dalek 5.0.0-pre.1", 2530 "data-encoding", 2531 + "derive_more 2.0.1", 2532 "ed25519-dalek 3.0.0-pre.1", 2533 "n0-snafu", 2534 "nested_enum_utils", 2535 "postcard", 2536 + "rand_core 0.9.3", 2537 "serde", 2538 "snafu", 2539 "url", ··· 2548 "blake3", 2549 "bytes", 2550 "data-encoding", 2551 + "derive_more 2.0.1", 2552 "ed25519-dalek 3.0.0-pre.1", 2553 "futures-concurrency", 2554 "futures-lite", 2555 "futures-util", 2556 "hex", 2557 + "indexmap 2.10.0", 2558 "iroh", 2559 "iroh-base", 2560 "iroh-metrics", ··· 2573 2574 [[package]] 2575 name = "iroh-metrics" 2576 + version = "0.36.1" 2577 source = "registry+https://github.com/rust-lang/crates.io-index" 2578 + checksum = "090161e84532a0cb78ab13e70abb882b769ec67cf5a2d2dcea39bd002e1f7172" 2579 dependencies = [ 2580 "iroh-metrics-derive", 2581 "itoa", ··· 2588 2589 [[package]] 2590 name = "iroh-metrics-derive" 2591 + version = "0.3.0" 2592 source = "registry+https://github.com/rust-lang/crates.io-index" 2593 + checksum = "8a39de3779d200dadde3a27b9fbdb34389a2af1b85ea445afca47bf4d7672573" 2594 dependencies = [ 2595 "heck", 2596 "proc-macro2", 2597 "quote", 2598 + "syn 2.0.105", 2599 ] 2600 2601 [[package]] ··· 2612 "rustc-hash", 2613 "rustls", 2614 "socket2 0.5.10", 2615 + "thiserror 2.0.16", 2616 "tokio", 2617 "tracing", 2618 "web-time", ··· 2625 checksum = "929d5d8fa77d5c304d3ee7cae9aede31f13908bd049f9de8c7c0094ad6f7c535" 2626 dependencies = [ 2627 "bytes", 2628 + "getrandom 0.2.16", 2629 "rand 0.8.5", 2630 "ring", 2631 "rustc-hash", 2632 "rustls", 2633 "rustls-pki-types", 2634 "slab", 2635 + "thiserror 2.0.16", 2636 "tinyvec", 2637 "tracing", 2638 "web-time", ··· 2662 "bytes", 2663 "cfg_aliases", 2664 "data-encoding", 2665 + "derive_more 2.0.1", 2666 + "getrandom 0.3.3", 2667 "hickory-resolver", 2668 "http", 2669 "http-body-util", ··· 2673 "iroh-metrics", 2674 "iroh-quinn", 2675 "iroh-quinn-proto", 2676 + "lru 0.16.2", 2677 "n0-future 0.2.0", 2678 "n0-snafu", 2679 "nested_enum_utils", ··· 2752 "serde_json", 2753 "snafu", 2754 "testresult", 2755 + "thiserror 2.0.16", 2756 "tokio", 2757 "tracing", 2758 "tracing-subscriber", ··· 2777 "rustls", 2778 "serde", 2779 "smallvec", 2780 + "thiserror 2.0.16", 2781 "tokio", 2782 "tokio-util", 2783 "tracing", ··· 2801 checksum = "80e06eb3077e16299f86816ca5f5d795abccf6e5c58340d701ecc4166bdcf2ea" 2802 dependencies = [ 2803 "anyhow", 2804 + "getrandom 0.3.3", 2805 "iroh", 2806 "iroh-base", 2807 "irpc", ··· 2814 2815 [[package]] 2816 name = "is-terminal" 2817 + version = "0.4.16" 2818 source = "registry+https://github.com/rust-lang/crates.io-index" 2819 + checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" 2820 dependencies = [ 2821 "hermit-abi", 2822 "libc", 2823 + "windows-sys 0.59.0", 2824 ] 2825 2826 [[package]] ··· 2833 ] 2834 2835 [[package]] 2836 name = "itoa" 2837 + version = "1.0.15" 2838 source = "registry+https://github.com/rust-lang/crates.io-index" 2839 + checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 2840 2841 [[package]] 2842 name = "jfifdump" ··· 2845 checksum = "68cf72bc7b75b6615ffd06bfe6840f3c57e7e4ea615558a2a452f458ebf5551e" 2846 2847 [[package]] 2848 name = "js-sys" 2849 + version = "0.3.77" 2850 source = "registry+https://github.com/rust-lang/crates.io-index" 2851 + checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 2852 dependencies = [ 2853 "once_cell", 2854 "wasm-bindgen", ··· 2876 2877 [[package]] 2878 name = "libc" 2879 + version = "0.2.175" 2880 source = "registry+https://github.com/rust-lang/crates.io-index" 2881 + checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" 2882 2883 [[package]] 2884 name = "libm" ··· 2887 checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" 2888 2889 [[package]] 2890 name = "linux-raw-sys" 2891 version = "0.4.15" 2892 source = "registry+https://github.com/rust-lang/crates.io-index" 2893 checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" 2894 2895 [[package]] 2896 name = "litemap" 2897 + version = "0.8.0" 2898 source = "registry+https://github.com/rust-lang/crates.io-index" 2899 + checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" 2900 2901 [[package]] 2902 name = "litrs" 2903 + version = "0.4.2" 2904 source = "registry+https://github.com/rust-lang/crates.io-index" 2905 + checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" 2906 2907 [[package]] 2908 name = "lock_api" 2909 + version = "0.4.13" 2910 source = "registry+https://github.com/rust-lang/crates.io-index" 2911 + checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" 2912 dependencies = [ 2913 + "autocfg", 2914 "scopeguard", 2915 ] 2916 2917 [[package]] 2918 name = "log" 2919 + version = "0.4.27" 2920 source = "registry+https://github.com/rust-lang/crates.io-index" 2921 + checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 2922 2923 [[package]] 2924 name = "loom" ··· 2935 2936 [[package]] 2937 name = "lru" 2938 + version = "0.13.0" 2939 source = "registry+https://github.com/rust-lang/crates.io-index" 2940 + checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" 2941 + 2942 + [[package]] 2943 + name = "lru" 2944 + version = "0.16.2" 2945 + source = "registry+https://github.com/rust-lang/crates.io-index" 2946 + checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" 2947 dependencies = [ 2948 + "hashbrown 0.16.0", 2949 ] 2950 2951 [[package]] ··· 2955 checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" 2956 2957 [[package]] 2958 name = "matchers" 2959 + version = "0.1.0" 2960 source = "registry+https://github.com/rust-lang/crates.io-index" 2961 + checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 2962 dependencies = [ 2963 + "regex-automata 0.1.10", 2964 ] 2965 2966 [[package]] 2967 name = "md5" ··· 2971 2972 [[package]] 2973 name = "memchr" 2974 + version = "2.7.5" 2975 source = "registry+https://github.com/rust-lang/crates.io-index" 2976 + checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 2977 2978 [[package]] 2979 name = "mime" ··· 3009 3010 [[package]] 3011 name = "mio" 3012 + version = "1.0.4" 3013 source = "registry+https://github.com/rust-lang/crates.io-index" 3014 + checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" 3015 dependencies = [ 3016 "libc", 3017 "wasi 0.11.1+wasi-snapshot-preview1", 3018 + "windows-sys 0.59.0", 3019 ] 3020 3021 [[package]] 3022 name = "moka" 3023 + version = "0.12.10" 3024 source = "registry+https://github.com/rust-lang/crates.io-index" 3025 + checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" 3026 dependencies = [ 3027 "crossbeam-channel", 3028 "crossbeam-epoch", 3029 "crossbeam-utils", 3030 + "loom", 3031 "parking_lot", 3032 "portable-atomic", 3033 + "rustc_version", 3034 "smallvec", 3035 "tagptr", 3036 + "thiserror 1.0.69", 3037 "uuid", 3038 ] 3039 ··· 3050 "serde_json", 3051 "thiserror 1.0.69", 3052 ] 3053 3054 [[package]] 3055 name = "n0-future" ··· 3119 3120 [[package]] 3121 name = "nested_enum_utils" 3122 + version = "0.2.2" 3123 source = "registry+https://github.com/rust-lang/crates.io-index" 3124 + checksum = "43fa9161ed44d30e9702fe42bd78693bceac0fed02f647da749f36109023d3a3" 3125 dependencies = [ 3126 "proc-macro-crate", 3127 "proc-macro2", 3128 "quote", 3129 + "syn 1.0.109", 3130 ] 3131 3132 [[package]] ··· 3138 "dlopen2", 3139 "ipnet", 3140 "libc", 3141 + "netlink-packet-core", 3142 "netlink-packet-route 0.22.0", 3143 "netlink-sys", 3144 "once_cell", ··· 3155 "dlopen2", 3156 "ipnet", 3157 "libc", 3158 + "netlink-packet-core", 3159 "netlink-packet-route 0.22.0", 3160 "netlink-sys", 3161 "once_cell", ··· 3164 ] 3165 3166 [[package]] 3167 name = "netlink-packet-core" 3168 version = "0.7.0" 3169 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3175 ] 3176 3177 [[package]] 3178 name = "netlink-packet-route" 3179 version = "0.22.0" 3180 source = "registry+https://github.com/rust-lang/crates.io-index" 3181 checksum = "fc0e7987b28514adf555dc1f9a5c30dfc3e50750bbaffb1aec41ca7b23dcd8e4" 3182 dependencies = [ 3183 "anyhow", 3184 + "bitflags", 3185 "byteorder", 3186 "libc", 3187 "log", 3188 + "netlink-packet-core", 3189 "netlink-packet-utils", 3190 ] 3191 ··· 3196 checksum = "56d83370a96813d7c977f8b63054f1162df6e5784f1c598d689236564fb5a6f2" 3197 dependencies = [ 3198 "anyhow", 3199 + "bitflags", 3200 "byteorder", 3201 "libc", 3202 "log", 3203 + "netlink-packet-core", 3204 "netlink-packet-utils", 3205 ] 3206 3207 [[package]] 3208 name = "netlink-packet-utils" 3209 version = "0.5.2" 3210 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3225 "bytes", 3226 "futures", 3227 "log", 3228 + "netlink-packet-core", 3229 "netlink-sys", 3230 + "thiserror 2.0.16", 3231 ] 3232 3233 [[package]] ··· 3252 "atomic-waker", 3253 "bytes", 3254 "cfg_aliases", 3255 + "derive_more 2.0.1", 3256 "iroh-quinn-udp", 3257 "js-sys", 3258 "libc", ··· 3260 "n0-watcher", 3261 "nested_enum_utils", 3262 "netdev 0.37.3", 3263 + "netlink-packet-core", 3264 "netlink-packet-route 0.24.0", 3265 + "netlink-proto", 3266 "netlink-sys", 3267 "pin-project-lite", 3268 "serde", 3269 "snafu", 3270 + "socket2 0.6.0", 3271 "time", 3272 "tokio", 3273 "tokio-util", 3274 "tracing", 3275 "web-sys", 3276 + "windows", 3277 + "windows-result", 3278 "wmi", 3279 ] 3280 ··· 3321 dependencies = [ 3322 "base32", 3323 "document-features", 3324 + "getrandom 0.2.16", 3325 "httpdate", 3326 "js-sys", 3327 "once_cell", ··· 3330 3331 [[package]] 3332 name = "nu-ansi-term" 3333 + version = "0.46.0" 3334 source = "registry+https://github.com/rust-lang/crates.io-index" 3335 + checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 3336 dependencies = [ 3337 + "overload", 3338 + "winapi", 3339 ] 3340 3341 [[package]] ··· 3350 3351 [[package]] 3352 name = "num-bigint-dig" 3353 + version = "0.8.4" 3354 source = "registry+https://github.com/rust-lang/crates.io-index" 3355 + checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" 3356 dependencies = [ 3357 + "byteorder", 3358 "lazy_static", 3359 "libm", 3360 "num-integer", ··· 3416 3417 [[package]] 3418 name = "num_enum" 3419 + version = "0.7.4" 3420 source = "registry+https://github.com/rust-lang/crates.io-index" 3421 + checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" 3422 dependencies = [ 3423 "num_enum_derive", 3424 "rustversion", ··· 3426 3427 [[package]] 3428 name = "num_enum_derive" 3429 + version = "0.7.4" 3430 source = "registry+https://github.com/rust-lang/crates.io-index" 3431 + checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" 3432 dependencies = [ 3433 "proc-macro-crate", 3434 "proc-macro2", 3435 "quote", 3436 + "syn 2.0.105", 3437 ] 3438 3439 [[package]] 3440 name = "object" 3441 + version = "0.36.7" 3442 source = "registry+https://github.com/rust-lang/crates.io-index" 3443 + checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 3444 dependencies = [ 3445 "memchr", 3446 ] ··· 3466 3467 [[package]] 3468 name = "openssl" 3469 + version = "0.10.73" 3470 source = "registry+https://github.com/rust-lang/crates.io-index" 3471 + checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" 3472 dependencies = [ 3473 + "bitflags", 3474 "cfg-if", 3475 "foreign-types", 3476 "libc", ··· 3487 dependencies = [ 3488 "proc-macro2", 3489 "quote", 3490 + "syn 2.0.105", 3491 ] 3492 3493 [[package]] 3494 name = "openssl-src" 3495 + version = "300.5.2+3.5.2" 3496 source = "registry+https://github.com/rust-lang/crates.io-index" 3497 + checksum = "d270b79e2926f5150189d475bc7e9d2c69f9c4697b185fa917d5a32b792d21b4" 3498 dependencies = [ 3499 "cc", 3500 ] 3501 3502 [[package]] 3503 name = "openssl-sys" 3504 + version = "0.9.109" 3505 source = "registry+https://github.com/rust-lang/crates.io-index" 3506 + checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" 3507 dependencies = [ 3508 "cc", 3509 "libc", ··· 3523 ] 3524 3525 [[package]] 3526 + name = "overload" 3527 + version = "0.1.1" 3528 + source = "registry+https://github.com/rust-lang/crates.io-index" 3529 + checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 3530 + 3531 + [[package]] 3532 name = "parking" 3533 version = "2.2.1" 3534 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3536 3537 [[package]] 3538 name = "parking_lot" 3539 + version = "0.12.4" 3540 source = "registry+https://github.com/rust-lang/crates.io-index" 3541 + checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" 3542 dependencies = [ 3543 "lock_api", 3544 "parking_lot_core", ··· 3546 3547 [[package]] 3548 name = "parking_lot_core" 3549 + version = "0.9.11" 3550 source = "registry+https://github.com/rust-lang/crates.io-index" 3551 + checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" 3552 dependencies = [ 3553 "cfg-if", 3554 "libc", 3555 + "redox_syscall", 3556 "smallvec", 3557 + "windows-targets 0.52.6", 3558 ] 3559 3560 [[package]] ··· 3589 ] 3590 3591 [[package]] 3592 name = "peg" 3593 version = "0.8.5" 3594 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3617 3618 [[package]] 3619 name = "pem" 3620 + version = "3.0.5" 3621 source = "registry+https://github.com/rust-lang/crates.io-index" 3622 + checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" 3623 dependencies = [ 3624 "base64 0.22.1", 3625 + "serde", 3626 ] 3627 3628 [[package]] ··· 3636 3637 [[package]] 3638 name = "pem-rfc7468" 3639 + version = "1.0.0-rc.3" 3640 source = "registry+https://github.com/rust-lang/crates.io-index" 3641 + checksum = "a8e58fab693c712c0d4e88f8eb3087b6521d060bcaf76aeb20cb192d809115ba" 3642 dependencies = [ 3643 "base64ct", 3644 ] 3645 3646 [[package]] 3647 name = "percent-encoding" 3648 + version = "2.3.1" 3649 source = "registry+https://github.com/rust-lang/crates.io-index" 3650 + checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 3651 3652 [[package]] 3653 name = "pest" 3654 + version = "2.8.1" 3655 source = "registry+https://github.com/rust-lang/crates.io-index" 3656 + checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" 3657 dependencies = [ 3658 "memchr", 3659 + "thiserror 2.0.16", 3660 "ucd-trie", 3661 ] 3662 3663 [[package]] 3664 name = "pest_derive" 3665 + version = "2.8.1" 3666 source = "registry+https://github.com/rust-lang/crates.io-index" 3667 + checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" 3668 dependencies = [ 3669 "pest", 3670 "pest_generator", ··· 3672 3673 [[package]] 3674 name = "pest_generator" 3675 + version = "2.8.1" 3676 source = "registry+https://github.com/rust-lang/crates.io-index" 3677 + checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" 3678 dependencies = [ 3679 "pest", 3680 "pest_meta", 3681 "proc-macro2", 3682 "quote", 3683 + "syn 2.0.105", 3684 ] 3685 3686 [[package]] 3687 name = "pest_meta" 3688 + version = "2.8.1" 3689 source = "registry+https://github.com/rust-lang/crates.io-index" 3690 + checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" 3691 dependencies = [ 3692 "pest", 3693 "sha2 0.10.9", 3694 ] 3695 3696 [[package]] 3697 name = "pharos" 3698 version = "0.5.3" 3699 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3720 dependencies = [ 3721 "proc-macro2", 3722 "quote", 3723 + "syn 2.0.105", 3724 ] 3725 3726 [[package]] ··· 3743 3744 [[package]] 3745 name = "pkarr" 3746 + version = "5.0.0" 3747 source = "registry+https://github.com/rust-lang/crates.io-index" 3748 + checksum = "792c1328860f6874e90e3b387b4929819cc7783a6bd5a4728e918706eb436a48" 3749 dependencies = [ 3750 "async-compat", 3751 "base32", ··· 3756 "ed25519-dalek 3.0.0-pre.1", 3757 "futures-buffered", 3758 "futures-lite", 3759 + "getrandom 0.3.3", 3760 "log", 3761 + "lru 0.13.0", 3762 "ntimestamp", 3763 "reqwest", 3764 "self_cell", 3765 "serde", 3766 "sha1_smol", 3767 "simple-dns", 3768 + "thiserror 2.0.16", 3769 "tokio", 3770 "tracing", 3771 "url", ··· 3795 3796 [[package]] 3797 name = "pkcs8" 3798 + version = "0.11.0-rc.7" 3799 source = "registry+https://github.com/rust-lang/crates.io-index" 3800 + checksum = "93eac55f10aceed84769df670ea4a32d2ffad7399400d41ee1c13b1cd8e1b478" 3801 dependencies = [ 3802 + "der 0.8.0-rc.9", 3803 "spki 0.8.0-rc.4", 3804 ] 3805 ··· 3833 "proc-macro2", 3834 "quote", 3835 "regex", 3836 + "syn 2.0.105", 3837 ] 3838 3839 [[package]] ··· 3882 3883 [[package]] 3884 name = "portable-atomic" 3885 + version = "1.11.1" 3886 source = "registry+https://github.com/rust-lang/crates.io-index" 3887 + checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" 3888 3889 [[package]] 3890 name = "portmapper" 3891 + version = "0.10.0" 3892 source = "registry+https://github.com/rust-lang/crates.io-index" 3893 + checksum = "90f7313cafd74e95e6a358c1d0a495112f175502cc2e69870d0a5b12b6553059" 3894 dependencies = [ 3895 "base64 0.22.1", 3896 "bytes", 3897 + "derive_more 2.0.1", 3898 "futures-lite", 3899 "futures-util", 3900 "hyper-util", ··· 3902 "iroh-metrics", 3903 "libc", 3904 "nested_enum_utils", 3905 + "netwatch", 3906 "num_enum", 3907 "rand 0.9.2", 3908 "serde", 3909 "smallvec", 3910 "snafu", 3911 + "socket2 0.6.0", 3912 "time", 3913 "tokio", 3914 "tokio-util", ··· 3939 dependencies = [ 3940 "proc-macro2", 3941 "quote", 3942 + "syn 2.0.105", 3943 ] 3944 3945 [[package]] 3946 name = "potential_utf" 3947 + version = "0.1.2" 3948 source = "registry+https://github.com/rust-lang/crates.io-index" 3949 + checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" 3950 dependencies = [ 3951 "zerovec", 3952 ] ··· 3979 3980 [[package]] 3981 name = "precis-profiles" 3982 + version = "0.1.12" 3983 source = "registry+https://github.com/rust-lang/crates.io-index" 3984 + checksum = "dc4f67f78f50388f03494794766ba824a704db16fb5d400fe8d545fa7bc0d3f1" 3985 dependencies = [ 3986 "lazy_static", 3987 "precis-core", ··· 4001 ] 4002 4003 [[package]] 4004 name = "proc-macro-crate" 4005 + version = "3.3.0" 4006 source = "registry+https://github.com/rust-lang/crates.io-index" 4007 + checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" 4008 dependencies = [ 4009 + "toml_edit", 4010 ] 4011 4012 [[package]] ··· 4035 4036 [[package]] 4037 name = "proc-macro2" 4038 + version = "1.0.97" 4039 source = "registry+https://github.com/rust-lang/crates.io-index" 4040 + checksum = "d61789d7719defeb74ea5fe81f2fdfdbd28a803847077cecce2ff14e1472f6f1" 4041 dependencies = [ 4042 "unicode-ident", 4043 ] 4044 4045 [[package]] 4046 name = "proptest" 4047 + version = "1.8.0" 4048 source = "registry+https://github.com/rust-lang/crates.io-index" 4049 + checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce" 4050 dependencies = [ 4051 + "bitflags", 4052 + "lazy_static", 4053 "num-traits", 4054 "rand 0.9.2", 4055 "rand_chacha 0.9.0", 4056 "rand_xorshift", 4057 + "regex-syntax 0.8.5", 4058 "unarray", 4059 ] 4060 4061 [[package]] 4062 name = "quick-xml" 4063 version = "0.37.5" 4064 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4069 4070 [[package]] 4071 name = "quinn" 4072 + version = "0.11.8" 4073 source = "registry+https://github.com/rust-lang/crates.io-index" 4074 + checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" 4075 dependencies = [ 4076 "bytes", 4077 "cfg_aliases", ··· 4080 "quinn-udp", 4081 "rustc-hash", 4082 "rustls", 4083 + "socket2 0.5.10", 4084 + "thiserror 2.0.16", 4085 "tokio", 4086 "tracing", 4087 "web-time", ··· 4089 4090 [[package]] 4091 name = "quinn-proto" 4092 + version = "0.11.12" 4093 source = "registry+https://github.com/rust-lang/crates.io-index" 4094 + checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" 4095 dependencies = [ 4096 "bytes", 4097 + "getrandom 0.3.3", 4098 "lru-slab", 4099 "rand 0.9.2", 4100 "ring", ··· 4102 "rustls", 4103 "rustls-pki-types", 4104 "slab", 4105 + "thiserror 2.0.16", 4106 "tinyvec", 4107 "tracing", 4108 "web-time", ··· 4110 4111 [[package]] 4112 name = "quinn-udp" 4113 + version = "0.5.13" 4114 source = "registry+https://github.com/rust-lang/crates.io-index" 4115 + checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" 4116 dependencies = [ 4117 "cfg_aliases", 4118 "libc", 4119 "once_cell", 4120 + "socket2 0.5.10", 4121 "tracing", 4122 + "windows-sys 0.59.0", 4123 ] 4124 4125 [[package]] 4126 name = "quote" 4127 + version = "1.0.40" 4128 source = "registry+https://github.com/rust-lang/crates.io-index" 4129 + checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 4130 dependencies = [ 4131 "proc-macro2", 4132 ] ··· 4171 checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" 4172 dependencies = [ 4173 "rand_chacha 0.9.0", 4174 + "rand_core 0.9.3", 4175 ] 4176 4177 [[package]] ··· 4191 checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 4192 dependencies = [ 4193 "ppv-lite86", 4194 + "rand_core 0.9.3", 4195 ] 4196 4197 [[package]] ··· 4200 source = "registry+https://github.com/rust-lang/crates.io-index" 4201 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 4202 dependencies = [ 4203 + "getrandom 0.2.16", 4204 ] 4205 4206 [[package]] 4207 name = "rand_core" 4208 + version = "0.9.3" 4209 source = "registry+https://github.com/rust-lang/crates.io-index" 4210 + checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 4211 dependencies = [ 4212 + "getrandom 0.3.3", 4213 ] 4214 4215 [[package]] ··· 4218 source = "registry+https://github.com/rust-lang/crates.io-index" 4219 checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" 4220 dependencies = [ 4221 + "rand_core 0.9.3", 4222 ] 4223 4224 [[package]] ··· 4277 dependencies = [ 4278 "proc-macro2", 4279 "rasn-derive-impl", 4280 + "syn 2.0.105", 4281 ] 4282 4283 [[package]] ··· 4287 checksum = "f14454245fd76215b830d083b6b6c6842047e50cb7ee73ce1e769d4b099c89fd" 4288 dependencies = [ 4289 "either", 4290 + "itertools", 4291 "proc-macro2", 4292 "quote", 4293 + "syn 2.0.105", 4294 "uuid", 4295 ] 4296 ··· 4311 checksum = "0c902bfc1add6e7471323cdb879fe6a3c3122b1cb0247937c0940b28e2334252" 4312 dependencies = [ 4313 "rasn", 4314 ] 4315 4316 [[package]] ··· 4327 ] 4328 4329 [[package]] 4330 name = "redox_syscall" 4331 + version = "0.5.17" 4332 source = "registry+https://github.com/rust-lang/crates.io-index" 4333 + checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" 4334 dependencies = [ 4335 + "bitflags", 4336 ] 4337 4338 [[package]] ··· 4352 dependencies = [ 4353 "proc-macro2", 4354 "quote", 4355 + "syn 2.0.105", 4356 ] 4357 4358 [[package]] 4359 name = "regex" 4360 + version = "1.11.1" 4361 source = "registry+https://github.com/rust-lang/crates.io-index" 4362 + checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 4363 dependencies = [ 4364 "aho-corasick", 4365 "memchr", 4366 + "regex-automata 0.4.9", 4367 + "regex-syntax 0.8.5", 4368 ] 4369 4370 [[package]] 4371 name = "regex-automata" 4372 + version = "0.1.10" 4373 source = "registry+https://github.com/rust-lang/crates.io-index" 4374 + checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 4375 + dependencies = [ 4376 + "regex-syntax 0.6.29", 4377 + ] 4378 + 4379 + [[package]] 4380 + name = "regex-automata" 4381 + version = "0.4.9" 4382 + source = "registry+https://github.com/rust-lang/crates.io-index" 4383 + checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 4384 dependencies = [ 4385 "aho-corasick", 4386 "memchr", 4387 + "regex-syntax 0.8.5", 4388 ] 4389 4390 [[package]] 4391 name = "regex-lite" 4392 + version = "0.1.6" 4393 source = "registry+https://github.com/rust-lang/crates.io-index" 4394 + checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" 4395 4396 [[package]] 4397 name = "regex-syntax" 4398 + version = "0.6.29" 4399 source = "registry+https://github.com/rust-lang/crates.io-index" 4400 + checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 4401 4402 [[package]] 4403 + name = "regex-syntax" 4404 + version = "0.8.5" 4405 source = "registry+https://github.com/rust-lang/crates.io-index" 4406 + checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 4407 4408 [[package]] 4409 name = "reqwest" 4410 + version = "0.12.23" 4411 source = "registry+https://github.com/rust-lang/crates.io-index" 4412 + checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" 4413 dependencies = [ 4414 "base64 0.22.1", 4415 "bytes", ··· 4435 "tokio", 4436 "tokio-rustls", 4437 "tokio-util", 4438 + "tower", 4439 "tower-http", 4440 "tower-service", 4441 "url", ··· 4448 4449 [[package]] 4450 name = "resolv-conf" 4451 + version = "0.7.4" 4452 source = "registry+https://github.com/rust-lang/crates.io-index" 4453 + checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3" 4454 4455 [[package]] 4456 name = "riff" ··· 4466 dependencies = [ 4467 "cc", 4468 "cfg-if", 4469 + "getrandom 0.2.16", 4470 "libc", 4471 "untrusted", 4472 "windows-sys 0.52.0", ··· 4479 checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" 4480 dependencies = [ 4481 "base64 0.21.7", 4482 + "bitflags", 4483 "serde", 4484 "serde_derive", 4485 ] 4486 4487 [[package]] 4488 name = "rpds" 4489 + version = "1.1.1" 4490 source = "registry+https://github.com/rust-lang/crates.io-index" 4491 + checksum = "a7f89f654d51fffdd6026289d07d1fd523244d46ae0a8bc22caa6dd7f9e8cb0b" 4492 dependencies = [ 4493 "archery", 4494 "serde", ··· 4496 4497 [[package]] 4498 name = "rsa" 4499 + version = "0.9.8" 4500 source = "registry+https://github.com/rust-lang/crates.io-index" 4501 + checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" 4502 dependencies = [ 4503 "const-oid 0.9.6", 4504 "digest 0.10.7", ··· 4561 source = "registry+https://github.com/rust-lang/crates.io-index" 4562 checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" 4563 dependencies = [ 4564 + "bitflags", 4565 "errno", 4566 "libc", 4567 + "linux-raw-sys", 4568 "windows-sys 0.59.0", 4569 ] 4570 4571 [[package]] 4572 name = "rustls" 4573 + version = "0.23.31" 4574 source = "registry+https://github.com/rust-lang/crates.io-index" 4575 + checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" 4576 dependencies = [ 4577 "log", 4578 "once_cell", 4579 "ring", ··· 4584 ] 4585 4586 [[package]] 4587 name = "rustls-pemfile" 4588 version = "2.2.0" 4589 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4594 4595 [[package]] 4596 name = "rustls-pki-types" 4597 + version = "1.12.0" 4598 source = "registry+https://github.com/rust-lang/crates.io-index" 4599 + checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" 4600 dependencies = [ 4601 "web-time", 4602 "zeroize", ··· 4604 4605 [[package]] 4606 name = "rustls-webpki" 4607 + version = "0.103.4" 4608 source = "registry+https://github.com/rust-lang/crates.io-index" 4609 + checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" 4610 dependencies = [ 4611 "ring", 4612 "rustls-pki-types", 4613 "untrusted", ··· 4621 4622 [[package]] 4623 name = "ryu" 4624 + version = "1.0.20" 4625 source = "registry+https://github.com/rust-lang/crates.io-index" 4626 + checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 4627 4628 [[package]] 4629 name = "salsa20" ··· 4633 dependencies = [ 4634 "cfg-if", 4635 "cipher", 4636 ] 4637 4638 [[package]] ··· 4661 4662 [[package]] 4663 name = "schemars" 4664 + version = "1.0.4" 4665 source = "registry+https://github.com/rust-lang/crates.io-index" 4666 + checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" 4667 dependencies = [ 4668 "dyn-clone", 4669 "ref-cast", ··· 4680 "proc-macro2", 4681 "quote", 4682 "serde_derive_internals", 4683 + "syn 2.0.105", 4684 ] 4685 4686 [[package]] ··· 4712 dependencies = [ 4713 "proc-macro2", 4714 "quote", 4715 + "syn 2.0.105", 4716 ] 4717 4718 [[package]] 4719 name = "self_cell" 4720 + version = "1.2.0" 4721 source = "registry+https://github.com/rust-lang/crates.io-index" 4722 + checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" 4723 4724 [[package]] 4725 name = "semver" 4726 + version = "1.0.26" 4727 source = "registry+https://github.com/rust-lang/crates.io-index" 4728 + checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" 4729 dependencies = [ 4730 "serde", 4731 ] 4732 4733 [[package]] ··· 4738 4739 [[package]] 4740 name = "serde" 4741 + version = "1.0.226" 4742 source = "registry+https://github.com/rust-lang/crates.io-index" 4743 + checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" 4744 dependencies = [ 4745 "serde_core", 4746 "serde_derive", ··· 4777 4778 [[package]] 4779 name = "serde_bytes" 4780 + version = "0.11.17" 4781 source = "registry+https://github.com/rust-lang/crates.io-index" 4782 + checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" 4783 dependencies = [ 4784 "serde", 4785 ] 4786 4787 [[package]] ··· 4796 4797 [[package]] 4798 name = "serde_core" 4799 + version = "1.0.226" 4800 source = "registry+https://github.com/rust-lang/crates.io-index" 4801 + checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" 4802 dependencies = [ 4803 "serde_derive", 4804 ] 4805 4806 [[package]] 4807 name = "serde_derive" 4808 + version = "1.0.226" 4809 source = "registry+https://github.com/rust-lang/crates.io-index" 4810 + checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" 4811 dependencies = [ 4812 "proc-macro2", 4813 "quote", 4814 + "syn 2.0.105", 4815 ] 4816 4817 [[package]] ··· 4822 dependencies = [ 4823 "proc-macro2", 4824 "quote", 4825 + "syn 2.0.105", 4826 ] 4827 4828 [[package]] 4829 name = "serde_json" 4830 + version = "1.0.145" 4831 source = "registry+https://github.com/rust-lang/crates.io-index" 4832 + checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" 4833 dependencies = [ 4834 + "indexmap 2.10.0", 4835 "itoa", 4836 "memchr", 4837 + "ryu", 4838 "serde", 4839 "serde_core", 4840 ] 4841 4842 [[package]] ··· 4862 4863 [[package]] 4864 name = "serde_with" 4865 + version = "3.14.1" 4866 source = "registry+https://github.com/rust-lang/crates.io-index" 4867 + checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e" 4868 dependencies = [ 4869 "base64 0.22.1", 4870 "chrono", 4871 "hex", 4872 "indexmap 1.9.3", 4873 + "indexmap 2.10.0", 4874 "schemars 0.9.0", 4875 + "schemars 1.0.4", 4876 + "serde", 4877 + "serde_derive", 4878 "serde_json", 4879 "serde_with_macros", 4880 "time", ··· 4882 4883 [[package]] 4884 name = "serde_with_macros" 4885 + version = "3.14.1" 4886 source = "registry+https://github.com/rust-lang/crates.io-index" 4887 + checksum = "327ada00f7d64abaac1e55a6911e90cf665aa051b9a561c7006c157f4633135e" 4888 dependencies = [ 4889 "darling", 4890 "proc-macro2", 4891 "quote", 4892 + "syn 2.0.105", 4893 ] 4894 4895 [[package]] 4896 name = "serdect" 4897 + version = "0.4.1" 4898 source = "registry+https://github.com/rust-lang/crates.io-index" 4899 + checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" 4900 dependencies = [ 4901 "base16ct", 4902 "serde", ··· 4958 4959 [[package]] 4960 name = "signal-hook-registry" 4961 + version = "1.4.6" 4962 source = "registry+https://github.com/rust-lang/crates.io-index" 4963 + checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" 4964 dependencies = [ 4965 "libc", 4966 ] 4967 ··· 4977 4978 [[package]] 4979 name = "signature" 4980 + version = "3.0.0-rc.4" 4981 source = "registry+https://github.com/rust-lang/crates.io-index" 4982 + checksum = "fc280a6ff65c79fbd6622f64d7127f32b85563bca8c53cd2e9141d6744a9056d" 4983 4984 [[package]] 4985 name = "simd-adler32" 4986 + version = "0.3.7" 4987 source = "registry+https://github.com/rust-lang/crates.io-index" 4988 + checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" 4989 4990 [[package]] 4991 name = "simdutf8" ··· 4999 source = "registry+https://github.com/rust-lang/crates.io-index" 5000 checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" 5001 dependencies = [ 5002 + "bitflags", 5003 ] 5004 5005 [[package]] ··· 5009 checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" 5010 5011 [[package]] 5012 name = "slab" 5013 version = "0.4.11" 5014 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5051 "heck", 5052 "proc-macro2", 5053 "quote", 5054 + "syn 2.0.105", 5055 ] 5056 5057 [[package]] ··· 5066 5067 [[package]] 5068 name = "socket2" 5069 + version = "0.6.0" 5070 source = "registry+https://github.com/rust-lang/crates.io-index" 5071 + checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" 5072 dependencies = [ 5073 "libc", 5074 + "windows-sys 0.59.0", 5075 ] 5076 5077 [[package]] ··· 5106 checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" 5107 dependencies = [ 5108 "base64ct", 5109 + "der 0.8.0-rc.9", 5110 ] 5111 5112 [[package]] 5113 name = "stable_deref_trait" 5114 + version = "1.2.0" 5115 source = "registry+https://github.com/rust-lang/crates.io-index" 5116 + checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 5117 5118 [[package]] 5119 name = "static-iref" ··· 5123 dependencies = [ 5124 "iref", 5125 "quote", 5126 + "syn 2.0.105", 5127 ] 5128 5129 [[package]] ··· 5142 "quote", 5143 "serde", 5144 "sha2 0.10.9", 5145 + "syn 2.0.105", 5146 "thiserror 1.0.69", 5147 ] 5148 ··· 5159 checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 5160 5161 [[package]] 5162 name = "strum" 5163 version = "0.27.2" 5164 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5176 "heck", 5177 "proc-macro2", 5178 "quote", 5179 + "syn 2.0.105", 5180 ] 5181 5182 [[package]] ··· 5211 5212 [[package]] 5213 name = "surge-ping" 5214 + version = "0.8.2" 5215 source = "registry+https://github.com/rust-lang/crates.io-index" 5216 + checksum = "6fda78103d8016bb25c331ddc54af634e801806463682cc3e549d335df644d95" 5217 dependencies = [ 5218 "hex", 5219 "parking_lot", 5220 "pnet_packet", 5221 "rand 0.9.2", 5222 + "socket2 0.5.10", 5223 "thiserror 1.0.69", 5224 "tokio", 5225 "tracing", ··· 5227 5228 [[package]] 5229 name = "swarm-discovery" 5230 + version = "0.4.0" 5231 source = "registry+https://github.com/rust-lang/crates.io-index" 5232 + checksum = "4eae338a4551897c6a50fa2c041c4b75f578962d9fca8adb828cf81f7158740f" 5233 dependencies = [ 5234 "acto", 5235 "hickory-proto", 5236 "rand 0.9.2", 5237 "socket2 0.5.10", 5238 + "thiserror 2.0.16", 5239 "tokio", 5240 "tracing", 5241 ] ··· 5253 5254 [[package]] 5255 name = "syn" 5256 + version = "2.0.105" 5257 source = "registry+https://github.com/rust-lang/crates.io-index" 5258 + checksum = "7bc3fcb250e53458e712715cf74285c1f889686520d79294a9ef3bd7aa1fc619" 5259 dependencies = [ 5260 "proc-macro2", 5261 "quote", ··· 5279 dependencies = [ 5280 "proc-macro2", 5281 "quote", 5282 + "syn 2.0.105", 5283 ] 5284 5285 [[package]] ··· 5288 source = "registry+https://github.com/rust-lang/crates.io-index" 5289 checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 5290 dependencies = [ 5291 + "bitflags", 5292 + "core-foundation", 5293 "system-configuration-sys", 5294 ] 5295 ··· 5323 dependencies = [ 5324 "cfg-if", 5325 "fastrand", 5326 + "getrandom 0.2.16", 5327 "once_cell", 5328 + "rustix", 5329 "windows-sys 0.59.0", 5330 ] 5331 ··· 5339 ] 5340 5341 [[package]] 5342 name = "testresult" 5343 version = "0.4.1" 5344 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5364 5365 [[package]] 5366 name = "thiserror" 5367 + version = "2.0.16" 5368 source = "registry+https://github.com/rust-lang/crates.io-index" 5369 + checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" 5370 dependencies = [ 5371 + "thiserror-impl 2.0.16", 5372 ] 5373 5374 [[package]] ··· 5379 dependencies = [ 5380 "proc-macro2", 5381 "quote", 5382 + "syn 2.0.105", 5383 ] 5384 5385 [[package]] 5386 name = "thiserror-impl" 5387 + version = "2.0.16" 5388 source = "registry+https://github.com/rust-lang/crates.io-index" 5389 + checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" 5390 dependencies = [ 5391 "proc-macro2", 5392 "quote", 5393 + "syn 2.0.105", 5394 ] 5395 5396 [[package]] ··· 5404 5405 [[package]] 5406 name = "time" 5407 + version = "0.3.41" 5408 source = "registry+https://github.com/rust-lang/crates.io-index" 5409 + checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" 5410 dependencies = [ 5411 "deranged", 5412 "itoa", 5413 "js-sys", 5414 "num-conv", 5415 "powerfmt", 5416 + "serde", 5417 "time-core", 5418 "time-macros", 5419 ] 5420 5421 [[package]] 5422 name = "time-core" 5423 + version = "0.1.4" 5424 source = "registry+https://github.com/rust-lang/crates.io-index" 5425 + checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" 5426 5427 [[package]] 5428 name = "time-macros" 5429 + version = "0.2.22" 5430 source = "registry+https://github.com/rust-lang/crates.io-index" 5431 + checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" 5432 dependencies = [ 5433 "num-conv", 5434 "time-core", ··· 5445 5446 [[package]] 5447 name = "tinystr" 5448 + version = "0.8.1" 5449 source = "registry+https://github.com/rust-lang/crates.io-index" 5450 + checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" 5451 dependencies = [ 5452 "displaydoc", 5453 "zerovec", ··· 5455 5456 [[package]] 5457 name = "tinyvec" 5458 + version = "1.9.0" 5459 source = "registry+https://github.com/rust-lang/crates.io-index" 5460 + checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" 5461 dependencies = [ 5462 "tinyvec_macros", 5463 ] ··· 5470 5471 [[package]] 5472 name = "tokio" 5473 + version = "1.47.1" 5474 source = "registry+https://github.com/rust-lang/crates.io-index" 5475 + checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" 5476 dependencies = [ 5477 + "backtrace", 5478 "bytes", 5479 + "io-uring", 5480 "libc", 5481 "mio", 5482 "pin-project-lite", 5483 "signal-hook-registry", 5484 + "slab", 5485 + "socket2 0.6.0", 5486 "tokio-macros", 5487 + "windows-sys 0.59.0", 5488 ] 5489 5490 [[package]] 5491 name = "tokio-macros" 5492 + version = "2.5.0" 5493 source = "registry+https://github.com/rust-lang/crates.io-index" 5494 + checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 5495 dependencies = [ 5496 "proc-macro2", 5497 "quote", 5498 + "syn 2.0.105", 5499 ] 5500 5501 [[package]] 5502 name = "tokio-rustls" 5503 + version = "0.26.2" 5504 source = "registry+https://github.com/rust-lang/crates.io-index" 5505 + checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" 5506 dependencies = [ 5507 "rustls", 5508 "tokio", ··· 5510 5511 [[package]] 5512 name = "tokio-stream" 5513 + version = "0.1.17" 5514 source = "registry+https://github.com/rust-lang/crates.io-index" 5515 + checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" 5516 dependencies = [ 5517 "futures-core", 5518 "pin-project-lite", ··· 5521 ] 5522 5523 [[package]] 5524 name = "tokio-util" 5525 + version = "0.7.16" 5526 source = "registry+https://github.com/rust-lang/crates.io-index" 5527 + checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" 5528 dependencies = [ 5529 "bytes", 5530 "futures-core", ··· 5536 5537 [[package]] 5538 name = "tokio-websockets" 5539 + version = "0.12.0" 5540 source = "registry+https://github.com/rust-lang/crates.io-index" 5541 + checksum = "3f29ba084eb43becc9864ba514b4a64f5f65b82f9a6ffbafa5436c1c80605f03" 5542 dependencies = [ 5543 "base64 0.22.1", 5544 "bytes", 5545 "futures-core", 5546 "futures-sink", 5547 + "getrandom 0.3.3", 5548 "http", 5549 "httparse", 5550 "rand 0.9.2", ··· 5573 dependencies = [ 5574 "serde", 5575 "serde_spanned", 5576 + "toml_datetime", 5577 + "toml_edit", 5578 ] 5579 5580 [[package]] ··· 5587 ] 5588 5589 [[package]] 5590 name = "toml_edit" 5591 version = "0.22.27" 5592 source = "registry+https://github.com/rust-lang/crates.io-index" 5593 checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" 5594 dependencies = [ 5595 + "indexmap 2.10.0", 5596 "serde", 5597 "serde_spanned", 5598 + "toml_datetime", 5599 "toml_write", 5600 "winnow", 5601 ] 5602 5603 [[package]] 5604 name = "toml_write" 5605 version = "0.1.2" 5606 source = "registry+https://github.com/rust-lang/crates.io-index" 5607 checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" 5608 5609 [[package]] 5610 name = "tower" 5611 + version = "0.5.2" 5612 source = "registry+https://github.com/rust-lang/crates.io-index" 5613 + checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 5614 dependencies = [ 5615 "futures-core", 5616 "futures-util", ··· 5623 5624 [[package]] 5625 name = "tower-http" 5626 + version = "0.6.6" 5627 source = "registry+https://github.com/rust-lang/crates.io-index" 5628 + checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" 5629 dependencies = [ 5630 + "bitflags", 5631 "bytes", 5632 "futures-util", 5633 "http", 5634 "http-body", 5635 "iri-string", 5636 "pin-project-lite", 5637 + "tower", 5638 "tower-layer", 5639 "tower-service", 5640 ] ··· 5653 5654 [[package]] 5655 name = "tracing" 5656 + version = "0.1.41" 5657 source = "registry+https://github.com/rust-lang/crates.io-index" 5658 + checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 5659 dependencies = [ 5660 "log", 5661 "pin-project-lite", ··· 5665 5666 [[package]] 5667 name = "tracing-attributes" 5668 + version = "0.1.30" 5669 source = "registry+https://github.com/rust-lang/crates.io-index" 5670 + checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" 5671 dependencies = [ 5672 "proc-macro2", 5673 "quote", 5674 + "syn 2.0.105", 5675 ] 5676 5677 [[package]] 5678 name = "tracing-core" 5679 + version = "0.1.34" 5680 source = "registry+https://github.com/rust-lang/crates.io-index" 5681 + checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" 5682 dependencies = [ 5683 "once_cell", 5684 "valuable", ··· 5707 5708 [[package]] 5709 name = "tracing-subscriber" 5710 + version = "0.3.19" 5711 source = "registry+https://github.com/rust-lang/crates.io-index" 5712 + checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" 5713 dependencies = [ 5714 "matchers", 5715 "nu-ansi-term", 5716 "once_cell", 5717 + "regex", 5718 "sharded-slab", 5719 "smallvec", 5720 "thread_local", ··· 5731 dependencies = [ 5732 "proc-macro2", 5733 "quote", 5734 + "syn 2.0.105", 5735 ] 5736 5737 [[package]] ··· 5742 5743 [[package]] 5744 name = "triomphe" 5745 + version = "0.1.14" 5746 source = "registry+https://github.com/rust-lang/crates.io-index" 5747 + checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" 5748 5749 [[package]] 5750 name = "try-lock" ··· 5754 5755 [[package]] 5756 name = "typenum" 5757 + version = "1.18.0" 5758 source = "registry+https://github.com/rust-lang/crates.io-index" 5759 + checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 5760 5761 [[package]] 5762 name = "ucd-parse" ··· 5780 checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" 5781 5782 [[package]] 5783 name = "unicase" 5784 + version = "2.8.1" 5785 source = "registry+https://github.com/rust-lang/crates.io-index" 5786 + checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" 5787 5788 [[package]] 5789 name = "unicode-ident" 5790 + version = "1.0.18" 5791 source = "registry+https://github.com/rust-lang/crates.io-index" 5792 + checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 5793 5794 [[package]] 5795 name = "unicode-normalization" 5796 + version = "0.1.24" 5797 source = "registry+https://github.com/rust-lang/crates.io-index" 5798 + checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" 5799 dependencies = [ 5800 "tinyvec", 5801 ] 5802 5803 [[package]] 5804 name = "unicode-xid" 5805 version = "0.2.6" 5806 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5849 checksum = "802d2051a700e3ec894c79f80d2705b69d85844dafbbe5d1a92776f8f48b563a" 5850 dependencies = [ 5851 "quote", 5852 + "syn 2.0.105", 5853 ] 5854 5855 [[package]] ··· 5880 "proc-macro2", 5881 "quote", 5882 "serde", 5883 + "syn 2.0.105", 5884 "toml 0.5.11", 5885 "uniffi_meta", 5886 ] ··· 5941 5942 [[package]] 5943 name = "ureq" 5944 + version = "3.1.2" 5945 source = "registry+https://github.com/rust-lang/crates.io-index" 5946 + checksum = "99ba1025f18a4a3fc3e9b48c868e9beb4f24f4b4b1a325bada26bd4119f46537" 5947 dependencies = [ 5948 "base64 0.22.1", 5949 "flate2", 5950 "log", 5951 "percent-encoding", 5952 "rustls", 5953 + "rustls-pemfile", 5954 "rustls-pki-types", 5955 "ureq-proto", 5956 "utf-8", ··· 5959 5960 [[package]] 5961 name = "ureq-proto" 5962 + version = "0.5.2" 5963 source = "registry+https://github.com/rust-lang/crates.io-index" 5964 + checksum = "60b4531c118335662134346048ddb0e54cc86bd7e81866757873055f0e38f5d2" 5965 dependencies = [ 5966 "base64 0.22.1", 5967 "http", ··· 5971 5972 [[package]] 5973 name = "url" 5974 + version = "2.5.4" 5975 source = "registry+https://github.com/rust-lang/crates.io-index" 5976 + checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 5977 dependencies = [ 5978 "form_urlencoded", 5979 "idna", 5980 "percent-encoding", 5981 "serde", 5982 ] 5983 5984 [[package]] ··· 6005 source = "registry+https://github.com/rust-lang/crates.io-index" 6006 checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" 6007 dependencies = [ 6008 + "getrandom 0.2.16", 6009 "serde", 6010 "wasm-bindgen", 6011 ] ··· 6045 6046 [[package]] 6047 name = "wasi" 6048 + version = "0.14.2+wasi-0.2.4" 6049 source = "registry+https://github.com/rust-lang/crates.io-index" 6050 + checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 6051 dependencies = [ 6052 + "wit-bindgen-rt", 6053 ] 6054 6055 [[package]] ··· 6063 6064 [[package]] 6065 name = "wasm-bindgen" 6066 + version = "0.2.100" 6067 source = "registry+https://github.com/rust-lang/crates.io-index" 6068 + checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 6069 dependencies = [ 6070 "cfg-if", 6071 "once_cell", 6072 "rustversion", 6073 "wasm-bindgen-macro", 6074 + ] 6075 + 6076 + [[package]] 6077 + name = "wasm-bindgen-backend" 6078 + version = "0.2.100" 6079 + source = "registry+https://github.com/rust-lang/crates.io-index" 6080 + checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 6081 + dependencies = [ 6082 + "bumpalo", 6083 + "log", 6084 + "proc-macro2", 6085 + "quote", 6086 + "syn 2.0.105", 6087 "wasm-bindgen-shared", 6088 ] 6089 6090 [[package]] 6091 name = "wasm-bindgen-futures" 6092 + version = "0.4.50" 6093 source = "registry+https://github.com/rust-lang/crates.io-index" 6094 + checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 6095 dependencies = [ 6096 "cfg-if", 6097 "js-sys", ··· 6102 6103 [[package]] 6104 name = "wasm-bindgen-macro" 6105 + version = "0.2.100" 6106 source = "registry+https://github.com/rust-lang/crates.io-index" 6107 + checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 6108 dependencies = [ 6109 "quote", 6110 "wasm-bindgen-macro-support", ··· 6112 6113 [[package]] 6114 name = "wasm-bindgen-macro-support" 6115 + version = "0.2.100" 6116 source = "registry+https://github.com/rust-lang/crates.io-index" 6117 + checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 6118 dependencies = [ 6119 "proc-macro2", 6120 "quote", 6121 + "syn 2.0.105", 6122 + "wasm-bindgen-backend", 6123 "wasm-bindgen-shared", 6124 ] 6125 6126 [[package]] 6127 name = "wasm-bindgen-shared" 6128 + version = "0.2.100" 6129 source = "registry+https://github.com/rust-lang/crates.io-index" 6130 + checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 6131 dependencies = [ 6132 "unicode-ident", 6133 ] ··· 6147 6148 [[package]] 6149 name = "web-sys" 6150 + version = "0.3.77" 6151 source = "registry+https://github.com/rust-lang/crates.io-index" 6152 + checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 6153 dependencies = [ 6154 "js-sys", 6155 "wasm-bindgen", ··· 6167 6168 [[package]] 6169 name = "webpki-roots" 6170 + version = "1.0.2" 6171 source = "registry+https://github.com/rust-lang/crates.io-index" 6172 + checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" 6173 dependencies = [ 6174 "rustls-pki-types", 6175 ] ··· 6185 6186 [[package]] 6187 name = "widestring" 6188 + version = "1.2.0" 6189 source = "registry+https://github.com/rust-lang/crates.io-index" 6190 + checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" 6191 6192 [[package]] 6193 name = "winapi" ··· 6207 6208 [[package]] 6209 name = "winapi-util" 6210 + version = "0.1.9" 6211 source = "registry+https://github.com/rust-lang/crates.io-index" 6212 + checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 6213 dependencies = [ 6214 + "windows-sys 0.59.0", 6215 ] 6216 6217 [[package]] ··· 6226 source = "registry+https://github.com/rust-lang/crates.io-index" 6227 checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" 6228 dependencies = [ 6229 + "windows-collections", 6230 + "windows-core", 6231 + "windows-future", 6232 "windows-link 0.1.3", 6233 + "windows-numerics", 6234 ] 6235 6236 [[package]] ··· 6239 source = "registry+https://github.com/rust-lang/crates.io-index" 6240 checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" 6241 dependencies = [ 6242 + "windows-core", 6243 ] 6244 6245 [[package]] ··· 6251 "windows-implement", 6252 "windows-interface", 6253 "windows-link 0.1.3", 6254 + "windows-result", 6255 + "windows-strings", 6256 ] 6257 6258 [[package]] ··· 6261 source = "registry+https://github.com/rust-lang/crates.io-index" 6262 checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" 6263 dependencies = [ 6264 + "windows-core", 6265 "windows-link 0.1.3", 6266 + "windows-threading", 6267 ] 6268 6269 [[package]] 6270 name = "windows-implement" 6271 + version = "0.60.0" 6272 source = "registry+https://github.com/rust-lang/crates.io-index" 6273 + checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" 6274 dependencies = [ 6275 "proc-macro2", 6276 "quote", 6277 + "syn 2.0.105", 6278 ] 6279 6280 [[package]] 6281 name = "windows-interface" 6282 + version = "0.59.1" 6283 source = "registry+https://github.com/rust-lang/crates.io-index" 6284 + checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" 6285 dependencies = [ 6286 "proc-macro2", 6287 "quote", 6288 + "syn 2.0.105", 6289 ] 6290 6291 [[package]] ··· 6296 6297 [[package]] 6298 name = "windows-link" 6299 + version = "0.2.0" 6300 source = "registry+https://github.com/rust-lang/crates.io-index" 6301 + checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" 6302 6303 [[package]] 6304 name = "windows-numerics" ··· 6306 source = "registry+https://github.com/rust-lang/crates.io-index" 6307 checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" 6308 dependencies = [ 6309 + "windows-core", 6310 "windows-link 0.1.3", 6311 ] 6312 6313 [[package]] 6314 name = "windows-result" 6315 version = "0.3.4" 6316 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6320 ] 6321 6322 [[package]] 6323 name = "windows-strings" 6324 version = "0.4.2" 6325 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6329 ] 6330 6331 [[package]] 6332 name = "windows-sys" 6333 version = "0.48.0" 6334 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6356 ] 6357 6358 [[package]] 6359 name = "windows-targets" 6360 version = "0.48.5" 6361 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6379 "windows_aarch64_gnullvm 0.52.6", 6380 "windows_aarch64_msvc 0.52.6", 6381 "windows_i686_gnu 0.52.6", 6382 + "windows_i686_gnullvm", 6383 "windows_i686_msvc 0.52.6", 6384 "windows_x86_64_gnu 0.52.6", 6385 "windows_x86_64_gnullvm 0.52.6", ··· 6387 ] 6388 6389 [[package]] 6390 name = "windows-threading" 6391 version = "0.1.0" 6392 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6396 ] 6397 6398 [[package]] 6399 name = "windows_aarch64_gnullvm" 6400 version = "0.48.5" 6401 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6408 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 6409 6410 [[package]] 6411 name = "windows_aarch64_msvc" 6412 version = "0.48.5" 6413 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6420 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 6421 6422 [[package]] 6423 name = "windows_i686_gnu" 6424 version = "0.48.5" 6425 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6430 version = "0.52.6" 6431 source = "registry+https://github.com/rust-lang/crates.io-index" 6432 checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 6433 6434 [[package]] 6435 name = "windows_i686_gnullvm" ··· 6438 checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 6439 6440 [[package]] 6441 name = "windows_i686_msvc" 6442 version = "0.48.5" 6443 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6450 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 6451 6452 [[package]] 6453 name = "windows_x86_64_gnu" 6454 version = "0.48.5" 6455 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6462 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 6463 6464 [[package]] 6465 name = "windows_x86_64_gnullvm" 6466 version = "0.48.5" 6467 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6474 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 6475 6476 [[package]] 6477 name = "windows_x86_64_msvc" 6478 version = "0.48.5" 6479 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6484 version = "0.52.6" 6485 source = "registry+https://github.com/rust-lang/crates.io-index" 6486 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 6487 6488 [[package]] 6489 name = "winnow" 6490 + version = "0.7.12" 6491 source = "registry+https://github.com/rust-lang/crates.io-index" 6492 + checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" 6493 dependencies = [ 6494 "memchr", 6495 ] ··· 6510 source = "registry+https://github.com/rust-lang/crates.io-index" 6511 checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" 6512 dependencies = [ 6513 + "bitflags", 6514 + ] 6515 + 6516 + [[package]] 6517 + name = "wit-bindgen-rt" 6518 + version = "0.39.0" 6519 + source = "registry+https://github.com/rust-lang/crates.io-index" 6520 + checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 6521 + dependencies = [ 6522 + "bitflags", 6523 ] 6524 6525 [[package]] 6526 name = "wmi" 6527 + version = "0.17.2" 6528 source = "registry+https://github.com/rust-lang/crates.io-index" 6529 + checksum = "3d3de777dce4cbcdc661d5d18e78ce4b46a37adc2bb7c0078a556c7f07bcce2f" 6530 dependencies = [ 6531 "chrono", 6532 "futures", 6533 "log", 6534 "serde", 6535 + "thiserror 2.0.16", 6536 + "windows", 6537 + "windows-core", 6538 ] 6539 6540 [[package]] 6541 name = "writeable" 6542 + version = "0.6.1" 6543 source = "registry+https://github.com/rust-lang/crates.io-index" 6544 + checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" 6545 6546 [[package]] 6547 name = "ws_stream_wasm" ··· 6556 "pharos", 6557 "rustc_version", 6558 "send_wrapper", 6559 + "thiserror 2.0.16", 6560 "wasm-bindgen", 6561 "wasm-bindgen-futures", 6562 "web-sys", ··· 6564 6565 [[package]] 6566 name = "wstd" 6567 + version = "0.5.6" 6568 source = "registry+https://github.com/rust-lang/crates.io-index" 6569 + checksum = "d0736607b57fcb58dd3148cf34d6a6ca63ba041fde8a12ab3f2c48ddf6d11877" 6570 dependencies = [ 6571 + "async-task", 6572 "http", 6573 "itoa", 6574 "pin-project-lite", 6575 "serde", 6576 "serde_json", 6577 "slab", 6578 + "wasip2", 6579 "wstd-macro", 6580 ] 6581 6582 [[package]] 6583 name = "wstd-macro" 6584 + version = "0.5.6" 6585 source = "registry+https://github.com/rust-lang/crates.io-index" 6586 + checksum = "cb142608f932022fa7d155d8ed99649d02c56a50532e71913a5a03c7c4e288d3" 6587 dependencies = [ 6588 "quote", 6589 + "syn 2.0.105", 6590 ] 6591 6592 [[package]] ··· 6635 ] 6636 6637 [[package]] 6638 name = "xml-no-std" 6639 version = "0.8.26" 6640 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6642 6643 [[package]] 6644 name = "xml-rs" 6645 + version = "0.8.27" 6646 source = "registry+https://github.com/rust-lang/crates.io-index" 6647 + checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" 6648 6649 [[package]] 6650 name = "xmltree" ··· 6656 ] 6657 6658 [[package]] 6659 name = "yasna" 6660 version = "0.5.2" 6661 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 6666 6667 [[package]] 6668 name = "yoke" 6669 + version = "0.8.0" 6670 source = "registry+https://github.com/rust-lang/crates.io-index" 6671 + checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" 6672 dependencies = [ 6673 + "serde", 6674 "stable_deref_trait", 6675 "yoke-derive", 6676 "zerofrom", ··· 6678 6679 [[package]] 6680 name = "yoke-derive" 6681 + version = "0.8.0" 6682 source = "registry+https://github.com/rust-lang/crates.io-index" 6683 + checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" 6684 dependencies = [ 6685 "proc-macro2", 6686 "quote", 6687 + "syn 2.0.105", 6688 "synstructure", 6689 ] 6690 ··· 6696 6697 [[package]] 6698 name = "zerocopy" 6699 + version = "0.8.26" 6700 source = "registry+https://github.com/rust-lang/crates.io-index" 6701 + checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" 6702 dependencies = [ 6703 "zerocopy-derive", 6704 ] 6705 6706 [[package]] 6707 name = "zerocopy-derive" 6708 + version = "0.8.26" 6709 source = "registry+https://github.com/rust-lang/crates.io-index" 6710 + checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" 6711 dependencies = [ 6712 "proc-macro2", 6713 "quote", 6714 + "syn 2.0.105", 6715 ] 6716 6717 [[package]] ··· 6731 dependencies = [ 6732 "proc-macro2", 6733 "quote", 6734 + "syn 2.0.105", 6735 "synstructure", 6736 ] 6737 6738 [[package]] 6739 name = "zeroize" 6740 + version = "1.8.1" 6741 source = "registry+https://github.com/rust-lang/crates.io-index" 6742 + checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 6743 dependencies = [ 6744 "zeroize_derive", 6745 ] 6746 6747 [[package]] 6748 name = "zeroize_derive" 6749 + version = "1.4.2" 6750 source = "registry+https://github.com/rust-lang/crates.io-index" 6751 + checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" 6752 dependencies = [ 6753 "proc-macro2", 6754 "quote", 6755 + "syn 2.0.105", 6756 ] 6757 6758 [[package]] 6759 name = "zerotrie" 6760 + version = "0.2.2" 6761 source = "registry+https://github.com/rust-lang/crates.io-index" 6762 + checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" 6763 dependencies = [ 6764 "displaydoc", 6765 "yoke", ··· 6768 6769 [[package]] 6770 name = "zerovec" 6771 + version = "0.11.4" 6772 source = "registry+https://github.com/rust-lang/crates.io-index" 6773 + checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" 6774 dependencies = [ 6775 "yoke", 6776 "zerofrom", ··· 6779 6780 [[package]] 6781 name = "zerovec-derive" 6782 + version = "0.11.1" 6783 source = "registry+https://github.com/rust-lang/crates.io-index" 6784 + checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" 6785 dependencies = [ 6786 "proc-macro2", 6787 "quote", 6788 + "syn 2.0.105", 6789 ] 6790 6791 [[package]] ··· 6796 dependencies = [ 6797 "arbitrary", 6798 "crc32fast", 6799 + "indexmap 2.10.0", 6800 "memchr", 6801 ]
+1 -1
Cargo.toml
··· 1 [workspace] 2 resolver = "3" 3 - members = ["rust/export-c2pa-schema", "rust/iroh-streamplace", "rust/sp-analytics"] 4 exclude = ["subprojects/c2pa_go"]
··· 1 [workspace] 2 resolver = "3" 3 + members = ["rust/export-c2pa-schema", "rust/iroh-streamplace"] 4 exclude = ["subprojects/c2pa_go"]
+5 -4
Makefile
··· 385 && sed -i.bak 's/PlaceStreamMultistreamTarget\.Main/PlaceStreamMultistreamTarget\.Record/' $$(find ./js/streamplace/src/lexicons/types/place/stream -type f) \ 386 && sed -i.bak 's/PlaceStreamChatProfile\.Main/PlaceStreamChatProfile\.Record/' $$(find ./js/streamplace/src/lexicons/types/place/stream -type f) \ 387 && for x in $$(find ./js/streamplace/src/lexicons -type f -name '*.ts'); do \ 388 - echo 'import { AppBskyRichtextFacet, AppBskyGraphBlock, ComAtprotoRepoStrongRef, AppBskyActorDefs, ComAtprotoSyncListRepos, AppBskyActorGetProfile, AppBskyFeedGetFeedSkeleton, ComAtprotoIdentityResolveHandle, ComAtprotoModerationCreateReport, ComAtprotoRepoCreateRecord, ComAtprotoRepoDeleteRecord, ComAtprotoRepoDescribeRepo, ComAtprotoRepoGetRecord, ComAtprotoRepoListRecords, ComAtprotoRepoPutRecord, ComAtprotoRepoUploadBlob, ComAtprotoServerDescribeServer, ComAtprotoSyncGetRecord, ComAtprotoSyncListReposComAtprotoRepoCreateRecord, ComAtprotoRepoDeleteRecord, ComAtprotoRepoGetRecord, ComAtprotoRepoListRecords, ComAtprotoIdentityRefreshIdentity } from "@atproto/api"' >> $$x; \ 389 done \ 390 - && npx prettier --write $$(find ./js/streamplace/src/lexicons -type f -name '*.ts') \ 391 && find . | grep bak$$ | xargs rm 392 393 .PHONY: md-lexicons 394 md-lexicons: 395 - pnpm exec lexmd \ 396 ./lexicons \ 397 .build/temp \ 398 subprojects/atproto/lexicons \ ··· 437 .PHONY: ci-lexicons 438 ci-lexicons: 439 $(MAKE) lexicons \ 440 - && if ! git diff --exit-code >/dev/null; then echo "lexicons are out of date, run 'make lexicons' to fix"; exit 1; fi 441 442 # _______ ______ _____ _______ _____ _ _ _____ 443 # |__ __| ____|/ ____|__ __|_ _| \ | |/ ____|
··· 385 && sed -i.bak 's/PlaceStreamMultistreamTarget\.Main/PlaceStreamMultistreamTarget\.Record/' $$(find ./js/streamplace/src/lexicons/types/place/stream -type f) \ 386 && sed -i.bak 's/PlaceStreamChatProfile\.Main/PlaceStreamChatProfile\.Record/' $$(find ./js/streamplace/src/lexicons/types/place/stream -type f) \ 387 && for x in $$(find ./js/streamplace/src/lexicons -type f -name '*.ts'); do \ 388 + echo 'import { ComAtprotoSyncGetRepo, AppBskyRichtextFacet, AppBskyGraphBlock, ComAtprotoRepoStrongRef, AppBskyActorDefs, ComAtprotoSyncListRepos, AppBskyActorGetProfile, AppBskyFeedGetFeedSkeleton, ComAtprotoIdentityResolveHandle, ComAtprotoModerationCreateReport, ComAtprotoRepoCreateRecord, ComAtprotoRepoDeleteRecord, ComAtprotoRepoDescribeRepo, ComAtprotoRepoGetRecord, ComAtprotoRepoListRecords, ComAtprotoRepoPutRecord, ComAtprotoRepoUploadBlob, ComAtprotoServerDescribeServer, ComAtprotoSyncGetRecord, ComAtprotoSyncListReposComAtprotoRepoCreateRecord, ComAtprotoRepoDeleteRecord, ComAtprotoRepoGetRecord, ComAtprotoRepoListRecords, ComAtprotoIdentityRefreshIdentity } from "@atproto/api"' >> $$x; \ 389 done \ 390 + && npx prettier --ignore-unknown --write $$(find ./js/streamplace/src/lexicons -type f -name '*.ts') \ 391 && find . | grep bak$$ | xargs rm 392 393 .PHONY: md-lexicons 394 md-lexicons: 395 + find "js/docs/src/content/docs/lex-reference" -type f -name '*.md' -delete \ 396 + && pnpm exec lexmd \ 397 ./lexicons \ 398 .build/temp \ 399 subprojects/atproto/lexicons \ ··· 438 .PHONY: ci-lexicons 439 ci-lexicons: 440 $(MAKE) lexicons \ 441 + && if ! git diff --exit-code >/dev/null; then echo "lexicons are out of date, run 'make lexicons' to fix"; git diff; exit 1; fi 442 443 # _______ ______ _____ _______ _____ _ _ _____ 444 # |__ __| ____|/ ____|__ __|_ _| \ | |/ ____|
+14 -14
go.mod
··· 30 github.com/go-gst/go-glib v1.4.0 31 github.com/go-gst/go-gst v1.4.0 32 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 33 - github.com/golang/glog v1.2.5 34 github.com/golangci/golangci-lint/v2 v2.1.6 35 github.com/google/uuid v1.6.0 36 github.com/gorilla/websocket v1.5.3 ··· 54 github.com/pion/webrtc/v4 v4.0.11 55 github.com/piprate/json-gold v0.5.0 56 github.com/prometheus/client_golang v1.23.0 57 github.com/rs/cors v1.11.1 58 github.com/samber/slog-http v1.4.0 59 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e 60 github.com/slok/go-http-metrics v0.13.0 61 github.com/starttoaster/prometheus-exporter-scraper v0.0.1 62 github.com/streamplace/atproto-oauth-golang v0.0.0-20250619231223-a9c04fb888ac 63 - github.com/streamplace/oatproxy v0.0.0-20260112011721-d74b4913c93f 64 github.com/stretchr/testify v1.11.1 65 github.com/tdewolff/canvas v0.0.0-20250728095813-50d4cb1eee71 66 github.com/whyrusleeping/cbor-gen v0.3.1 67 github.com/whyrusleeping/go-did v0.0.0-20230824162731-404d1707d5d6 68 gitlab.com/gitlab-org/release-cli v0.18.0 69 - go.opentelemetry.io/otel v1.38.0 70 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 71 - go.opentelemetry.io/otel/sdk v1.38.0 72 go.uber.org/goleak v1.3.0 73 golang.org/x/image v0.30.0 74 golang.org/x/net v0.47.0 ··· 105 cloud.google.com/go v0.116.0 // indirect 106 cloud.google.com/go/auth v0.15.0 // indirect 107 cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect 108 - cloud.google.com/go/compute/metadata v0.9.0 // indirect 109 cloud.google.com/go/firestore v1.16.0 // indirect 110 cloud.google.com/go/iam v1.2.0 // indirect 111 cloud.google.com/go/longrunning v0.6.0 // indirect ··· 425 github.com/rabbitmq/amqp091-go v1.8.0 // indirect 426 github.com/rabbitmq/rabbitmq-stream-go-client v1.1.1 // indirect 427 github.com/raeperd/recvcheck v0.2.0 // indirect 428 - github.com/rivo/uniseg v0.4.7 // indirect 429 github.com/rogpeppe/go-internal v1.14.1 // indirect 430 github.com/rs/xid v1.5.0 // indirect 431 github.com/russross/blackfriday/v2 v2.1.0 // indirect ··· 499 go-simpler.org/sloglint v0.11.0 // indirect 500 go.augendre.info/fatcontext v0.8.0 // indirect 501 go.opencensus.io v0.24.0 // indirect 502 - go.opentelemetry.io/auto/sdk v1.2.1 // indirect 503 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect 504 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect 505 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect 506 - go.opentelemetry.io/otel/metric v1.38.0 // indirect 507 - go.opentelemetry.io/otel/trace v1.38.0 // indirect 508 go.opentelemetry.io/proto/otlp v1.5.0 // indirect 509 go.uber.org/atomic v1.11.0 // indirect 510 go.uber.org/automaxprocs v1.6.0 // indirect ··· 514 golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect 515 golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect 516 golang.org/x/mod v0.29.0 // indirect 517 - golang.org/x/oauth2 v0.32.0 // indirect 518 golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect 519 golang.org/x/text v0.31.0 // indirect 520 gonum.org/v1/plot v0.16.0 // indirect 521 google.golang.org/appengine/v2 v2.0.2 // indirect 522 google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect 523 - google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda // indirect 524 - google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda // indirect 525 - google.golang.org/grpc v1.78.0 // indirect 526 - google.golang.org/protobuf v1.36.11 // indirect 527 gopkg.in/inf.v0 v0.9.1 // indirect 528 gopkg.in/ini.v1 v1.67.0 // indirect 529 gopkg.in/warnings.v0 v0.1.2 // indirect
··· 30 github.com/go-gst/go-glib v1.4.0 31 github.com/go-gst/go-gst v1.4.0 32 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 33 + github.com/golang/glog v1.2.4 34 github.com/golangci/golangci-lint/v2 v2.1.6 35 github.com/google/uuid v1.6.0 36 github.com/gorilla/websocket v1.5.3 ··· 54 github.com/pion/webrtc/v4 v4.0.11 55 github.com/piprate/json-gold v0.5.0 56 github.com/prometheus/client_golang v1.23.0 57 + github.com/rivo/uniseg v0.4.7 58 github.com/rs/cors v1.11.1 59 github.com/samber/slog-http v1.4.0 60 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e 61 github.com/slok/go-http-metrics v0.13.0 62 github.com/starttoaster/prometheus-exporter-scraper v0.0.1 63 github.com/streamplace/atproto-oauth-golang v0.0.0-20250619231223-a9c04fb888ac 64 + github.com/streamplace/oatproxy v0.0.0-20260130124113-420429019d3b 65 github.com/stretchr/testify v1.11.1 66 github.com/tdewolff/canvas v0.0.0-20250728095813-50d4cb1eee71 67 github.com/whyrusleeping/cbor-gen v0.3.1 68 github.com/whyrusleeping/go-did v0.0.0-20230824162731-404d1707d5d6 69 gitlab.com/gitlab-org/release-cli v0.18.0 70 + go.opentelemetry.io/otel v1.36.0 71 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 72 + go.opentelemetry.io/otel/sdk v1.36.0 73 go.uber.org/goleak v1.3.0 74 golang.org/x/image v0.30.0 75 golang.org/x/net v0.47.0 ··· 106 cloud.google.com/go v0.116.0 // indirect 107 cloud.google.com/go/auth v0.15.0 // indirect 108 cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect 109 + cloud.google.com/go/compute/metadata v0.6.0 // indirect 110 cloud.google.com/go/firestore v1.16.0 // indirect 111 cloud.google.com/go/iam v1.2.0 // indirect 112 cloud.google.com/go/longrunning v0.6.0 // indirect ··· 426 github.com/rabbitmq/amqp091-go v1.8.0 // indirect 427 github.com/rabbitmq/rabbitmq-stream-go-client v1.1.1 // indirect 428 github.com/raeperd/recvcheck v0.2.0 // indirect 429 github.com/rogpeppe/go-internal v1.14.1 // indirect 430 github.com/rs/xid v1.5.0 // indirect 431 github.com/russross/blackfriday/v2 v2.1.0 // indirect ··· 499 go-simpler.org/sloglint v0.11.0 // indirect 500 go.augendre.info/fatcontext v0.8.0 // indirect 501 go.opencensus.io v0.24.0 // indirect 502 + go.opentelemetry.io/auto/sdk v1.1.0 // indirect 503 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect 504 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect 505 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect 506 + go.opentelemetry.io/otel/metric v1.36.0 // indirect 507 + go.opentelemetry.io/otel/trace v1.36.0 // indirect 508 go.opentelemetry.io/proto/otlp v1.5.0 // indirect 509 go.uber.org/atomic v1.11.0 // indirect 510 go.uber.org/automaxprocs v1.6.0 // indirect ··· 514 golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect 515 golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect 516 golang.org/x/mod v0.29.0 // indirect 517 + golang.org/x/oauth2 v0.30.0 // indirect 518 golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect 519 golang.org/x/text v0.31.0 // indirect 520 gonum.org/v1/plot v0.16.0 // indirect 521 google.golang.org/appengine/v2 v2.0.2 // indirect 522 google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect 523 + google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect 524 + google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect 525 + google.golang.org/grpc v1.71.0 // indirect 526 + google.golang.org/protobuf v1.36.7 // indirect 527 gopkg.in/inf.v0 v0.9.1 // indirect 528 gopkg.in/ini.v1 v1.67.0 // indirect 529 gopkg.in/warnings.v0 v0.1.2 // indirect
+2 -25
go.sum
··· 32 cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= 33 cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= 34 cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= 35 - cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= 36 - cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= 37 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 38 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 39 cloud.google.com/go/firestore v1.16.0 h1:YwmDHcyrxVRErWcgxunzEaZxtNbc8QoFYA/JOEwDPgc= ··· 531 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 532 github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc= 533 github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= 534 - github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= 535 - github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= 536 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 537 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 538 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= ··· 1323 github.com/streamplace/go-dpop v0.0.0-20250510031900-c897158a8ad4/go.mod h1:bGUXY9Wd4mnd+XUrOYZr358J2f6z9QO/dLhL1SsiD+0= 1324 github.com/streamplace/oatproxy v0.0.0-20260112011721-d74b4913c93f h1:hhbQ8CtcAZVlLit/r7b9QDK7qEgOth4hgE13xV6ViBI= 1325 github.com/streamplace/oatproxy v0.0.0-20260112011721-d74b4913c93f/go.mod h1:pXi24hA7xBHj8eEywX6wGqJOR9FaEYlGwQ/72rN6okw= 1326 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 1327 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 1328 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= ··· 1478 go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= 1479 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 1480 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 1481 - go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= 1482 - go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= 1483 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= 1484 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= 1485 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= 1486 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= 1487 go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= 1488 go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= 1489 - go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= 1490 - go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= 1491 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= 1492 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= 1493 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= ··· 1496 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= 1497 go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= 1498 go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= 1499 - go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= 1500 - go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= 1501 go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= 1502 go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= 1503 - go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= 1504 - go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= 1505 go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= 1506 go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= 1507 - go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= 1508 go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= 1509 go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= 1510 - go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= 1511 - go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= 1512 go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= 1513 go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= 1514 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= ··· 1664 golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= 1665 golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= 1666 golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= 1667 - golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= 1668 - golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= 1669 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 1670 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 1671 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= ··· 1925 google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4= 1926 google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0= 1927 google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU= 1928 - google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda h1:+2XxjfsAu6vqFxwGBRcHiMaDCuZiqXGDUDVWVtrFAnE= 1929 - google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= 1930 google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c= 1931 google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= 1932 - google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda h1:i/Q+bfisr7gq6feoJnS/DlpdwEL4ihp41fvRiM3Ork0= 1933 - google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= 1934 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 1935 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 1936 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= ··· 1946 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 1947 google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= 1948 google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= 1949 - google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= 1950 - google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= 1951 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 1952 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 1953 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= ··· 1967 google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 1968 google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= 1969 google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 1970 - google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= 1971 - google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= 1972 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 1973 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 1974 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
··· 32 cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= 33 cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= 34 cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= 35 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 36 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 37 cloud.google.com/go/firestore v1.16.0 h1:YwmDHcyrxVRErWcgxunzEaZxtNbc8QoFYA/JOEwDPgc= ··· 529 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 530 github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc= 531 github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= 532 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 533 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 534 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= ··· 1319 github.com/streamplace/go-dpop v0.0.0-20250510031900-c897158a8ad4/go.mod h1:bGUXY9Wd4mnd+XUrOYZr358J2f6z9QO/dLhL1SsiD+0= 1320 github.com/streamplace/oatproxy v0.0.0-20260112011721-d74b4913c93f h1:hhbQ8CtcAZVlLit/r7b9QDK7qEgOth4hgE13xV6ViBI= 1321 github.com/streamplace/oatproxy v0.0.0-20260112011721-d74b4913c93f/go.mod h1:pXi24hA7xBHj8eEywX6wGqJOR9FaEYlGwQ/72rN6okw= 1322 + github.com/streamplace/oatproxy v0.0.0-20260130124113-420429019d3b h1:BB/R1egvkEqZhGeKL3tqAlTn0mkoOaaMY6r6s18XJYA= 1323 + github.com/streamplace/oatproxy v0.0.0-20260130124113-420429019d3b/go.mod h1:pXi24hA7xBHj8eEywX6wGqJOR9FaEYlGwQ/72rN6okw= 1324 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 1325 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 1326 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= ··· 1476 go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= 1477 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 1478 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 1479 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= 1480 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= 1481 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= 1482 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= 1483 go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= 1484 go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= 1485 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= 1486 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= 1487 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= ··· 1490 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= 1491 go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= 1492 go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= 1493 go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= 1494 go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= 1495 go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= 1496 go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= 1497 go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= 1498 go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= 1499 go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= 1500 go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= 1501 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= ··· 1651 golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= 1652 golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= 1653 golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= 1654 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 1655 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 1656 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= ··· 1910 google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4= 1911 google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0= 1912 google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU= 1913 google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c= 1914 google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= 1915 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 1916 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 1917 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= ··· 1927 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 1928 google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= 1929 google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= 1930 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 1931 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 1932 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= ··· 1946 google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 1947 google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= 1948 google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 1949 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 1950 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 1951 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+2 -1
js/app/components/follow-button.tsx
··· 123 disabled={isFollowing === null} 124 loading={isFollowing === null} 125 leftIcon={!isFollowing && <Icon icon={Plus} size="sm" />} 126 > 127 {isFollowing === null 128 ? "Loading..." 129 : isFollowing 130 - ? "Unfollow" 131 : "Follow"} 132 </Button> 133 {error && <Text style={[{ color: "#c00" }, zero.ml[2]]}>{error}</Text>}
··· 123 disabled={isFollowing === null} 124 loading={isFollowing === null} 125 leftIcon={!isFollowing && <Icon icon={Plus} size="sm" />} 126 + hoverStyle={isFollowing ? { backgroundColor: "#dc2626" } : undefined} 127 > 128 {isFollowing === null 129 ? "Loading..." 130 : isFollowing 131 + ? "Following" 132 : "Follow"} 133 </Button> 134 {error && <Text style={[{ color: "#c00" }, zero.ml[2]]}>{error}</Text>}
+9 -5
js/app/components/home/cards.tsx
··· 49 style={[ 50 zero.flex.values[1], 51 { 52 backgroundColor: theme.colors.muted, 53 borderRadius, 54 overflow: "hidden", 55 borderColor: theme.colors.mutedForeground + 80, 56 - borderWidth: 2, 57 alignItems: layoutHorizontal ? "center" : "stretch", 58 flexDirection: layoutHorizontal ? "row" : "column", 59 }, 60 ]} 61 > 62 - {/* Thumbnail Section */} 63 <View 64 style={[ 65 { ··· 67 minWidth: layoutHorizontal ? "63%" : "100%", 68 // native seems to be unable to adjust widths properly? 69 maxHeight: !isWeb ? "76.5%" : "100%", 70 - borderRadius, 71 - overflow: "hidden", 72 position: "relative", 73 alignSelf: layoutHorizontal ? "auto" : "center", 74 backgroundColor: theme.colors.card, ··· 77 > 78 <Image 79 source={{ uri: `${url}/${thumbnailUrl}`, width: 160, height: 90 }} 80 - style={{ width: "100%", height: "100%", aspectRatio: 16 / 9 }} 81 resizeMode="contain" 82 /> 83 {isLive && ( ··· 193 ]} 194 numberOfLines={1} 195 ellipsizeMode="tail" 196 > 197 @{streamerName} 198 </Text>
··· 49 style={[ 50 zero.flex.values[1], 51 { 52 + borderCurve: "continuous", 53 backgroundColor: theme.colors.muted, 54 borderRadius, 55 overflow: "hidden", 56 borderColor: theme.colors.mutedForeground + 80, 57 + borderWidth: isWeb ? 1 : 0, 58 alignItems: layoutHorizontal ? "center" : "stretch", 59 flexDirection: layoutHorizontal ? "row" : "column", 60 }, 61 ]} 62 > 63 + {/* Thumbnail */} 64 <View 65 style={[ 66 { ··· 68 minWidth: layoutHorizontal ? "63%" : "100%", 69 // native seems to be unable to adjust widths properly? 70 maxHeight: !isWeb ? "76.5%" : "100%", 71 position: "relative", 72 alignSelf: layoutHorizontal ? "auto" : "center", 73 backgroundColor: theme.colors.card, ··· 76 > 77 <Image 78 source={{ uri: `${url}/${thumbnailUrl}`, width: 160, height: 90 }} 79 + style={{ 80 + width: "100%", 81 + height: "100%", 82 + aspectRatio: 16 / 9, 83 + }} 84 resizeMode="contain" 85 /> 86 {isLive && ( ··· 196 ]} 197 numberOfLines={1} 198 ellipsizeMode="tail" 199 + leading="tight" 200 > 201 @{streamerName} 202 </Text>
-2
js/app/components/live-dashboard/bento-grid.tsx
··· 155 streamTitle={ 156 profile?.displayName || profile?.handle || "Live Stream" 157 } 158 - viewers={viewers || 0} 159 uptime={getUptime()} 160 bitrate={getBitrate()} 161 timeBetweenSegments={segmentTiming.timeBetweenSegments || 0} ··· 235 streamTitle={ 236 profile?.displayName || profile?.handle || "Live Stream" 237 } 238 - viewers={viewers || 0} 239 uptime={getUptime()} 240 bitrate={getBitrate()} 241 timeBetweenSegments={segmentTiming.timeBetweenSegments || 0}
··· 155 streamTitle={ 156 profile?.displayName || profile?.handle || "Live Stream" 157 } 158 uptime={getUptime()} 159 bitrate={getBitrate()} 160 timeBetweenSegments={segmentTiming.timeBetweenSegments || 0} ··· 234 streamTitle={ 235 profile?.displayName || profile?.handle || "Live Stream" 236 } 237 uptime={getUptime()} 238 bitrate={getBitrate()} 239 timeBetweenSegments={segmentTiming.timeBetweenSegments || 0}
+7 -3
js/app/components/live-dashboard/live-selector.tsx
··· 57 if (selectedMode === "streamkey") { 58 return ( 59 <View flex={1} style={[flex.grow[1], { width: "100%" }]}> 60 - <View padding="md" direction="row" justify="between" align="end"> 61 - <Button variant="ghost" onPress={() => setSelectedMode(null)}> 62 โ† Back 63 </Button> 64 <Text variant="h4" weight="bold"> 65 Stream from OBS 66 </Text> 67 - <Button variant="ghost" style={{ opacity: 0 }}> 68 โ† Back 69 </Button> 70 </View>
··· 57 if (selectedMode === "streamkey") { 58 return ( 59 <View flex={1} style={[flex.grow[1], { width: "100%" }]}> 60 + <View padding="md" direction="row" justify="around" align="start"> 61 + <Button 62 + variant="ghost" 63 + width="min" 64 + onPress={() => setSelectedMode(null)} 65 + > 66 โ† Back 67 </Button> 68 <Text variant="h4" weight="bold"> 69 Stream from OBS 70 </Text> 71 + <Button variant="ghost" width="min" style={{ opacity: 0 }}> 72 โ† Back 73 </Button> 74 </View>
+82 -14
js/app/components/live-dashboard/livestream-panel.tsx
··· 1 import { 2 Button, 3 Checkbox, 4 ContentMetadataForm, 5 Dashboard, 6 formatHandle, 7 formatHandleWithAt, 8 Input, 9 Textarea, 10 Tooltip, 11 useCreateStreamRecord, ··· 15 useUrl, 16 zero, 17 } from "@streamplace/components"; 18 - import { ImagePlus, X } from "lucide-react-native"; 19 import { useCallback, useEffect, useMemo, useState } from "react"; 20 import { 21 Image, 22 Platform, 23 ScrollView, 24 - Text, 25 TouchableOpacity, 26 View, 27 } from "react-native"; ··· 80 selectedImage, 81 onImageSelect, 82 onImageRemove, 83 }: { 84 selectedImage?: string | File | Blob; 85 onImageSelect?: () => void; 86 onImageRemove?: () => void; 87 }) => { 88 const imageUrl = useMemo(() => { 89 if (!selectedImage) return undefined; ··· 150 </TouchableOpacity> 151 </View> 152 ) : ( 153 - <TouchableOpacity onPress={onImageSelect} style={containerStyle}> 154 - <ImagePlus size={48} color="#6b7280" /> 155 - <Text style={[text.gray[400], { marginTop: 8, fontSize: 14 }]}> 156 - Add thumbnail image 157 - </Text> 158 - <Text style={[text.gray[500], { fontSize: 12, marginTop: 4 }]}> 159 - Optional โ€ข JPG, PNG up to 975KB 160 - </Text> 161 - </TouchableOpacity> 162 )} 163 </View> 164 ); 165 }; ··· 185 186 const [createPost, setCreatePost] = useState(true); 187 const [sendPushNotification, setSendPushNotification] = useState(true); 188 - const [canonicalUrl, setCanonicalUrl] = useState<string>( 189 - livestream?.record.canonicalUrl || "", 190 - ); 191 const defaultCanonicalUrl = useMemo(() => { 192 return `${url}/${profile && formatHandle(profile)}`; 193 }, [url, profile?.handle]); ··· 196 if (!livestream) { 197 return; 198 } 199 if ( 200 livestream.record.canonicalUrl && 201 livestream.record.canonicalUrl !== defaultCanonicalUrl 202 ) { 203 setCanonicalUrl(livestream.record.canonicalUrl); 204 } 205 if ( 206 typeof livestream.record.notificationSettings?.pushNotification === 207 "boolean" ··· 210 livestream.record.notificationSettings.pushNotification, 211 ); 212 } 213 setCreatePost(typeof livestream.record.post !== "undefined"); 214 }, [livestream, defaultCanonicalUrl]); 215 ··· 319 const handleImageRemove = useCallback(() => { 320 setSelectedImage(undefined); 321 }, []); 322 323 const disabled = useMemo( 324 () => !userIsLive || loading || title.trim() === "", ··· 569 selectedImage={selectedImage} 570 onImageSelect={handleImageSelect} 571 onImageRemove={handleImageRemove} 572 /> 573 )} 574
··· 1 import { 2 + Admonition, 3 Button, 4 Checkbox, 5 ContentMetadataForm, 6 Dashboard, 7 formatHandle, 8 formatHandleWithAt, 9 + getBlob, 10 Input, 11 + resolveDIDDocument, 12 + Text, 13 Textarea, 14 Tooltip, 15 useCreateStreamRecord, ··· 19 useUrl, 20 zero, 21 } from "@streamplace/components"; 22 + import { ArrowRight, ImagePlus, X } from "lucide-react-native"; 23 import { useCallback, useEffect, useMemo, useState } from "react"; 24 import { 25 Image, 26 Platform, 27 + Pressable, 28 ScrollView, 29 TouchableOpacity, 30 View, 31 } from "react-native"; ··· 84 selectedImage, 85 onImageSelect, 86 onImageRemove, 87 + onUseLastImage, 88 + hasLastImage, 89 + onGoToMetadata, 90 }: { 91 selectedImage?: string | File | Blob; 92 onImageSelect?: () => void; 93 onImageRemove?: () => void; 94 + onUseLastImage?: () => void; 95 + hasLastImage?: boolean; 96 + onGoToMetadata?: () => void; 97 }) => { 98 const imageUrl = useMemo(() => { 99 if (!selectedImage) return undefined; ··· 160 </TouchableOpacity> 161 </View> 162 ) : ( 163 + <> 164 + <TouchableOpacity onPress={onImageSelect} style={containerStyle}> 165 + <ImagePlus size={48} color="#6b7280" /> 166 + <Text style={[text.gray[400], { marginTop: 8, fontSize: 14 }]}> 167 + Add thumbnail image 168 + </Text> 169 + <Text style={[text.gray[500], { fontSize: 12, marginTop: 4 }]}> 170 + Optional โ€ข JPG, PNG up to 975KB 171 + </Text> 172 + </TouchableOpacity> 173 + {hasLastImage && ( 174 + <Button 175 + variant="secondary" 176 + size="sm" 177 + onPress={onUseLastImage} 178 + style={[{ marginTop: 8 }]} 179 + > 180 + <Text style={[text.gray[300], { fontSize: 14 }]}> 181 + Use Last Image 182 + </Text> 183 + </Button> 184 + )} 185 + </> 186 )} 187 + <View style={{ marginTop: 8 }}> 188 + <Admonition variant="info" size="sm"> 189 + <Text size="sm"> 190 + You are required to disclose if your content is not suitable for 191 + certain viewers. 192 + </Text> 193 + <Pressable onPress={onGoToMetadata}> 194 + <Text size="sm" color={zero.colors.blue[400]}> 195 + Go to the metadata page{" "} 196 + <ArrowRight size="14" style={{ marginVertical: -2 }} /> 197 + </Text> 198 + </Pressable> 199 + </Admonition> 200 + </View> 201 </View> 202 ); 203 }; ··· 223 224 const [createPost, setCreatePost] = useState(true); 225 const [sendPushNotification, setSendPushNotification] = useState(true); 226 + const [canonicalUrl, setCanonicalUrl] = useState<string>(""); 227 const defaultCanonicalUrl = useMemo(() => { 228 return `${url}/${profile && formatHandle(profile)}`; 229 }, [url, profile?.handle]); ··· 232 if (!livestream) { 233 return; 234 } 235 + 236 + // Prefill title with previous stream's title 237 + if (livestream.record.title) { 238 + setTitle(livestream.record.title); 239 + } 240 + 241 + // Prefill canonical URL 242 if ( 243 livestream.record.canonicalUrl && 244 livestream.record.canonicalUrl !== defaultCanonicalUrl 245 ) { 246 setCanonicalUrl(livestream.record.canonicalUrl); 247 } 248 + 249 + // Prefill notification settings 250 if ( 251 typeof livestream.record.notificationSettings?.pushNotification === 252 "boolean" ··· 255 livestream.record.notificationSettings.pushNotification, 256 ); 257 } 258 + 259 + // Prefill post creation preference 260 setCreatePost(typeof livestream.record.post !== "undefined"); 261 }, [livestream, defaultCanonicalUrl]); 262 ··· 366 const handleImageRemove = useCallback(() => { 367 setSelectedImage(undefined); 368 }, []); 369 + 370 + const handleUseLastImage = useCallback(async () => { 371 + if (!livestream?.record.thumb) return; 372 + 373 + try { 374 + const did = livestream.uri.split("/")[2]; 375 + const cid = (livestream.record.thumb.ref as any).$link; 376 + 377 + const didDoc = await resolveDIDDocument(did); 378 + const blob = await getBlob(did, cid, didDoc); 379 + setSelectedImage(blob); 380 + } catch (error) { 381 + console.error("Failed to fetch last image:", error); 382 + toast.show("Error", "Failed to load previous thumbnail", { 383 + duration: 3, 384 + }); 385 + } 386 + }, [livestream, toast]); 387 388 const disabled = useMemo( 389 () => !userIsLive || loading || title.trim() === "", ··· 634 selectedImage={selectedImage} 635 onImageSelect={handleImageSelect} 636 onImageRemove={handleImageRemove} 637 + onUseLastImage={handleUseLastImage} 638 + hasLastImage={!!livestream?.record.thumb} 639 + onGoToMetadata={() => handleModeChange("metadata")} 640 /> 641 )} 642
+23 -3
js/app/components/live-dashboard/stream-key.tsx
··· 8 useTheme, 9 useToast, 10 View, 11 } from "@streamplace/components"; 12 import Loading from "components/loading/loading"; 13 import { Clipboard, ClipboardCheck } from "lucide-react-native"; ··· 68 <View fullWidth style={{ maxWidth: 600 }}> 69 <FormRow> 70 <Button 71 variant={protocol !== "rtmp" ? "secondary" : "primary"} 72 onPress={() => setProtocol("rtmp")} 73 style={{ ··· 78 RTMP 79 </Button> 80 <Button 81 variant={protocol !== "whip" ? "secondary" : "primary"} 82 onPress={() => setProtocol("whip")} 83 style={{ ··· 93 <FormRow> 94 <Label>Output Settings</Label> 95 <Content> 96 - <Body> 97 <Text>Output mode: Advanced</Text> 98 <Text> 99 Keyframe Interval: <Code>1s</Code> 100 </Text> 101 <Text> 102 - x264 Options: <Code>bframes=0</Code> 103 </Text> 104 - </Body> 105 </Content> 106 </FormRow> 107 </View> ··· 271 selectTextOnFocus={true} 272 /> 273 <Button 274 onPress={handleCopy} 275 style={[ 276 {
··· 8 useTheme, 9 useToast, 10 View, 11 + zero, 12 } from "@streamplace/components"; 13 import Loading from "components/loading/loading"; 14 import { Clipboard, ClipboardCheck } from "lucide-react-native"; ··· 69 <View fullWidth style={{ maxWidth: 600 }}> 70 <FormRow> 71 <Button 72 + width="min" 73 variant={protocol !== "rtmp" ? "secondary" : "primary"} 74 onPress={() => setProtocol("rtmp")} 75 style={{ ··· 80 RTMP 81 </Button> 82 <Button 83 + width="min" 84 variant={protocol !== "whip" ? "secondary" : "primary"} 85 onPress={() => setProtocol("whip")} 86 style={{ ··· 96 <FormRow> 97 <Label>Output Settings</Label> 98 <Content> 99 + <View style={[zero.mt[2]]}> 100 <Text>Output mode: Advanced</Text> 101 <Text> 102 Keyframe Interval: <Code>1s</Code> 103 </Text> 104 <Text> 105 + x264 Options:{" "} 106 + <Code 107 + style={{ 108 + paddingHorizontal: 4, 109 + backgroundColor: "#648800", 110 + }} 111 + > 112 + bframes=0 113 + </Code> 114 </Text> 115 + <Text 116 + underline 117 + style={{ 118 + fontWeight: "bold", 119 + }} 120 + > 121 + (Very important!) 122 + </Text> 123 + </View> 124 </Content> 125 </FormRow> 126 </View> ··· 290 selectTextOnFocus={true} 291 /> 292 <Button 293 + width="min" 294 onPress={handleCopy} 295 style={[ 296 {
+5 -1
js/app/components/live-dashboard/stream-monitor.tsx
··· 104 <View style={[flex.values[1], layout.flex.center, bg.neutral[900]]}> 105 {isLive && userProfile ? ( 106 isStreamVisible ? ( 107 - <Player src={userProfile.did} name={userProfile.handle}> 108 <DesktopUi /> 109 <PlayerUI.ViewerLoadingOverlay /> 110 <OfflineCounter isMobile={true} />
··· 104 <View style={[flex.values[1], layout.flex.center, bg.neutral[900]]}> 105 {isLive && userProfile ? ( 106 isStreamVisible ? ( 107 + <Player 108 + src={userProfile.did} 109 + name={userProfile.handle} 110 + muted={true} 111 + > 112 <DesktopUi /> 113 <PlayerUI.ViewerLoadingOverlay /> 114 <OfflineCounter isMobile={true} />
+11 -5
js/app/components/login/login-form.tsx
··· 20 21 interface LoginFormProps { 22 onSuccess?: () => void; 23 } 24 25 - export default function LoginForm({ onSuccess }: LoginFormProps) { 26 const { theme } = useTheme(); 27 const loginAction = useStore((state) => state.login); 28 const openLoginLink = useStore((state) => state.openLoginLink); ··· 74 }; 75 76 const onSignup = () => { 77 - // TODO: remove requirement for oauth-protected-resource in oatproxy 78 - loginAction("https://bsky.social", openLoginLink); 79 }; 80 81 const isMobile = Platform.OS === "ios" || Platform.OS === "android"; ··· 284 ]} 285 > 286 <Button width="min" onPress={() => onSignup()} variant="ghost"> 287 - <Text style={[{ color: "white" }]}>Sign Up on Bluesky</Text> 288 </Button> 289 <Button 290 onPress={submit} ··· 293 width="min" 294 loading={loginState.loading} 295 > 296 - <Text style={[{ color: "white" }]}>Log in</Text> 297 </Button> 298 </View> 299 </>
··· 20 21 interface LoginFormProps { 22 onSuccess?: () => void; 23 + onCloseModal?: () => void; 24 + onOpenPdsModal?: () => void; 25 } 26 27 + export default function LoginForm({ 28 + onSuccess, 29 + onCloseModal, 30 + onOpenPdsModal, 31 + }: LoginFormProps) { 32 const { theme } = useTheme(); 33 const loginAction = useStore((state) => state.login); 34 const openLoginLink = useStore((state) => state.openLoginLink); ··· 80 }; 81 82 const onSignup = () => { 83 + onCloseModal?.(); 84 + onOpenPdsModal?.(); 85 }; 86 87 const isMobile = Platform.OS === "ios" || Platform.OS === "android"; ··· 290 ]} 291 > 292 <Button width="min" onPress={() => onSignup()} variant="ghost"> 293 + <Text style={[{ color: "white" }]}>Sign Up</Text> 294 </Button> 295 <Button 296 onPress={submit} ··· 299 width="min" 300 loading={loginState.loading} 301 > 302 + <Text style={[{ color: "white" }]}>Log In</Text> 303 </Button> 304 </View> 305 </>
+15 -2
js/app/components/login/login-modal.tsx
··· 6 interface LoginModalProps { 7 visible: boolean; 8 onClose: () => void; 9 } 10 11 - export default function LoginModal({ visible, onClose }: LoginModalProps) { 12 const { theme, zero: z } = useTheme(); 13 14 return ( 15 <Modal ··· 64 </TouchableOpacity> 65 </View> 66 67 - <LoginForm onSuccess={onClose} /> 68 </Pressable> 69 </View> 70 </Modal>
··· 6 interface LoginModalProps { 7 visible: boolean; 8 onClose: () => void; 9 + onOpenPdsModal: () => void; 10 } 11 12 + export default function LoginModal({ 13 + visible, 14 + onClose, 15 + onOpenPdsModal, 16 + }: LoginModalProps) { 17 const { theme, zero: z } = useTheme(); 18 + 19 + if (!visible) { 20 + return null; 21 + } 22 23 return ( 24 <Modal ··· 73 </TouchableOpacity> 74 </View> 75 76 + <LoginForm 77 + onSuccess={onClose} 78 + onCloseModal={onClose} 79 + onOpenPdsModal={onOpenPdsModal} 80 + /> 81 </Pressable> 82 </View> 83 </Modal>
+3 -1
js/app/components/login/login.tsx
··· 12 export default function Login() { 13 const { theme } = useTheme(); 14 const closeLoginModal = useStore((state) => state.closeLoginModal); 15 const userProfile = useUserProfile(); 16 const navigation = useNavigation(); 17 const isReady = useIsReady(); ··· 26 27 // check for stored return route on mount 28 useEffect(() => { 29 storage.getItem("returnRoute").then((stored) => { 30 if (stored) { 31 try { ··· 103 <Text style={[{ fontSize: 36, fontWeight: "200", color: "white" }]}> 104 Log in 105 </Text> 106 - <LoginForm /> 107 </View> 108 </View> 109 </ScrollView>
··· 12 export default function Login() { 13 const { theme } = useTheme(); 14 const closeLoginModal = useStore((state) => state.closeLoginModal); 15 + const openPdsModal = useStore((state) => state.openPdsModal); 16 const userProfile = useUserProfile(); 17 const navigation = useNavigation(); 18 const isReady = useIsReady(); ··· 27 28 // check for stored return route on mount 29 useEffect(() => { 30 + if (Platform.OS !== "web") return; 31 storage.getItem("returnRoute").then((stored) => { 32 if (stored) { 33 try { ··· 105 <Text style={[{ fontSize: 36, fontWeight: "200", color: "white" }]}> 106 Log in 107 </Text> 108 + <LoginForm onOpenPdsModal={openPdsModal} /> 109 </View> 110 </View> 111 </ScrollView>
+364
js/app/components/login/pds-host-selector-modal.tsx
···
··· 1 + import { 2 + Admonition, 3 + Button, 4 + Checkbox, 5 + Input, 6 + ResponsiveDialog, 7 + Trans as T, 8 + Text, 9 + useTheme, 10 + useTranslation, 11 + zero, 12 + } from "@streamplace/components"; 13 + import { Check, ExternalLink } from "lucide-react-native"; 14 + import React, { useState } from "react"; 15 + import { Linking, Pressable, View } from "react-native"; 16 + 17 + interface PdsHost { 18 + value: string; 19 + label: string; 20 + description: string; 21 + handlePolicyDocs?: string; 22 + terms: string; 23 + privacy: string; 24 + } 25 + 26 + const PDS_HOSTS = [ 27 + { 28 + value: "https://selfhosted.social", 29 + label: "selfhosted.social", 30 + description: "A popular community-run PDS", 31 + terms: "https://selfhosted.social/legal#terms", 32 + privacy: "https://selfhosted.social/legal", 33 + }, 34 + { 35 + // will redirect to https://bsky.social for sign in :thumb: 36 + value: "https://witchesbutter.us-west.host.bsky.network", 37 + label: "Bluesky", 38 + description: "The main Bluesky PDS instance", 39 + terms: "https://bsky.social/about/support/tos", 40 + privacy: "https://bsky.social/about/support/privacy-policy", 41 + }, 42 + { 43 + value: "https://blacksky.app", 44 + label: "Blacksky PDS", 45 + description: "A PDS service by Blacksky Algorithms", 46 + terms: "https://blackskyweb.xyz/about/support/tos", 47 + privacy: "https://blackskyweb.xyz/about/support/privacy-policy/", 48 + handlePolicyDocs: 49 + "https://docs.blacksky.community/migrating-to-blacksky-pds-complete-guide#who-can-use-blacksky-services", 50 + }, 51 + { 52 + value: "https://pds.tophhie.cloud", 53 + label: "Tophhie Cloud", 54 + description: "A PDS service by Tophhie", 55 + terms: "https://blog.tophhie.cloud/atproto-tos/", 56 + privacy: "https://blog.tophhie.cloud/atproto-privacy-policy/", 57 + }, 58 + ]; 59 + 60 + // Shuffle the hosts 61 + // items with handle policies should never be first ! 62 + const shuffleArray = <T,>(array: T[]): T[] => { 63 + const arr = [...array]; 64 + for (let i = arr.length - 1; i > 0; i--) { 65 + const j = Math.floor(Math.random() * (i + 1)); 66 + [arr[i], arr[j]] = [arr[j], arr[i]]; 67 + } 68 + return arr; 69 + }; 70 + 71 + const SHUFFLED_PDS_HOSTS = (() => { 72 + const withPolicies = PDS_HOSTS.filter((h) => h.handlePolicyDocs); 73 + const [first, ...withoutPolicies] = PDS_HOSTS.filter( 74 + (h) => !h.handlePolicyDocs, 75 + ); 76 + return [first, ...shuffleArray(withPolicies.concat(withoutPolicies))]; 77 + })(); 78 + 79 + interface PdsHostSelectorModalProps { 80 + open: boolean; 81 + onOpenChange: (open: boolean) => void; 82 + onSubmit: (pdsHost: string) => void; 83 + } 84 + 85 + export const PdsHostSelectorModal: React.FC<PdsHostSelectorModalProps> = ({ 86 + open, 87 + onOpenChange, 88 + onSubmit, 89 + }) => { 90 + const [selectedHost, setSelectedHost] = useState<string | null>( 91 + SHUFFLED_PDS_HOSTS[0].value, 92 + ); 93 + const [customHost, setCustomHost] = useState<string>(""); 94 + const [useCustom, setUseCustom] = useState(false); 95 + const [handlePolicyChecked, hasCheckedHandlePolicy] = useState(false); 96 + 97 + const { theme } = useTheme(); 98 + const { t } = useTranslation(); 99 + 100 + const selectedHostObj = 101 + SHUFFLED_PDS_HOSTS.find((host) => host.value === selectedHost) || 102 + SHUFFLED_PDS_HOSTS[0]; 103 + 104 + const handleCancel = () => { 105 + setSelectedHost(SHUFFLED_PDS_HOSTS[0].value); 106 + setCustomHost(""); 107 + setUseCustom(false); 108 + onOpenChange(false); 109 + }; 110 + 111 + const handleSubmit = () => { 112 + const hostToUse = useCustom ? customHost : selectedHost; 113 + if (!hostToUse) return; 114 + 115 + onSubmit(hostToUse); 116 + handleCancel(); 117 + }; 118 + 119 + const handleLearnMore = () => { 120 + Linking.openURL("https://atproto.com/guides/self-hosting"); 121 + }; 122 + const handleTOS = () => { 123 + Linking.openURL(selectedHostObj.terms); 124 + }; 125 + const handlePrivacy = () => { 126 + Linking.openURL(selectedHostObj.privacy); 127 + }; 128 + 129 + const handleSelectHost = (value: string) => { 130 + setSelectedHost(value); 131 + setUseCustom(false); 132 + }; 133 + 134 + const handleSelectCustom = () => { 135 + setUseCustom(true); 136 + }; 137 + 138 + return ( 139 + <ResponsiveDialog 140 + open={open} 141 + onOpenChange={onOpenChange} 142 + showCloseButton={false} 143 + variant="default" 144 + size="sm" 145 + dismissible={false} 146 + position="center" 147 + > 148 + <View style={[{ maxWidth: 500 }]}> 149 + <View style={[zero.my[4]]}> 150 + <Text size="2xl" style={[zero.mb[2]]}> 151 + {t("pds-selector-title")} 152 + </Text> 153 + <Text style={[{ color: theme.colors.textMuted }]}> 154 + {t("pds-selector-description")} 155 + </Text> 156 + </View> 157 + <View style={[zero.pb[2]]}> 158 + {SHUFFLED_PDS_HOSTS.map((host, index) => ( 159 + <Pressable 160 + key={host.value} 161 + onPress={() => handleSelectHost(host.value)} 162 + style={[ 163 + zero.py[2], 164 + zero.px[3], 165 + zero.r.lg, 166 + { 167 + borderWidth: 1, 168 + borderColor: 169 + !useCustom && selectedHost === host.value 170 + ? theme.colors.primary 171 + : theme.colors.border, 172 + backgroundColor: 173 + !useCustom && selectedHost === host.value 174 + ? "rgba(0, 122, 255, 0.05)" 175 + : "transparent", 176 + }, 177 + index > 0 && zero.mt[2], 178 + ]} 179 + > 180 + <View 181 + style={[ 182 + zero.layout.flex.row, 183 + zero.layout.flex.spaceBetween, 184 + zero.layout.flex.alignCenter, 185 + ]} 186 + > 187 + <View style={[zero.flex[1]]}> 188 + <Text>{host.label}</Text> 189 + <Text 190 + style={[ 191 + zero.mt[1], 192 + { fontSize: 14, color: theme.colors.textMuted }, 193 + ]} 194 + > 195 + {host.description} 196 + </Text> 197 + </View> 198 + {!useCustom && selectedHost === host.value && ( 199 + <Check size={20} color={theme.colors.primary} /> 200 + )} 201 + </View> 202 + </Pressable> 203 + ))} 204 + 205 + <Pressable 206 + onPress={handleSelectCustom} 207 + style={[ 208 + zero.py[2], 209 + zero.px[3], 210 + zero.r.lg, 211 + zero.mt[2], 212 + { 213 + borderWidth: 1, 214 + borderColor: useCustom 215 + ? theme.colors.primary 216 + : theme.colors.border, 217 + backgroundColor: useCustom 218 + ? "rgba(0, 122, 255, 0.05)" 219 + : "transparent", 220 + }, 221 + ]} 222 + > 223 + <View 224 + style={[ 225 + zero.layout.flex.row, 226 + zero.layout.flex.spaceBetween, 227 + zero.layout.flex.alignCenter, 228 + ]} 229 + > 230 + <View style={[zero.flex[1]]}> 231 + <Text>{t("pds-selector-custom-label")}</Text> 232 + <Text 233 + style={[ 234 + zero.mt[1], 235 + { fontSize: 14, color: theme.colors.textMuted }, 236 + ]} 237 + > 238 + {t("pds-selector-custom-description")} 239 + </Text> 240 + </View> 241 + {useCustom && <Check size={20} color={theme.colors.primary} />} 242 + </View> 243 + </Pressable> 244 + 245 + <View style={[zero.mt[4]]}> 246 + <Pressable 247 + onPress={handleLearnMore} 248 + style={[ 249 + zero.layout.flex.row, 250 + zero.gap.all[1], 251 + zero.layout.flex.alignCenter, 252 + ]} 253 + > 254 + <Text style={[{ color: theme.colors.ring, fontSize: 14 }]}> 255 + {t("pds-selector-learn-more")} 256 + </Text> 257 + <ExternalLink size={16} color={theme.colors.ring} /> 258 + </Pressable> 259 + </View> 260 + 261 + {useCustom && ( 262 + <View style={[zero.mt[3]]}> 263 + <Text style={[zero.mb[2], { color: theme.colors.textMuted }]}> 264 + {t("pds-selector-custom-url-label")} 265 + </Text> 266 + <Input 267 + value={customHost} 268 + onChangeText={setCustomHost} 269 + placeholder={t("pds-selector-custom-url-placeholder")} 270 + autoCapitalize="none" 271 + autoCorrect={false} 272 + keyboardType="url" 273 + /> 274 + </View> 275 + )} 276 + <Admonition variant="info" style={[zero.my[4]] as any}> 277 + <Text style={[zero.mb[2]]}>{t("pds-selector-info")}</Text> 278 + {!useCustom && ( 279 + <Text style={[zero.mb[2]]}> 280 + <T 281 + i18nKey="pds-selector-read-policies" 282 + values={{ label: selectedHostObj?.label }} 283 + components={{ 284 + tosLink: ( 285 + <Text 286 + onPress={handleTOS} 287 + style={[{ color: theme.colors.ring }]} 288 + /> 289 + ), 290 + privacyLink: ( 291 + <Text 292 + onPress={handlePrivacy} 293 + style={[{ color: theme.colors.ring }]} 294 + /> 295 + ), 296 + }} 297 + /> 298 + </Text> 299 + )} 300 + </Admonition> 301 + {!useCustom && selectedHostObj.handlePolicyDocs && ( 302 + <View 303 + style={[ 304 + zero.layout.flex.row, 305 + zero.layout.flex.align.center, 306 + zero.layout.flex.justify.start, 307 + zero.gap.all[2], 308 + zero.mb[4], 309 + zero.mt[2], 310 + ]} 311 + > 312 + <Checkbox 313 + checked={handlePolicyChecked} 314 + onCheckedChange={hasCheckedHandlePolicy} 315 + /> 316 + <Text style={[zero.flex[1]]}> 317 + <T 318 + i18nKey="pds-selector-handle-policy-checkbox" 319 + components={{ 320 + policyLink: ( 321 + <Text 322 + onPress={() => 323 + Linking.openURL(selectedHostObj.handlePolicyDocs!) 324 + } 325 + style={[{ color: theme.colors.ring }]} 326 + > 327 + {selectedHostObj.label} guidelines and handle policy 328 + </Text> 329 + ), 330 + }} 331 + /> 332 + </Text> 333 + </View> 334 + )} 335 + </View> 336 + <View 337 + style={[ 338 + zero.flex[1], 339 + zero.layout.flex.row, 340 + zero.layout.flex.justify.end, 341 + zero.gap.all[2], 342 + ]} 343 + > 344 + <Button width="min" variant="secondary" onPress={handleCancel}> 345 + <Text>{t("cancel")}</Text> 346 + </Button> 347 + <Button 348 + width="min" 349 + variant="primary" 350 + onPress={handleSubmit} 351 + disabled={ 352 + (useCustom && !customHost.trim()) || 353 + (!handlePolicyChecked && !!selectedHostObj.handlePolicyDocs) 354 + } 355 + > 356 + <Text>{t("continue")}</Text> 357 + </Button> 358 + </View> 359 + </View> 360 + </ResponsiveDialog> 361 + ); 362 + }; 363 + 364 + export default PdsHostSelectorModal;
+2
js/app/components/mobile/bottom-metadata.tsx
··· 17 import FollowButton from "components/follow-button"; 18 import { ChevronLeft, ChevronRight } from "lucide-react-native"; 19 import { Image, Linking, Pressable, View } from "react-native"; 20 const { gap, px, py, colors } = zero; 21 22 export function BottomMetadata({ ··· 119 <View style={[layout.flex.row, layout.flex.align.center, gap.all[4]]}> 120 <PlayerUI.Viewers /> 121 <ShareSheet /> 122 <View> 123 <Button 124 variant="outline"
··· 17 import FollowButton from "components/follow-button"; 18 import { ChevronLeft, ChevronRight } from "lucide-react-native"; 19 import { Image, Linking, Pressable, View } from "react-native"; 20 + import { KebabMenu } from "./desktop-ui/kebab"; 21 const { gap, px, py, colors } = zero; 22 23 export function BottomMetadata({ ··· 120 <View style={[layout.flex.row, layout.flex.align.center, gap.all[4]]}> 121 <PlayerUI.Viewers /> 122 <ShareSheet /> 123 + <KebabMenu /> 124 <View> 125 <Button 126 variant="outline"
+46 -1
js/app/components/mobile/chat.tsx
··· 3 ChatBox, 4 Loader, 5 Resizable, 6 Text, 7 useHandle, 8 useLivestreamInfo, ··· 54 { translateX: sidebarOffset.value }, 55 { translateY: -kb.keyboardHeight }, 56 ], 57 - opacity: sidebarOpacity.value, 58 })); 59 60 return ( ··· 88 ]} 89 > 90 <View style={{ flex: 1, position: "relative" }}> 91 <ChatPanel /> 92 </View> 93 </Animated.View> ··· 110 <Resizable 111 isPlayerRatioGreater={isPlayerRatioGreater} 112 startingPercentage={0.4} 113 > 114 <ChatPanel /> 115 </Resizable> ··· 149 <Chat /> 150 </View> 151 <View style={[layout.flex.column, gap.all[2]]}> 152 {agent?.did ? ( 153 <ChatBox 154 emojiData={emojiData}
··· 3 ChatBox, 4 Loader, 5 Resizable, 6 + StreamNotificationProvider, 7 Text, 8 useHandle, 9 useLivestreamInfo, ··· 55 { translateX: sidebarOffset.value }, 56 { translateY: -kb.keyboardHeight }, 57 ], 58 + })); 59 + 60 + const notificationOffsetStyle = useAnimatedStyle(() => ({ 61 + transform: [{ translateX: -sidebarOffset.value }], 62 })); 63 64 return ( ··· 92 ]} 93 > 94 <View style={{ flex: 1, position: "relative" }}> 95 + <Animated.View 96 + style={[ 97 + { 98 + position: "absolute", 99 + top: 1, 100 + right: 1, 101 + zIndex: 2, 102 + width: "100%", 103 + minWidth: 350, 104 + pointerEvents: "none", 105 + transformOrigin: "top right", 106 + }, 107 + notificationOffsetStyle, 108 + ]} 109 + > 110 + <StreamNotificationProvider position="top" /> 111 + </Animated.View> 112 <ChatPanel /> 113 </View> 114 </Animated.View> ··· 131 <Resizable 132 isPlayerRatioGreater={isPlayerRatioGreater} 133 startingPercentage={0.4} 134 + renderAbove={(isCollapsed) => ( 135 + <StreamNotificationProvider position="bottom" /> 136 + )} 137 > 138 <ChatPanel /> 139 </Resizable> ··· 173 <Chat /> 174 </View> 175 <View style={[layout.flex.column, gap.all[2]]}> 176 + {/* 177 + // in case one needs this again 178 + 179 + <Pressable 180 + onPress={() => 181 + StreamNotifications.activate("Stream notification activated!") 182 + } 183 + style={[ 184 + layout.flex.row, 185 + layout.flex.center, 186 + { 187 + padding: 12, 188 + borderRadius: borderRadius.xl, 189 + backgroundColor: "rgba(255, 255, 255, 0.05)", 190 + }, 191 + ]} 192 + > 193 + <Text style={{ color: "rgba(255, 255, 255, 0.7)", fontSize: 12 }}> 194 + Activate Stream Notification 195 + </Text> 196 + </Pressable>*/} 197 {agent?.did ? ( 198 <ChatBox 199 emojiData={emojiData}
+1
js/app/components/mobile/desktop-ui/index.ts
··· 1 export { BottomControlBar } from "./bottom-controls"; 2 export { LiveBubble } from "./live-bubble"; 3 export { MuteOverlay } from "./mute-overlay"; 4 export { TopControlBar } from "./top-controls";
··· 1 export { BottomControlBar } from "./bottom-controls"; 2 + export { KebabMenu } from "./kebab"; 3 export { LiveBubble } from "./live-bubble"; 4 export { MuteOverlay } from "./mute-overlay"; 5 export { TopControlBar } from "./top-controls";
+203
js/app/components/mobile/desktop-ui/kebab.tsx
···
··· 1 + import { 2 + AppBskyActorDefs, 3 + ComAtprotoModerationCreateReport, 4 + } from "@atproto/api"; 5 + import { useRootContext } from "@rn-primitives/dropdown-menu"; 6 + import { 7 + DropdownMenu, 8 + DropdownMenuGroup, 9 + DropdownMenuItem, 10 + DropdownMenuTrigger, 11 + ResponsiveDropdownMenuContent, 12 + Text, 13 + UpdateStreamTitleDialog, 14 + useCanModerate, 15 + useLivestream, 16 + useLivestreamInfo, 17 + useLivestreamStore, 18 + usePlayerStore, 19 + useTheme, 20 + useUpdateLivestreamRecord, 21 + } from "@streamplace/components"; 22 + import { EllipsisVertical } from "lucide-react-native"; 23 + import { useState } from "react"; 24 + import Animated, { 25 + Easing, 26 + useAnimatedStyle, 27 + withTiming, 28 + } from "react-native-reanimated"; 29 + import { LivestreamViewHydrated } from "streamplace"; 30 + 31 + type ReportSubject = 32 + | ComAtprotoModerationCreateReport.InputSchema["subject"] 33 + | null; 34 + 35 + interface KebabMenuProps { 36 + dropdownPortalContainer?: string; 37 + } 38 + 39 + export function KebabMenu({ dropdownPortalContainer }: KebabMenuProps) { 40 + const th = useTheme(); 41 + const [isOpen, setIsOpen] = useState(false); 42 + const [showUpdateTitleDialog, setShowUpdateTitleDialog] = useState(false); 43 + 44 + const livestreamFromStore = useLivestreamStore((x) => x.livestream); 45 + const livestream = useLivestream(); 46 + const setReportModalOpen = usePlayerStore((x) => x.setReportModalOpen); 47 + const setReportSubject = usePlayerStore((x) => x.setReportSubject); 48 + const { profile } = useLivestreamInfo(); 49 + 50 + // Get the streamer's DID from the profile 51 + const streamerDID = profile?.did; 52 + // Check moderation permissions for the current user on this streamer's channel 53 + const modPermissions = useCanModerate(streamerDID); 54 + const { updateLivestream, isLoading: isUpdateTitleLoading } = 55 + useUpdateLivestreamRecord(); 56 + 57 + const iconRotate = useAnimatedStyle(() => { 58 + return { 59 + transform: [ 60 + { 61 + rotateZ: withTiming(isOpen ? "5deg" : "0deg", { 62 + duration: 200, 63 + easing: Easing.out(Easing.ease), 64 + }), 65 + }, 66 + ], 67 + }; 68 + }); 69 + 70 + return ( 71 + <> 72 + <DropdownMenu onOpenChange={setIsOpen} key={dropdownPortalContainer}> 73 + <DropdownMenuTrigger> 74 + <Animated.View style={[iconRotate]}> 75 + <EllipsisVertical color={th.theme.colors.foreground} /> 76 + </Animated.View> 77 + </DropdownMenuTrigger> 78 + <ResponsiveDropdownMenuContent 79 + side="top" 80 + align="end" 81 + portalHost={dropdownPortalContainer} 82 + > 83 + {modPermissions.canManageLivestream && ( 84 + <DropdownMenuGroup title="Stream Settings"> 85 + <UpdateStreamTitleItem 86 + setShowUpdateTitleDialog={setShowUpdateTitleDialog} 87 + isUpdateTitleLoading={isUpdateTitleLoading} 88 + livestream={livestream} 89 + /> 90 + </DropdownMenuGroup> 91 + )} 92 + <DropdownMenuGroup title="Report"> 93 + <ReportStreamItem 94 + livestream={livestreamFromStore} 95 + setReportModalOpen={setReportModalOpen} 96 + setReportSubject={setReportSubject} 97 + /> 98 + <ReportUserItem 99 + profile={profile} 100 + setReportModalOpen={setReportModalOpen} 101 + setReportSubject={setReportSubject} 102 + /> 103 + </DropdownMenuGroup> 104 + </ResponsiveDropdownMenuContent> 105 + </DropdownMenu> 106 + 107 + {showUpdateTitleDialog && ( 108 + <UpdateStreamTitleDialog 109 + livestream={livestream} 110 + streamerDID={streamerDID} 111 + updateLivestream={updateLivestream} 112 + isLoading={isUpdateTitleLoading} 113 + onClose={() => setShowUpdateTitleDialog(false)} 114 + /> 115 + )} 116 + </> 117 + ); 118 + } 119 + 120 + function ReportStreamItem({ 121 + livestream, 122 + setReportModalOpen, 123 + setReportSubject, 124 + }: { 125 + livestream: LivestreamViewHydrated | null; 126 + setReportModalOpen: (open: boolean) => void; 127 + setReportSubject: (subject: ReportSubject) => void; 128 + }) { 129 + const { onOpenChange } = useRootContext(); 130 + 131 + return ( 132 + <DropdownMenuItem 133 + onPress={() => { 134 + if (!livestream) return; 135 + onOpenChange?.(false); 136 + setReportModalOpen(true); 137 + setReportSubject({ 138 + $type: "com.atproto.repo.strongRef", 139 + uri: livestream.uri, 140 + cid: livestream.cid, 141 + }); 142 + }} 143 + disabled={!livestream} 144 + > 145 + <Text>Report Livestream...</Text> 146 + </DropdownMenuItem> 147 + ); 148 + } 149 + 150 + function ReportUserItem({ 151 + profile, 152 + setReportModalOpen, 153 + setReportSubject, 154 + }: { 155 + profile: AppBskyActorDefs.ProfileViewBasic | null; 156 + setReportModalOpen: (open: boolean) => void; 157 + setReportSubject: (subject: ReportSubject) => void; 158 + }) { 159 + const { onOpenChange } = useRootContext(); 160 + 161 + return ( 162 + <DropdownMenuItem 163 + onPress={() => { 164 + if (!profile?.did) return; 165 + onOpenChange?.(false); 166 + setReportModalOpen(true); 167 + setReportSubject({ 168 + $type: "com.atproto.admin.defs#repoRef", 169 + did: profile.did, 170 + }); 171 + }} 172 + disabled={!profile?.did} 173 + > 174 + <Text>Report User...</Text> 175 + </DropdownMenuItem> 176 + ); 177 + } 178 + 179 + function UpdateStreamTitleItem({ 180 + setShowUpdateTitleDialog, 181 + isUpdateTitleLoading, 182 + livestream, 183 + }: { 184 + setShowUpdateTitleDialog: (show: boolean) => void; 185 + isUpdateTitleLoading: boolean; 186 + livestream: any; 187 + }) { 188 + const { onOpenChange } = useRootContext(); 189 + 190 + return ( 191 + <DropdownMenuItem 192 + onPress={() => { 193 + onOpenChange?.(false); 194 + setShowUpdateTitleDialog(true); 195 + }} 196 + disabled={isUpdateTitleLoading || !livestream} 197 + > 198 + <Text> 199 + {isUpdateTitleLoading ? "Updating..." : "Update stream title"} 200 + </Text> 201 + </DropdownMenuItem> 202 + ); 203 + }
+1
js/app/components/mobile/desktop-ui.tsx
··· 254 setTitle={setTitle} 255 ingestStarting={ingestStarting} 256 toggleGoLive={toggleGoLive} 257 /> 258 )} 259
··· 254 setTitle={setTitle} 255 ingestStarting={ingestStarting} 256 toggleGoLive={toggleGoLive} 257 + isLive={isActivelyLive} 258 /> 259 )} 260
+41 -23
js/app/components/mobile/player.tsx
··· 43 export function Player( 44 props: Partial<PlayerProps> & { 45 setFullscreen?: (fullscreen: boolean) => void; 46 }, 47 ) { 48 return ( ··· 60 function PlayerWithProvider( 61 props: Partial<PlayerProps> & { 62 setFullscreen?: (fullscreen: boolean) => void; 63 }, 64 ) { 65 const [showChat, setShowChat] = useState(true); ··· 188 ); 189 } 190 191 return ( 192 - <View 193 - style={{ 194 - flexDirection: chatVisible ? "row" : "column", 195 - flex: 1, 196 - width: "100%", 197 - height: "100%", 198 - }} 199 - > 200 - <PlayerInner 201 - {...props} 202 - showChat={showChat} 203 - setShowChat={setShowChat} 204 - showUnavailable={showUnavailable} 205 - /> 206 - {shouldShowChatSidePanel ? ( 207 - <DesktopChatPanel 208 - chatVisible={chatVisible} 209 - chatPanelWidth={chatPanelWidth} 210 - /> 211 - ) : ( 212 - !showUnavailable && <MobileUi /> 213 - )} 214 - </View> 215 ); 216 } 217
··· 43 export function Player( 44 props: Partial<PlayerProps> & { 45 setFullscreen?: (fullscreen: boolean) => void; 46 + onTeleport?: (targetHandle: string, targetDID: string) => void; 47 }, 48 ) { 49 return ( ··· 61 function PlayerWithProvider( 62 props: Partial<PlayerProps> & { 63 setFullscreen?: (fullscreen: boolean) => void; 64 + onTeleport?: (targetHandle: string, targetDID: string) => void; 65 }, 66 ) { 67 const [showChat, setShowChat] = useState(true); ··· 190 ); 191 } 192 193 + const defaultHandleTeleport = (targetHandle: string, targetDID: string) => { 194 + navigation.navigate("Home", { 195 + screen: "Stream", 196 + params: { user: targetHandle }, 197 + }); 198 + }; 199 + 200 + const handleTeleport = props.onTeleport || defaultHandleTeleport; 201 + 202 return ( 203 + <RotationProvider enabled={Platform.OS !== "web"}> 204 + <LivestreamProvider src={props.src ?? ""} onTeleport={handleTeleport}> 205 + <StatusBar hidden={true} /> 206 + <PlayerProvider defaultId={props.playerId || undefined}> 207 + <View 208 + style={{ 209 + flexDirection: chatVisible ? "row" : "column", 210 + flex: 1, 211 + width: "100%", 212 + height: "100%", 213 + }} 214 + > 215 + <PlayerInner 216 + {...props} 217 + showChat={showChat} 218 + setShowChat={setShowChat} 219 + showUnavailable={showUnavailable} 220 + /> 221 + {shouldShowChatSidePanel ? ( 222 + <DesktopChatPanel 223 + chatVisible={chatVisible} 224 + chatPanelWidth={chatPanelWidth} 225 + /> 226 + ) : ( 227 + !showUnavailable && <MobileUi /> 228 + )} 229 + </View> 230 + </PlayerProvider> 231 + </LivestreamProvider> 232 + </RotationProvider> 233 ); 234 } 235
+16 -3
js/app/components/mobile/ui.tsx
··· 72 ingestStarting, 73 setIngestStarting, 74 toggleGoLive, 75 } = useLivestreamInfo(); 76 const { width, height } = usePlayerDimensions(); 77 const { isPlayerRatioGreater } = useSegmentDimensions(); ··· 102 103 const isSelfAndNotLive = ingest === "new"; 104 const isLive = ingest !== null && ingest !== "new"; 105 106 const FADE_OUT_DELAY = 4000; 107 const fadeOpacity = useSharedValue(1); ··· 222 <View 223 style={[ 224 layout.position.absolute, 225 - position.top[28], 226 position.left[0], 227 position.right[0], 228 layout.flex.column, ··· 230 ]} 231 > 232 <PlayerUI.MetricsPanel 233 - showMetrics={isLive || isSelfAndNotLive} 234 /> 235 </View> 236 )} ··· 241 setTitle={setTitle} 242 ingestStarting={ingestStarting} 243 toggleGoLive={toggleGoLive} 244 /> 245 )} 246 ··· 468 <Pressable onPress={doSetIngestCamera}> 469 <SwitchCamera color={theme.colors.foreground} size={20} /> 470 </Pressable> 471 </> 472 )} 473 {Platform.OS === "web" ? ( ··· 515 )} 516 </Pressable> 517 )} 518 - <PlayerUI.ContextMenu /> 519 </View> 520 )} 521 {shouldShowChatSidePanel && setShowChat && (
··· 72 ingestStarting, 73 setIngestStarting, 74 toggleGoLive, 75 + toggleStopStream, 76 } = useLivestreamInfo(); 77 const { width, height } = usePlayerDimensions(); 78 const { isPlayerRatioGreater } = useSegmentDimensions(); ··· 103 104 const isSelfAndNotLive = ingest === "new"; 105 const isLive = ingest !== null && ingest !== "new"; 106 + 107 + useEffect(() => { 108 + if (isLive && ingestStarting) { 109 + setIngestStarting(false); 110 + } 111 + }, [isLive, ingestStarting, setIngestStarting]); 112 113 const FADE_OUT_DELAY = 4000; 114 const fadeOpacity = useSharedValue(1); ··· 229 <View 230 style={[ 231 layout.position.absolute, 232 + position.top[32], 233 position.left[0], 234 position.right[0], 235 layout.flex.column, ··· 237 ]} 238 > 239 <PlayerUI.MetricsPanel 240 + showMetrics={shouldShowFloatingMetrics} 241 /> 242 </View> 243 )} ··· 248 setTitle={setTitle} 249 ingestStarting={ingestStarting} 250 toggleGoLive={toggleGoLive} 251 + isLive={isLive} 252 /> 253 )} 254 ··· 476 <Pressable onPress={doSetIngestCamera}> 477 <SwitchCamera color={theme.colors.foreground} size={20} /> 478 </Pressable> 479 + {Platform.OS === "web" && <PlayerUI.StreamContextMenu />} 480 </> 481 )} 482 {Platform.OS === "web" ? ( ··· 524 )} 525 </Pressable> 526 )} 527 + {ingest === null ? ( 528 + <PlayerUI.ContextMenu /> 529 + ) : ( 530 + <PlayerUI.StreamContextMenu /> 531 + )} 532 </View> 533 )} 534 {shouldShowChatSidePanel && setShowChat && (
-64
js/app/components/provider/CurrentToast.tsx
··· 1 - import { Text, zero } from "@streamplace/components"; 2 - import { Platform, Pressable, View } from "react-native"; 3 - 4 - const isWeb = Platform.OS === "web"; 5 - 6 - // Note: Toast functionality removed - this is now a placeholder implementation 7 - // In a real app, you might want to use a toast library like react-native-toast-message 8 - // or implement a simple alert/modal system 9 - 10 - export function CurrentToast() { 11 - // Toast functionality removed - would need replacement with simple modal or alert 12 - return null; 13 - } 14 - 15 - export function ToastControl() { 16 - // Note: This was a demo component for testing toasts 17 - return ( 18 - <View style={[{ gap: 8 }, zero.layout.flex.alignCenter]}> 19 - <Text style={[{ fontSize: 18, fontWeight: "bold" }]}> 20 - Toast demo (disabled) 21 - </Text> 22 - <View 23 - style={[ 24 - zero.layout.flex.row, 25 - { gap: 8 }, 26 - zero.layout.flex.justifyCenter, 27 - ]} 28 - > 29 - <Pressable 30 - style={[ 31 - { 32 - backgroundColor: "#0066cc", 33 - padding: 12, 34 - borderRadius: 8, 35 - alignItems: "center", 36 - }, 37 - ]} 38 - onPress={() => { 39 - // Would show toast: "Successfully saved!" with message: "Don't worry, we've got your data." 40 - console.log("Toast would show: Successfully saved!"); 41 - }} 42 - > 43 - <Text style={{ color: "white" }}>Show</Text> 44 - </Pressable> 45 - <Pressable 46 - style={[ 47 - { 48 - backgroundColor: "#666", 49 - padding: 12, 50 - borderRadius: 8, 51 - alignItems: "center", 52 - }, 53 - ]} 54 - onPress={() => { 55 - // Would hide toast 56 - console.log("Toast would hide"); 57 - }} 58 - > 59 - <Text style={{ color: "white" }}>Hide</Text> 60 - </Pressable> 61 - </View> 62 - </View> 63 - ); 64 - }
···
+6 -1
js/app/features/bluesky/blueskyProvider.tsx
··· 2 import { storage } from "@streamplace/components"; 3 import { useURL } from "expo-linking"; 4 import { useEffect, useState } from "react"; 5 import { useStore } from "store"; 6 import { useIsReady, useOAuthSession, useUserProfile } from "store/hooks"; 7 import { navigateToRoute } from "utils/navigation"; ··· 23 loadOAuthClient(); 24 25 // load return route from storage on mount 26 storage.getItem("returnRoute").then((stored) => { 27 if (stored) { 28 try { ··· 82 if ( 83 lastAuthStatus !== "loggedIn" && 84 authStatus === "loggedIn" && 85 - returnRoute 86 ) { 87 console.log( 88 "Login successful, navigating back to returnRoute:",
··· 2 import { storage } from "@streamplace/components"; 3 import { useURL } from "expo-linking"; 4 import { useEffect, useState } from "react"; 5 + import { Platform } from "react-native"; 6 import { useStore } from "store"; 7 import { useIsReady, useOAuthSession, useUserProfile } from "store/hooks"; 8 import { navigateToRoute } from "utils/navigation"; ··· 24 loadOAuthClient(); 25 26 // load return route from storage on mount 27 + if (Platform.OS !== "web") { 28 + return; 29 + } 30 storage.getItem("returnRoute").then((stored) => { 31 if (stored) { 32 try { ··· 86 if ( 87 lastAuthStatus !== "loggedIn" && 88 authStatus === "loggedIn" && 89 + returnRoute && 90 + Platform.OS === "web" 91 ) { 92 console.log( 93 "Login successful, navigating back to returnRoute:",
+8 -3
js/app/hooks/useBlueskyNotifications.tsx
··· 1 import { useToast } from "@streamplace/components"; 2 import { CircleX } from "lucide-react-native"; 3 import { useEffect } from "react"; 4 import { useStore } from "../store"; 5 6 function titleCase(str: string) { ··· 18 let toast = useToast(); 19 const notification = useStore((state) => state.notification); 20 const clearNotification = useStore((state) => state.clearNotification); 21 22 useEffect(() => { 23 if (notification) { ··· 41 { 42 duration: 100, 43 variant: notification.type, 44 - actionLabel: "Copy message", 45 iconLeft: CircleX, 46 onAction: () => { 47 navigator.clipboard.writeText( ··· 59 notification.message, 60 { 61 variant: notification.type, 62 - actionLabel: "Copy message", 63 onAction: () => { 64 navigator.clipboard.writeText(notification.message); 65 }, ··· 74 notification.message, 75 { 76 variant: notification.type, 77 - actionLabel: "Copy message", 78 onAction: () => { 79 navigator.clipboard.writeText(notification.message); 80 },
··· 1 import { useToast } from "@streamplace/components"; 2 import { CircleX } from "lucide-react-native"; 3 import { useEffect } from "react"; 4 + import { Platform } from "react-native"; 5 + import clearQueryParams from "utils/clear-query-params"; 6 import { useStore } from "../store"; 7 8 function titleCase(str: string) { ··· 20 let toast = useToast(); 21 const notification = useStore((state) => state.notification); 22 const clearNotification = useStore((state) => state.clearNotification); 23 + 24 + // we've already saved the notif to the store 25 + clearQueryParams(["error", "error_description"]); 26 27 useEffect(() => { 28 if (notification) { ··· 46 { 47 duration: 100, 48 variant: notification.type, 49 + actionLabel: Platform.OS === "web" ? "Copy message" : undefined, 50 iconLeft: CircleX, 51 onAction: () => { 52 navigator.clipboard.writeText( ··· 64 notification.message, 65 { 66 variant: notification.type, 67 + actionLabel: Platform.OS === "web" ? "Copy message" : undefined, 68 onAction: () => { 69 navigator.clipboard.writeText(notification.message); 70 }, ··· 79 notification.message, 80 { 81 variant: notification.type, 82 + actionLabel: Platform.OS === "web" ? "Copy message" : undefined, 83 onAction: () => { 84 navigator.clipboard.writeText(notification.message); 85 },
+1 -1
js/app/hooks/useSegmentTiming.tsx
··· 22 export function useSegmentTiming() { 23 const latestSegment = useLivestreamStore((x) => x.segment); 24 const [segmentDeltas, setSegmentDeltas] = useState<number[]>([]); 25 - const prevSegmentRef = useRef<any>(null); 26 const prevTimestampRef = useRef<number | null>(null); 27 28 // Dummy state to force update every second
··· 22 export function useSegmentTiming() { 23 const latestSegment = useLivestreamStore((x) => x.segment); 24 const [segmentDeltas, setSegmentDeltas] = useState<number[]>([]); 25 + const prevSegmentRef = useRef<any>(); 26 const prevTimestampRef = useRef<number | null>(null); 27 28 // Dummy state to force update every second
+1 -1
js/app/package.json
··· 1 { 2 "name": "@streamplace/app", 3 "main": "./src/entrypoint.tsx", 4 - "version": "0.9.0", 5 "runtimeVersion": "0.7.2", 6 "scripts": { 7 "start": "npx expo start -c --port 38081",
··· 1 { 2 "name": "@streamplace/app", 3 "main": "./src/entrypoint.tsx", 4 + "version": "0.9.9", 5 "runtimeVersion": "0.7.2", 6 "scripts": { 7 "start": "npx expo start -c --port 38081",
+21 -7
js/app/src/router.tsx
··· 81 import HomeScreen from "./screens/home"; 82 83 import { useUrl } from "@streamplace/components"; 84 import { BrandingAdmin } from "components/settings/branding-admin"; 85 import { LanguagesCategorySettings } from "components/settings/languages-category-settings"; 86 import MultistreamManager from "components/settings/multistream-manager"; ··· 297 const AvatarButton = () => { 298 const userProfile = useUserProfile(); 299 const openLoginModal = useStore((state) => state.openLoginModal); 300 const loginAction = useStore((state) => state.login); 301 const openLoginLink = useStore((state) => state.openLoginLink); 302 const { theme } = useTheme(); ··· 332 ); 333 } 334 335 - const handleSignup = () => { 336 - // TODO: remove requirement for oauth-protected-resource in oatproxy 337 - loginAction("https://bsky.social", openLoginLink); 338 - }; 339 - 340 if (isCompact) { 341 return ( 342 <Button ··· 369 <Text style={{ color: theme.colors.text }}>Log In</Text> 370 </Button> 371 <Button 372 - onPress={handleSignup} 373 variant="primary" 374 width="min" 375 style={[zero.r.full]} ··· 477 const pollMySegments = useStore((state) => state.pollMySegments); 478 const showLoginModal = useStore((state) => state.showLoginModal); 479 const closeLoginModal = useStore((state) => state.closeLoginModal); 480 const [livePopup, setLivePopup] = useState(false); 481 const siteTitle = useSiteTitle(); 482 const defaultStreamer = useDefaultStreamer(); 483 ··· 784 }} 785 /> 786 </Drawer.Navigator> 787 - <LoginModal visible={showLoginModal} onClose={closeLoginModal} /> 788 </> 789 ); 790 }
··· 81 import HomeScreen from "./screens/home"; 82 83 import { useUrl } from "@streamplace/components"; 84 + import PdsHostSelectorModal from "components/login/pds-host-selector-modal"; 85 import { BrandingAdmin } from "components/settings/branding-admin"; 86 import { LanguagesCategorySettings } from "components/settings/languages-category-settings"; 87 import MultistreamManager from "components/settings/multistream-manager"; ··· 298 const AvatarButton = () => { 299 const userProfile = useUserProfile(); 300 const openLoginModal = useStore((state) => state.openLoginModal); 301 + const openPDSModal = useStore((state) => state.openPdsModal); 302 const loginAction = useStore((state) => state.login); 303 const openLoginLink = useStore((state) => state.openLoginLink); 304 const { theme } = useTheme(); ··· 334 ); 335 } 336 337 if (isCompact) { 338 return ( 339 <Button ··· 366 <Text style={{ color: theme.colors.text }}>Log In</Text> 367 </Button> 368 <Button 369 + onPress={() => openPDSModal()} 370 variant="primary" 371 width="min" 372 style={[zero.r.full]} ··· 474 const pollMySegments = useStore((state) => state.pollMySegments); 475 const showLoginModal = useStore((state) => state.showLoginModal); 476 const closeLoginModal = useStore((state) => state.closeLoginModal); 477 + const showPdsModal = useStore((state) => state.showPdsModal); 478 + const openPdsModal = useStore((state) => state.openPdsModal); 479 + const closePdsModal = useStore((state) => state.closePdsModal); 480 const [livePopup, setLivePopup] = useState(false); 481 + const loginAction = useStore((state) => state.login); 482 + const openLoginLink = useStore((state) => state.openLoginLink); 483 const siteTitle = useSiteTitle(); 484 const defaultStreamer = useDefaultStreamer(); 485 ··· 786 }} 787 /> 788 </Drawer.Navigator> 789 + <LoginModal 790 + visible={showLoginModal} 791 + onClose={closeLoginModal} 792 + onOpenPdsModal={openPdsModal} 793 + /> 794 + <PdsHostSelectorModal 795 + open={showPdsModal} 796 + onOpenChange={closePdsModal} 797 + onSubmit={(pdsHost) => { 798 + closePdsModal(); 799 + loginAction(pdsHost, openLoginLink); 800 + }} 801 + /> 802 </> 803 ); 804 }
+23 -3
js/app/src/screens/mobile-stream.tsx
··· 1 import { 2 KeepAwake, 3 LivestreamProvider, ··· 33 user, 34 src, 35 extraProps, 36 }: { 37 user: string; 38 src: string; 39 extraProps: Partial<PlayerProps>; 40 }) { 41 const problems = useLivestreamStore((x) => x.problems); 42 ··· 52 <> 53 <KeepAwake /> 54 <FullscreenProvider> 55 - <Player src={src} {...extraProps} /> 56 </FullscreenProvider> 57 </> 58 ); ··· 60 61 export default function MobileStream({ route }) { 62 const { user, protocol, url } = route?.params ?? {}; 63 let extraProps: Partial<PlayerProps> = {}; 64 if (isWeb) { 65 extraProps = queryToProps(new URLSearchParams(window.location.search)); ··· 69 src = url; 70 } 71 72 return ( 73 - <LivestreamProvider src={src}> 74 <PlayerProvider> 75 - <MobileStreamInner user={user} src={src} extraProps={extraProps} /> 76 </PlayerProvider> 77 </LivestreamProvider> 78 );
··· 1 + import { useNavigation } from "@react-navigation/native"; 2 import { 3 KeepAwake, 4 LivestreamProvider, ··· 34 user, 35 src, 36 extraProps, 37 + onTeleport, 38 }: { 39 user: string; 40 src: string; 41 extraProps: Partial<PlayerProps>; 42 + onTeleport?: (targetHandle: string, targetDID: string) => void; 43 }) { 44 const problems = useLivestreamStore((x) => x.problems); 45 ··· 55 <> 56 <KeepAwake /> 57 <FullscreenProvider> 58 + <Player key={src} src={src} {...extraProps} onTeleport={onTeleport} /> 59 </FullscreenProvider> 60 </> 61 ); ··· 63 64 export default function MobileStream({ route }) { 65 const { user, protocol, url } = route?.params ?? {}; 66 + let navi = useNavigation(); 67 let extraProps: Partial<PlayerProps> = {}; 68 if (isWeb) { 69 extraProps = queryToProps(new URLSearchParams(window.location.search)); ··· 73 src = url; 74 } 75 76 + const handleTeleport = (targetHandle: string, targetDID?: string) => { 77 + if (!navi || (!targetHandle && !targetDID)) { 78 + console.error("Navigation or target info missing for teleport"); 79 + return; 80 + } 81 + navi.navigate("Home", { 82 + screen: "Stream", 83 + params: { user: targetHandle }, 84 + }); 85 + }; 86 + 87 return ( 88 + <LivestreamProvider key={src} src={src} onTeleport={handleTeleport}> 89 <PlayerProvider> 90 + <MobileStreamInner 91 + user={user} 92 + src={src} 93 + extraProps={extraProps} 94 + onTeleport={handleTeleport} 95 + /> 96 </PlayerProvider> 97 </LivestreamProvider> 98 );
+1 -13
js/app/store/slices/baseSlice.ts
··· 1 import { storage } from "@streamplace/components"; 2 - import { v4 as uuidv4 } from "uuid"; 3 import { StateCreator } from "zustand"; 4 5 export const STORED_KEY_KEY = "storedKey"; 6 export const DID_KEY = "did"; 7 - export const DEVICE_ID_KEY = "deviceId"; 8 9 export interface StreamKey { 10 privateKey: string; ··· 14 15 export interface BaseSlice { 16 hydrated: boolean; 17 - deviceId: string; 18 hydrate: () => Promise<void>; 19 } 20 21 export const createBaseSlice: StateCreator<BaseSlice> = (set, get) => ({ 22 hydrated: false, 23 - deviceId: "", 24 hydrate: async () => { 25 try { 26 let storedKey: StreamKey | null = null; ··· 28 if (storedKeyStr) { 29 storedKey = JSON.parse(storedKeyStr); 30 } 31 - 32 - // Load or generate device ID 33 - let deviceId = await storage.getItem(DEVICE_ID_KEY); 34 - if (!deviceId) { 35 - deviceId = uuidv4(); 36 - await storage.setItem(DEVICE_ID_KEY, deviceId); 37 - } 38 - 39 - set({ hydrated: true, deviceId }); 40 } catch (e) { 41 set({ hydrated: false }); 42 }
··· 1 import { storage } from "@streamplace/components"; 2 import { StateCreator } from "zustand"; 3 4 export const STORED_KEY_KEY = "storedKey"; 5 export const DID_KEY = "did"; 6 7 export interface StreamKey { 8 privateKey: string; ··· 12 13 export interface BaseSlice { 14 hydrated: boolean; 15 hydrate: () => Promise<void>; 16 } 17 18 export const createBaseSlice: StateCreator<BaseSlice> = (set, get) => ({ 19 hydrated: false, 20 hydrate: async () => { 21 try { 22 let storedKey: StreamKey | null = null; ··· 24 if (storedKeyStr) { 25 storedKey = JSON.parse(storedKeyStr); 26 } 27 + set({ hydrated: true }); 28 } catch (e) { 29 set({ hydrated: false }); 30 }
+14 -16
js/app/store/slices/blueskySlice.ts
··· 19 PlaceStreamServerSettings, 20 StreamplaceAgent, 21 } from "streamplace"; 22 import { privateKeyToAccount } from "viem/accounts"; 23 import { StateCreator } from "zustand"; 24 import createOAuthClient, { ··· 86 showLoginModal: boolean; 87 openLoginModal: (returnRoute?: { name: string; params?: any }) => void; 88 closeLoginModal: () => void; 89 golivePost: ( 90 text: string, 91 now: Date, ··· 114 createServerSettingsRecord: (debugRecording: boolean) => Promise<void>; 115 } 116 117 - const clearQueryParams = () => { 118 - if (Platform.OS !== "web") { 119 - return; 120 - } 121 - const u = new URL(document.location.href); 122 - const params = new URLSearchParams(u.search); 123 - if (u.search === "") { 124 - return; 125 - } 126 - params.delete("iss"); 127 - params.delete("state"); 128 - params.delete("code"); 129 - u.search = params.toString(); 130 - window.history.replaceState(null, "", u.toString()); 131 - }; 132 - 133 const uploadThumbnail = async ( 134 handle: string, 135 u: URL, ··· 210 serverSettings: null, 211 returnRoute: null, 212 showLoginModal: false, 213 notification: null, 214 215 clearNotification: () => { 216 set({ notification: null }); 217 }, 218 ··· 237 closeLoginModal: () => { 238 console.log("closeLoginModal"); 239 set({ showLoginModal: false }); 240 }, 241 242 loadOAuthClient: async () => {
··· 19 PlaceStreamServerSettings, 20 StreamplaceAgent, 21 } from "streamplace"; 22 + import clearQueryParams from "utils/clear-query-params"; 23 import { privateKeyToAccount } from "viem/accounts"; 24 import { StateCreator } from "zustand"; 25 import createOAuthClient, { ··· 87 showLoginModal: boolean; 88 openLoginModal: (returnRoute?: { name: string; params?: any }) => void; 89 closeLoginModal: () => void; 90 + showPdsModal: boolean; 91 + openPdsModal: () => void; 92 + closePdsModal: () => void; 93 golivePost: ( 94 text: string, 95 now: Date, ··· 118 createServerSettingsRecord: (debugRecording: boolean) => Promise<void>; 119 } 120 121 const uploadThumbnail = async ( 122 handle: string, 123 u: URL, ··· 198 serverSettings: null, 199 returnRoute: null, 200 showLoginModal: false, 201 + showPdsModal: false, 202 notification: null, 203 204 clearNotification: () => { 205 + clearQueryParams(); 206 set({ notification: null }); 207 }, 208 ··· 227 closeLoginModal: () => { 228 console.log("closeLoginModal"); 229 set({ showLoginModal: false }); 230 + }, 231 + 232 + openPdsModal: () => { 233 + set({ showPdsModal: true }); 234 + }, 235 + 236 + closePdsModal: () => { 237 + set({ showPdsModal: false }); 238 }, 239 240 loadOAuthClient: async () => {
+11 -15
js/app/store/slices/contentMetadataSlice.ts
··· 1 import { AppStore } from "store"; 2 import { StateCreator } from "zustand"; 3 import { BlueskySlice } from "./blueskySlice"; ··· 201 }); 202 203 try { 204 - let targetPDS = null; 205 try { 206 - const didResponse = await fetch(`https://plc.directory/${targetDid}`); 207 - if (didResponse.ok) { 208 - const didDoc = await didResponse.json(); 209 - const pdsService = didDoc.service?.find( 210 - (s: any) => s.id === "#atproto_pds", 211 - ); 212 - if (pdsService) { 213 - targetPDS = pdsService.serviceEndpoint; 214 - console.log( 215 - `[getContentMetadata] Resolved PDS for ${targetDid}:`, 216 - targetPDS, 217 - ); 218 - } 219 - } 220 } catch (pdsResolveError) { 221 console.log( 222 `[getContentMetadata] Failed to resolve PDS for ${targetDid}:`,
··· 1 + import { 2 + getPDSServiceEndpoint, 3 + resolveDIDDocument, 4 + } from "@streamplace/components"; 5 import { AppStore } from "store"; 6 import { StateCreator } from "zustand"; 7 import { BlueskySlice } from "./blueskySlice"; ··· 205 }); 206 207 try { 208 + let targetPDS: string | null = null; 209 try { 210 + const didDoc = await resolveDIDDocument(targetDid); 211 + targetPDS = getPDSServiceEndpoint(didDoc); 212 + console.log( 213 + `[getContentMetadata] Resolved PDS for ${targetDid}:`, 214 + targetPDS, 215 + ); 216 } catch (pdsResolveError) { 217 console.log( 218 `[getContentMetadata] Failed to resolve PDS for ${targetDid}:`,
-3
js/app/store/slices/streamplaceSlice.ts
··· 1 import { storage } from "@streamplace/components"; 2 - import { uuidv4 } from "hooks/uuid"; 3 import { Platform } from "react-native"; 4 import type { PlaceStreamSegment } from "streamplace"; 5 import { StateCreator } from "zustand"; ··· 31 initialized: boolean; 32 userMuted: boolean | null; 33 chatWarned: boolean; 34 - sessionId: string; 35 mySegments: PlaceStreamSegment.SegmentView[]; 36 // actions 37 initialize: () => Promise<void>; ··· 60 initialized: false, 61 userMuted: null, 62 chatWarned: false, 63 - sessionId: uuidv4(), 64 mySegments: [], 65 initialize: async () => { 66 let [url, userMutedStr, chatWarningStr] = await Promise.all([
··· 1 import { storage } from "@streamplace/components"; 2 import { Platform } from "react-native"; 3 import type { PlaceStreamSegment } from "streamplace"; 4 import { StateCreator } from "zustand"; ··· 30 initialized: boolean; 31 userMuted: boolean | null; 32 chatWarned: boolean; 33 mySegments: PlaceStreamSegment.SegmentView[]; 34 // actions 35 initialize: () => Promise<void>; ··· 58 initialized: false, 59 userMuted: null, 60 chatWarned: false, 61 mySegments: [], 62 initialize: async () => { 63 let [url, userMutedStr, chatWarningStr] = await Promise.all([
+15
js/app/utils/clear-query-params.ts
···
··· 1 + import { Platform } from "react-native"; 2 + 3 + export default function clearQueryParams(par = ["iss", "state", "code"]) { 4 + if (Platform.OS !== "web") { 5 + return; 6 + } 7 + const u = new URL(document.location.href); 8 + const params = new URLSearchParams(u.search); 9 + if (u.search === "") { 10 + return; 11 + } 12 + par.forEach((p) => params.delete(p)); 13 + u.search = params.toString(); 14 + window.history.replaceState(null, "", u.toString()); 15 + }
+3 -6
js/atproto-oauth-client-react-native/README.md
··· 87 forwarded the port with `adb reverse`. For testing on iOS hardware, you'll 88 instead need to set up TLS. 89 90 - [react-native-quick-crypto]: 91 - https://github.com/margelo/react-native-quick-crypto 92 [expo-sqlite]: https://docs.expo.dev/versions/latest/sdk/sqlite/ 93 - [README]: 94 - https://github.com/bluesky-social/atproto/tree/main/packages/oauth/oauth-client-browser 95 - [example]: 96 - https://github.com/bluesky-social/atproto/tree/main/packages/oauth/oauth-client-browser-example
··· 87 forwarded the port with `adb reverse`. For testing on iOS hardware, you'll 88 instead need to set up TLS. 89 90 + [react-native-quick-crypto]: https://github.com/margelo/react-native-quick-crypto 91 [expo-sqlite]: https://docs.expo.dev/versions/latest/sdk/sqlite/ 92 + [README]: https://github.com/bluesky-social/atproto/tree/main/packages/oauth/oauth-client-browser 93 + [example]: https://github.com/bluesky-social/atproto/tree/main/packages/oauth/oauth-client-browser-example
+1 -1
js/atproto-oauth-client-react-native/package.json
··· 1 { 2 "name": "@streamplace/atproto-oauth-client-react-native", 3 - "version": "0.9.0", 4 "license": "MIT", 5 "description": "ATProto OAuth client for React Native", 6 "keywords": [
··· 1 { 2 "name": "@streamplace/atproto-oauth-client-react-native", 3 + "version": "0.9.9", 4 "license": "MIT", 5 "description": "ATProto OAuth client for React Native", 6 "keywords": [
js/components/assets/badges/live.png

This is a binary file and will not be displayed.

js/components/assets/badges/mod.png

This is a binary file and will not be displayed.

js/components/assets/badges/vip.png

This is a binary file and will not be displayed.

+13 -1
js/components/locales/en-US/common.ftl
··· 51 [streamer] Looks like <1>@{ $handle } is offline</1>, but they recommend checking out: 52 *[default] Looks like <1>@{ $handle } is offline</1>, but we recommend checking out: 53 } 54 - user-offline-no-recommendations = 55 Looks like <1>@{ $handle } is offline</1> right now. 56 Check back later. 57 streaming-title = streaming { $title } ··· 60 [1] 1 viewer 61 *[other] { $count } viewers 62 }
··· 51 [streamer] Looks like <1>@{ $handle } is offline</1>, but they recommend checking out: 52 *[default] Looks like <1>@{ $handle } is offline</1>, but we recommend checking out: 53 } 54 + user-offline-no-recommendations = 55 Looks like <1>@{ $handle } is offline</1> right now. 56 Check back later. 57 streaming-title = streaming { $title } ··· 60 [1] 1 viewer 61 *[other] { $count } viewers 62 } 63 + 64 + ## PDS Host Selector 65 + pds-selector-title = New to the Atmosphere? 66 + pds-selector-description = You'll need to select a PDS (Personal Data Server) to access apps on the Atmosphere, such as Bluesky, Tangled, and Spark. 67 + pds-selector-custom-label = Another PDS 68 + pds-selector-custom-description = Enter your own PDS host URL 69 + pds-selector-custom-url-label = Custom PDS URL 70 + pds-selector-custom-url-placeholder = https://pds.example.com 71 + pds-selector-learn-more = Learn more about self-hosting 72 + pds-selector-info = Each host has their own policies and reliability standards. Your ATProto data lives on the host you choose and you can migrate later. Note: Streamplace has its own moderation rules - you can be banned from Streamplace regardless of which host you choose. 73 + pds-selector-read-policies = Read { $label }'s <tosLink>Terms of Service</tosLink> and <privacyLink>Privacy Policy</privacyLink> before continuing. 74 + pds-selector-handle-policy-checkbox = I have read and agree to the <policyLink>handle policy</policyLink>
+2 -1
js/components/locales/en-US/settings.ftl
··· 121 active = Active 122 123 ## Multistreaming 124 - multistreaming = Multistreaming 125 multistream-targets = Multistream Targets 126 multistream-description = Automatically push your Streamplace livestreams to other streaming services like Twitch or YouTube. 127 create-multistream-target = Create Multistream Target ··· 168 no-languages-found = No languages found 169 170 ## Branding Administration 171 branding-admin = Branding Administration 172 branding-admin-description = Customize your Streamplace instance. Note that settings may take a few hours to propagate. 173 branding-login-required = Please log in to manage branding
··· 121 active = Active 122 123 ## Multistreaming 124 + multistream = Multistreaming 125 multistream-targets = Multistream Targets 126 multistream-description = Automatically push your Streamplace livestreams to other streaming services like Twitch or YouTube. 127 create-multistream-target = Create Multistream Target ··· 168 no-languages-found = No languages found 169 170 ## Branding Administration 171 + branding = Branding 172 branding-admin = Branding Administration 173 branding-admin-description = Customize your Streamplace instance. Note that settings may take a few hours to propagate. 174 branding-login-required = Please log in to manage branding
+2 -1
js/components/package.json
··· 1 { 2 "name": "@streamplace/components", 3 - "version": "0.9.0", 4 "description": "Streamplace React (Native) Components", 5 "main": "dist/index.js", 6 "types": "src/index.tsx", ··· 42 "expo-sensors": "^15.0.7", 43 "expo-sqlite": "~15.2.12", 44 "expo-video": "^2.0.0", 45 "hls.js": "^1.5.17", 46 "i18next": "^25.4.2", 47 "i18next-browser-languagedetector": "^8.2.0",
··· 1 { 2 "name": "@streamplace/components", 3 + "version": "0.9.9", 4 "description": "Streamplace React (Native) Components", 5 "main": "dist/index.js", 6 "types": "src/index.tsx", ··· 42 "expo-sensors": "^15.0.7", 43 "expo-sqlite": "~15.2.12", 44 "expo-video": "^2.0.0", 45 + "graphemer": "^1.4.0", 46 "hls.js": "^1.5.17", 47 "i18next": "^25.4.2", 48 "i18next-browser-languagedetector": "^8.2.0",
+107 -24
js/components/src/components/chat/chat-box.tsx
··· 1 import Picker from "@emoji-mart/react"; 2 import { AtSignIcon, ExternalLink, X } from "lucide-react-native"; 3 import { useEffect, useMemo, useRef, useState } from "react"; 4 import { Platform, Pressable, TextInput } from "react-native"; 5 import { ChatMessageViewHydrated } from "streamplace"; 6 - import { 7 - Button, 8 - Loader, 9 - Text, 10 - useChat, 11 - useCreateChatMessage, 12 - useLivestream, 13 - useReplyToMessage, 14 - useSetReplyToMessage, 15 - useTheme, 16 - View, 17 - } from "../../"; 18 import { 19 borders, 20 flex, ··· 28 r, 29 w, 30 } from "../../lib/theme/atoms"; 31 import { Textarea } from "../ui/textarea"; 32 import { RenderChatMessage } from "./chat-message"; 33 import { EmojiData, EmojiSuggestions } from "./emoji-suggestions"; ··· 37 // @ts-ignore we can iterate through this just fine it seems 38 ..."๐Ÿ˜€๐Ÿฅธ๐Ÿ˜๐Ÿ˜˜๐Ÿ˜๐Ÿฅธ๐Ÿ˜†๐Ÿฅธ๐Ÿ˜œ๐Ÿฅธ๐Ÿ˜‚๐Ÿ˜…๐Ÿฅธ๐Ÿ™‚๐Ÿคซ๐Ÿ˜ฑ๐Ÿฅธ๐Ÿคฃ๐Ÿ˜—๐Ÿ˜„๐Ÿฅธ๐Ÿ˜Ž๐Ÿค“๐Ÿ˜ฒ๐Ÿ˜ฏ๐Ÿ˜ฐ๐Ÿฅธ๐Ÿ˜ฅ๐Ÿฅธ๐Ÿ˜ฃ๐Ÿฅธ๐Ÿ˜ž๐Ÿ˜“๐Ÿฅธ๐Ÿ˜ฉ๐Ÿ˜ฉ๐Ÿฅธ๐Ÿ˜ค๐Ÿฅฑ", 39 ]; 40 41 export function ChatBox({ 42 isPopout, ··· 62 new Map(), 63 ); 64 const [filteredEmojis, setFilteredEmojis] = useState<any[]>([]); 65 66 let linfo = useLivestream(); 67 ··· 73 const setReplyToMessage = useSetReplyToMessage(); 74 const textAreaRef = useRef<TextInput>(null); 75 76 const authors = useMemo(() => { 77 if (!chat) return null; 78 return chat.reduce((acc, msg) => { ··· 83 return acc; 84 }, new Map<string, ChatMessageViewHydrated["chatProfile"]>()); 85 }, [chat]); 86 87 const handleMentionSelect = (handle: string) => { 88 const beforeAt = message.slice(0, message.lastIndexOf("@")); ··· 232 } 233 }; 234 235 - const submit = () => { 236 if (!message.trim()) return; 237 setMessage(""); 238 setReplyToMessage(null); 239 240 setSubmitting(true); 241 - createChatMessage({ 242 - text: message, 243 - reply: replyTo || undefined, 244 - }); 245 - setSubmitting(false); 246 247 - // if we press "send" button, we want the same action as pressing "Enter" 248 - // if we're already focused no need to do extra work 249 if (textAreaRef.current && !textAreaRef.current.isFocused()) { 250 textAreaRef.current.focus(); 251 requestAnimationFrame(() => { ··· 412 } 413 } 414 }} 415 - style={[chatBoxStyle]} 416 // "submit" won't blur on enter 417 submitBehavior="submit" 418 placeholder="Type a message..." ··· 452 { justifyContent: "flex-end" }, 453 ]} 454 > 455 <Button 456 variant="secondary" 457 style={{ borderRadius: 16, maxWidth: 44, aspectRatio: 1 }} 458 aria-label="Insert Mention" 459 onPress={() => { 460 - // if the last character is not @, add it 461 !message.endsWith("@") && setMessage(message + "@"); 462 - // get all the text after the last @ 463 const atIndex = message.lastIndexOf("@"); 464 const searchText = message.slice(atIndex + 1).toLowerCase(); 465 updateSuggestions(searchText); 466 setShowSuggestions(true); 467 - // focus the textarea 468 textAreaRef.current?.focus(); 469 }} 470 >
··· 1 import Picker from "@emoji-mart/react"; 2 + import Graphemer from "graphemer"; 3 import { AtSignIcon, ExternalLink, X } from "lucide-react-native"; 4 + import { env } from "process"; 5 import { useEffect, useMemo, useRef, useState } from "react"; 6 import { Platform, Pressable, TextInput } from "react-native"; 7 import { ChatMessageViewHydrated } from "streamplace"; 8 + import { Button, Loader, Text, toast, useTheme, View } from "../../"; 9 + import { handleSlashCommand } from "../../lib/slash-commands"; 10 + import { registerTeleportCommand } from "../../lib/slash-commands/teleport"; 11 + import { StreamNotifications } from "../../lib/stream-notifications"; 12 + import { SystemMessages } from "../../lib/system-messages"; 13 import { 14 borders, 15 flex, ··· 23 r, 24 w, 25 } from "../../lib/theme/atoms"; 26 + import { 27 + useChat, 28 + useCreateChatMessage, 29 + useLivestream, 30 + useLivestreamStore, 31 + useReplyToMessage, 32 + useSetReplyToMessage, 33 + } from "../../livestream-store"; 34 + import { useDID, usePDSAgent } from "../../streamplace-store"; 35 import { Textarea } from "../ui/textarea"; 36 import { RenderChatMessage } from "./chat-message"; 37 import { EmojiData, EmojiSuggestions } from "./emoji-suggestions"; ··· 41 // @ts-ignore we can iterate through this just fine it seems 42 ..."๐Ÿ˜€๐Ÿฅธ๐Ÿ˜๐Ÿ˜˜๐Ÿ˜๐Ÿฅธ๐Ÿ˜†๐Ÿฅธ๐Ÿ˜œ๐Ÿฅธ๐Ÿ˜‚๐Ÿ˜…๐Ÿฅธ๐Ÿ™‚๐Ÿคซ๐Ÿ˜ฑ๐Ÿฅธ๐Ÿคฃ๐Ÿ˜—๐Ÿ˜„๐Ÿฅธ๐Ÿ˜Ž๐Ÿค“๐Ÿ˜ฒ๐Ÿ˜ฏ๐Ÿ˜ฐ๐Ÿฅธ๐Ÿ˜ฅ๐Ÿฅธ๐Ÿ˜ฃ๐Ÿฅธ๐Ÿ˜ž๐Ÿ˜“๐Ÿฅธ๐Ÿ˜ฉ๐Ÿ˜ฉ๐Ÿฅธ๐Ÿ˜ค๐Ÿฅฑ", 43 ]; 44 + 45 + const graphemer = new Graphemer(); 46 47 export function ChatBox({ 48 isPopout, ··· 68 new Map(), 69 ); 70 const [filteredEmojis, setFilteredEmojis] = useState<any[]>([]); 71 + const isOverLimit = graphemer.countGraphemes(message) > 300; 72 73 let linfo = useLivestream(); 74 ··· 80 const setReplyToMessage = useSetReplyToMessage(); 81 const textAreaRef = useRef<TextInput>(null); 82 83 + const pdsAgent = usePDSAgent(); 84 + const userDID = useDID(); 85 + const setActiveTeleportUri = useLivestreamStore( 86 + (state) => state.setActiveTeleportUri, 87 + ); 88 + 89 + useEffect(() => { 90 + if (pdsAgent && userDID) { 91 + registerTeleportCommand(pdsAgent, userDID, setActiveTeleportUri); 92 + } 93 + }, [pdsAgent, userDID, setActiveTeleportUri]); 94 + 95 const authors = useMemo(() => { 96 if (!chat) return null; 97 return chat.reduce((acc, msg) => { ··· 102 return acc; 103 }, new Map<string, ChatMessageViewHydrated["chatProfile"]>()); 104 }, [chat]); 105 + 106 + useEffect(() => { 107 + if (pdsAgent && linfo?.author?.did && pdsAgent.did === linfo.author.did) { 108 + registerTeleportCommand(pdsAgent, pdsAgent.did, setActiveTeleportUri); 109 + } 110 + }, [pdsAgent, linfo?.author?.did, setActiveTeleportUri]); 111 112 const handleMentionSelect = (handle: string) => { 113 const beforeAt = message.slice(0, message.lastIndexOf("@")); ··· 257 } 258 }; 259 260 + const submit = async () => { 261 if (!message.trim()) return; 262 + if (graphemer.countGraphemes(message) > 300) { 263 + toast.show( 264 + "Message too long", 265 + "Please limit your message to 300 characters.", 266 + { 267 + variant: "error", 268 + duration: 3, 269 + }, 270 + ); 271 + return; 272 + } 273 + 274 + const messageText = message; 275 setMessage(""); 276 setReplyToMessage(null); 277 278 + if (messageText.startsWith("/")) { 279 + const result = await handleSlashCommand(messageText); 280 + if (result.handled) { 281 + if (result.error) { 282 + console.error("Slash command error:", result.error); 283 + SystemMessages.commandError(result.error); 284 + } 285 + return; 286 + } 287 + } 288 setSubmitting(true); 289 290 + try { 291 + const result = await handleSlashCommand(messageText); 292 + 293 + if (result.handled) { 294 + if (result.error) { 295 + console.error("Slash command error:", result.error); 296 + } 297 + } else { 298 + createChatMessage({ 299 + text: messageText, 300 + reply: replyTo || undefined, 301 + }); 302 + } 303 + } catch (err) { 304 + console.error("Error submitting message:", err); 305 + } finally { 306 + setSubmitting(false); 307 + } 308 + 309 if (textAreaRef.current && !textAreaRef.current.isFocused()) { 310 textAreaRef.current.focus(); 311 requestAnimationFrame(() => { ··· 472 } 473 } 474 }} 475 + style={[ 476 + chatBoxStyle, 477 + isOverLimit && { 478 + borderColor: "#ef4444", 479 + borderWidth: 2, 480 + outline: "none", 481 + }, 482 + ]} 483 // "submit" won't blur on enter 484 submitBehavior="submit" 485 placeholder="Type a message..." ··· 519 { justifyContent: "flex-end" }, 520 ]} 521 > 522 + {env.NODE_ENV === "development" && ( 523 + <Button 524 + variant="secondary" 525 + style={{ borderRadius: 16 }} 526 + width="min" 527 + onPress={() => { 528 + StreamNotifications.teleport({ 529 + targetHandle: "test.bsky.social", 530 + targetDID: "did:plc:test", 531 + countdown: 30, 532 + canCancel: true, 533 + onDismiss: (reason) => 534 + console.log("teleport dismissed:", reason), 535 + }); 536 + }} 537 + > 538 + Test Notification 539 + </Button> 540 + )} 541 <Button 542 variant="secondary" 543 style={{ borderRadius: 16, maxWidth: 44, aspectRatio: 1 }} 544 aria-label="Insert Mention" 545 onPress={() => { 546 !message.endsWith("@") && setMessage(message + "@"); 547 const atIndex = message.lastIndexOf("@"); 548 const searchText = message.slice(atIndex + 1).toLowerCase(); 549 updateSuggestions(searchText); 550 setShowSuggestions(true); 551 textAreaRef.current?.focus(); 552 }} 553 >
+28 -2
js/components/src/components/chat/chat-message.tsx
··· 4 Mention, 5 } from "@atproto/api/dist/client/types/app/bsky/richtext/facet"; 6 import { memo, useCallback } from "react"; 7 - import { Linking, View } from "react-native"; 8 import { ChatMessageViewHydrated } from "streamplace"; 9 import { RichtextSegment, segmentize } from "../../lib/facet"; 10 import { borders, flex, gap, ml, mr, opacity, pl } from "../../lib/theme/atoms"; ··· 23 }>; 24 } 25 26 import { useLivestreamStore } from "../../livestream-store"; 27 import { Text } from "../ui/text"; 28 ··· 76 } 77 }; 78 79 - const RichTextMessage = ({ 80 text, 81 facets, 82 }: { ··· 164 style={{ 165 fontVariant: ["tabular-nums"], 166 color: colors.gray[400], 167 }} 168 > 169 {formatTime(item.record.createdAt)} 170 </Text> 171 )} 172 <Text 173 weight="bold" 174 color="default"
··· 4 Mention, 5 } from "@atproto/api/dist/client/types/app/bsky/richtext/facet"; 6 import { memo, useCallback } from "react"; 7 + import { Image, Linking, View } from "react-native"; 8 import { ChatMessageViewHydrated } from "streamplace"; 9 import { RichtextSegment, segmentize } from "../../lib/facet"; 10 import { borders, flex, gap, ml, mr, opacity, pl } from "../../lib/theme/atoms"; ··· 23 }>; 24 } 25 26 + import { zero } from "../.."; 27 import { useLivestreamStore } from "../../livestream-store"; 28 import { Text } from "../ui/text"; 29 ··· 77 } 78 }; 79 80 + export const RichTextMessage = ({ 81 text, 82 facets, 83 }: { ··· 165 style={{ 166 fontVariant: ["tabular-nums"], 167 color: colors.gray[400], 168 + width: 44, 169 }} 170 > 171 {formatTime(item.record.createdAt)} 172 </Text> 173 )} 174 + {item.badges?.length ? ( 175 + <View style={[zero.layout.flex.align.end]}> 176 + {item.badges.map((badge, index) => ( 177 + <View style={{ height: 3 }} key={`badge-${index}`}> 178 + {badge.badgeType === "place.stream.badge.defs#mod" ? ( 179 + <Image 180 + source={require("../../../assets/badges/mod.png")} 181 + style={{ height: 20, width: 20, marginTop: 3 }} 182 + /> 183 + ) : badge.badgeType === "place.stream.badge.defs#streamer" ? ( 184 + <Image 185 + source={require("../../../assets/badges/live.png")} 186 + style={{ height: 20, width: 20, marginTop: 3 }} 187 + /> 188 + ) : ( 189 + <Image 190 + source={require("../../../assets/badges/vip.png")} 191 + style={{ height: 20, width: 20, marginTop: 3 }} 192 + /> 193 + )} 194 + </View> 195 + ))} 196 + </View> 197 + ) : null} 198 <Text 199 weight="bold" 200 color="default"
+6 -2
js/components/src/components/chat/chat.tsx
··· 13 } from "react-native-reanimated"; 14 import { ChatMessageViewHydrated } from "streamplace"; 15 import { 16 SystemMessage, 17 Text, 18 useChat, 19 usePlayerStore, ··· 171 if (item.author.did === "did:sys:system") { 172 return ( 173 <SystemMessage 174 timestamp={new Date(item.record.createdAt)} 175 title={item.record.text} 176 /> 177 ); 178 } ··· 257 258 useEffect(() => { 259 buttonOpacity.value = withTiming(isScrolledUp ? 1 : 0, { duration: 200 }); 260 - buttonTranslateY.value = withTiming(isScrolledUp ? 0 : 20, { 261 duration: 200, 262 }); 263 }, [isScrolledUp]); ··· 341 onPress={scrollToBottom} 342 style={[ 343 { 344 - pointerEvents: "auto", 345 backgroundColor: theme.colors.primary, 346 opacity: 0.9, 347 borderRadius: 20,
··· 13 } from "react-native-reanimated"; 14 import { ChatMessageViewHydrated } from "streamplace"; 15 import { 16 + getSystemMessageType, 17 SystemMessage, 18 + SystemMessageType, 19 Text, 20 useChat, 21 usePlayerStore, ··· 173 if (item.author.did === "did:sys:system") { 174 return ( 175 <SystemMessage 176 + variant={getSystemMessageType(item) || SystemMessageType.notification} 177 timestamp={new Date(item.record.createdAt)} 178 title={item.record.text} 179 + facets={item.record.facets} 180 /> 181 ); 182 } ··· 261 262 useEffect(() => { 263 buttonOpacity.value = withTiming(isScrolledUp ? 1 : 0, { duration: 200 }); 264 + buttonTranslateY.value = withTiming(isScrolledUp ? 0 : 50, { 265 duration: 200, 266 }); 267 }, [isScrolledUp]); ··· 345 onPress={scrollToBottom} 346 style={[ 347 { 348 + pointerEvents: isScrolledUp ? "auto" : "none", 349 backgroundColor: theme.colors.primary, 350 opacity: 0.9, 351 borderRadius: 20,
+2 -218
js/components/src/components/chat/mod-view.tsx
··· 5 import { 6 useCreateBlockRecord, 7 useCreateHideChatRecord, 8 - useUpdateLivestreamRecord, 9 } from "../../streamplace-store/block"; 10 import { 11 ModerationPermissions, ··· 17 import { ChatMessageViewHydrated } from "streamplace"; 18 import { 19 useDeleteChatMessage, 20 - useLivestream, 21 useLivestreamStore, 22 } from "../../livestream-store"; 23 import { useStreamplaceStore } from "../../streamplace-store"; 24 import { formatHandle, formatHandleWithAt } from "../../utils/format-handle"; 25 import { 26 atoms, 27 - Button, 28 - DialogFooter, 29 DropdownMenu, 30 DropdownMenuGroup, 31 DropdownMenuItem, 32 DropdownMenuTrigger, 33 layout, 34 - ResponsiveDialog, 35 ResponsiveDropdownMenuContent, 36 Text, 37 - Textarea, 38 useToast, 39 View, 40 } from "../ui"; ··· 61 let [messageRemoved, setMessageRemoved] = useState(false); 62 let { createBlock, isLoading: isBlockLoading } = useCreateBlockRecord(); 63 let { createHideChat, isLoading: isHideLoading } = useCreateHideChatRecord(); 64 - let { updateLivestream, isLoading: isUpdateTitleLoading } = 65 - useUpdateLivestreamRecord(); 66 - const livestream = useLivestream(); 67 - const [showUpdateTitleDialog, setShowUpdateTitleDialog] = useState(false); 68 69 const setReportModalOpen = usePlayerStore((x) => x.setReportModalOpen); 70 const setReportSubject = usePlayerStore((x) => x.setReportSubject); ··· 95 } 96 }, [message]); 97 98 - // Early return AFTER all hooks have been called 99 - if (!agent?.did) { 100 - return <></>; 101 - } 102 - 103 - // Can show moderation actions if user can hide, ban, or manage livestream 104 - const canModerate = 105 - modPermissions.canHide || 106 - modPermissions.canBan || 107 - modPermissions.canManageLivestream; 108 - 109 // Check if any moderation actions are actually available for this message 110 // This must match the individual action checks inside the DropdownMenuGroup 111 const hasAvailableActions = !!( ··· 146 createHideChat={createHideChat} 147 createBlock={createBlock} 148 toast={toast} 149 - setShowUpdateTitleDialog={setShowUpdateTitleDialog} 150 - isUpdateTitleLoading={isUpdateTitleLoading} 151 - livestream={livestream} 152 setReportModalOpen={setReportModalOpen} 153 setReportSubject={setReportSubject} 154 deleteChatMessage={deleteChatMessage} ··· 156 )} 157 </ResponsiveDropdownMenuContent> 158 </DropdownMenu> 159 - 160 - {/* Update Stream Title Dialog - rendered outside dropdown */} 161 - {showUpdateTitleDialog && ( 162 - <UpdateStreamTitleDialog 163 - livestream={livestream} 164 - streamerDID={streamerDID} 165 - updateLivestream={updateLivestream} 166 - isLoading={isUpdateTitleLoading} 167 - onClose={() => setShowUpdateTitleDialog(false)} 168 - /> 169 - )} 170 </> 171 ); 172 }); ··· 184 createHideChat: (uri: string, streamerDID?: string) => Promise<any>; 185 createBlock: (did: string, streamerDID?: string) => Promise<any>; 186 toast: ReturnType<typeof useToast>; 187 - setShowUpdateTitleDialog: (show: boolean) => void; 188 - isUpdateTitleLoading: boolean; 189 - livestream: any; 190 setReportModalOpen: (open: boolean) => void; 191 setReportSubject: (subject: any) => void; 192 deleteChatMessage: (uri: string) => Promise<any>; ··· 205 createHideChat, 206 createBlock, 207 toast, 208 - setShowUpdateTitleDialog, 209 - isUpdateTitleLoading, 210 - livestream, 211 setReportModalOpen, 212 setReportSubject, 213 deleteChatMessage, ··· 301 </DropdownMenuGroup> 302 )} 303 304 - {modPermissions.canManageLivestream && ( 305 - <DropdownMenuGroup key="stream-actions" title={`Stream actions`}> 306 - <DropdownMenuItem 307 - onPress={() => { 308 - setShowUpdateTitleDialog(true); 309 - }} 310 - disabled={isUpdateTitleLoading || !livestream} 311 - > 312 - <Text 313 - color={isUpdateTitleLoading || !livestream ? "muted" : "primary"} 314 - > 315 - {isUpdateTitleLoading ? "Updating..." : "Update stream title"} 316 - </Text> 317 - </DropdownMenuItem> 318 - </DropdownMenuGroup> 319 - )} 320 - 321 <DropdownMenuGroup key="user-actions" title={`User actions`}> 322 <DropdownMenuItem 323 onPress={() => { ··· 328 > 329 <Text color="primary">View user on {BSKY_FRONTEND_DOMAIN}</Text> 330 </DropdownMenuItem> 331 - {message.author.did === agent?.did && ( 332 <DeleteButton 333 message={message} 334 deleteChatMessage={deleteChatMessage} 335 onOpenChange={onOpenChange} 336 /> 337 )} 338 - {message.author.did !== agent?.did && ( 339 <ReportButton 340 message={message} 341 setReportModalOpen={setReportModalOpen} ··· 429 </DropdownMenuItem> 430 ); 431 } 432 - 433 - interface UpdateStreamTitleDialogProps { 434 - livestream: any; 435 - streamerDID?: string; 436 - updateLivestream: ( 437 - livestreamUri: string, 438 - title: string, 439 - streamerDID?: string, 440 - ) => Promise<any>; 441 - isLoading: boolean; 442 - onClose: () => void; 443 - } 444 - 445 - function UpdateStreamTitleDialog({ 446 - livestream, 447 - streamerDID, 448 - updateLivestream, 449 - isLoading, 450 - onClose, 451 - }: UpdateStreamTitleDialogProps) { 452 - const [title, setTitle] = useState(livestream?.record?.title || ""); 453 - const [error, setError] = useState<string | null>(null); 454 - const toast = useToast(); 455 - 456 - useEffect(() => { 457 - if (livestream?.record?.title) { 458 - setTitle(livestream.record.title); 459 - } 460 - }, [livestream?.record?.title]); 461 - 462 - const handleUpdate = async () => { 463 - setError(null); 464 - 465 - if (!title.trim()) { 466 - setError("Please enter a stream title"); 467 - return; 468 - } 469 - 470 - if (!livestream?.uri) { 471 - setError("No livestream found"); 472 - return; 473 - } 474 - 475 - try { 476 - await updateLivestream(livestream.uri, title.trim(), streamerDID); 477 - toast.show( 478 - "Stream title updated", 479 - "The stream title has been successfully updated.", 480 - { duration: 3 }, 481 - ); 482 - onClose(); 483 - } catch (err) { 484 - setError( 485 - err instanceof Error ? err.message : "Failed to update stream title", 486 - ); 487 - } 488 - }; 489 - 490 - return ( 491 - <ResponsiveDialog 492 - open={true} 493 - onOpenChange={(open) => { 494 - if (!open) { 495 - onClose(); 496 - setError(null); 497 - setTitle(livestream?.record?.title || ""); 498 - } 499 - }} 500 - title="Update Stream Title" 501 - description="Update the title of the livestream." 502 - size="md" 503 - dismissible={false} 504 - > 505 - <View style={[{ padding: 16, paddingBottom: 0 }]}> 506 - <View style={[{ marginBottom: 16 }]}> 507 - <Text 508 - style={[ 509 - { color: atoms.colors.gray[300], fontSize: 13, marginBottom: 8 }, 510 - ]} 511 - > 512 - Stream Title 513 - </Text> 514 - <Textarea 515 - value={title} 516 - onChangeText={(text) => { 517 - setTitle(text); 518 - setError(null); 519 - }} 520 - placeholder="Enter stream title..." 521 - maxLength={140} 522 - multiline 523 - style={[ 524 - { 525 - padding: 12, 526 - borderRadius: 8, 527 - backgroundColor: atoms.colors.neutral[800], 528 - color: atoms.colors.white, 529 - borderWidth: 1, 530 - borderColor: atoms.colors.neutral[600], 531 - minHeight: 100, 532 - fontSize: 16, 533 - }, 534 - ]} 535 - /> 536 - <Text 537 - style={[ 538 - { color: atoms.colors.gray[400], fontSize: 12, marginTop: 4 }, 539 - ]} 540 - > 541 - {title.length}/140 characters 542 - </Text> 543 - </View> 544 - 545 - {error && ( 546 - <View 547 - style={[ 548 - { 549 - backgroundColor: atoms.colors.red[900], 550 - padding: 12, 551 - borderRadius: 8, 552 - borderWidth: 1, 553 - borderColor: atoms.colors.red[700], 554 - marginBottom: 16, 555 - }, 556 - ]} 557 - > 558 - <Text style={[{ color: atoms.colors.red[400], fontSize: 13 }]}> 559 - {error} 560 - </Text> 561 - </View> 562 - )} 563 - </View> 564 - 565 - <DialogFooter> 566 - <Button 567 - width="min" 568 - variant="secondary" 569 - onPress={() => { 570 - onClose(); 571 - setError(null); 572 - setTitle(livestream?.record?.title || ""); 573 - }} 574 - disabled={isLoading} 575 - > 576 - <Text>Cancel</Text> 577 - </Button> 578 - <Button 579 - variant="primary" 580 - width="min" 581 - onPress={handleUpdate} 582 - disabled={isLoading || !title.trim()} 583 - > 584 - <Text>{isLoading ? "Updating..." : "Update Title"}</Text> 585 - </Button> 586 - </DialogFooter> 587 - </ResponsiveDialog> 588 - ); 589 - }
··· 5 import { 6 useCreateBlockRecord, 7 useCreateHideChatRecord, 8 } from "../../streamplace-store/block"; 9 import { 10 ModerationPermissions, ··· 16 import { ChatMessageViewHydrated } from "streamplace"; 17 import { 18 useDeleteChatMessage, 19 useLivestreamStore, 20 } from "../../livestream-store"; 21 import { useStreamplaceStore } from "../../streamplace-store"; 22 import { formatHandle, formatHandleWithAt } from "../../utils/format-handle"; 23 import { 24 atoms, 25 DropdownMenu, 26 DropdownMenuGroup, 27 DropdownMenuItem, 28 DropdownMenuTrigger, 29 layout, 30 ResponsiveDropdownMenuContent, 31 Text, 32 useToast, 33 View, 34 } from "../ui"; ··· 55 let [messageRemoved, setMessageRemoved] = useState(false); 56 let { createBlock, isLoading: isBlockLoading } = useCreateBlockRecord(); 57 let { createHideChat, isLoading: isHideLoading } = useCreateHideChatRecord(); 58 59 const setReportModalOpen = usePlayerStore((x) => x.setReportModalOpen); 60 const setReportSubject = usePlayerStore((x) => x.setReportSubject); ··· 85 } 86 }, [message]); 87 88 // Check if any moderation actions are actually available for this message 89 // This must match the individual action checks inside the DropdownMenuGroup 90 const hasAvailableActions = !!( ··· 125 createHideChat={createHideChat} 126 createBlock={createBlock} 127 toast={toast} 128 setReportModalOpen={setReportModalOpen} 129 setReportSubject={setReportSubject} 130 deleteChatMessage={deleteChatMessage} ··· 132 )} 133 </ResponsiveDropdownMenuContent> 134 </DropdownMenu> 135 </> 136 ); 137 }); ··· 149 createHideChat: (uri: string, streamerDID?: string) => Promise<any>; 150 createBlock: (did: string, streamerDID?: string) => Promise<any>; 151 toast: ReturnType<typeof useToast>; 152 setReportModalOpen: (open: boolean) => void; 153 setReportSubject: (subject: any) => void; 154 deleteChatMessage: (uri: string) => Promise<any>; ··· 167 createHideChat, 168 createBlock, 169 toast, 170 setReportModalOpen, 171 setReportSubject, 172 deleteChatMessage, ··· 260 </DropdownMenuGroup> 261 )} 262 263 <DropdownMenuGroup key="user-actions" title={`User actions`}> 264 <DropdownMenuItem 265 onPress={() => { ··· 270 > 271 <Text color="primary">View user on {BSKY_FRONTEND_DOMAIN}</Text> 272 </DropdownMenuItem> 273 + {agent?.did && message.author.did === agent.did && ( 274 <DeleteButton 275 message={message} 276 deleteChatMessage={deleteChatMessage} 277 onOpenChange={onOpenChange} 278 /> 279 )} 280 + {(!agent?.did || message.author.did !== agent.did) && ( 281 <ReportButton 282 message={message} 283 setReportModalOpen={setReportModalOpen} ··· 371 </DropdownMenuItem> 372 ); 373 }
+14 -5
js/components/src/components/chat/system-message.tsx
··· 1 import { View } from "react-native"; 2 - import { flex, gap, layout, ml, pb, pl, px, w } from "../../ui"; 3 - import { atoms } from "../ui"; 4 import { Code, Text } from "../ui/text"; 5 6 interface SystemMessageProps { 7 title: string; 8 timestamp: Date; 9 } 10 11 - export function SystemMessage({ title, timestamp }: SystemMessageProps) { 12 return ( 13 <View style={[w.percent[100], px[2], pb[2]]}> 14 <Code color="muted" tracking="widest" style={[pl[12], ml[1]]}> ··· 18 <Text 19 style={{ 20 fontVariant: ["tabular-nums"], 21 - color: atoms.colors.gray[300], 22 }} 23 > 24 {timestamp.toLocaleTimeString([], { ··· 28 })} 29 </Text> 30 <Text weight="bold" color="default" style={[flex.shrink[1]]}> 31 - {title} 32 </Text> 33 </View> 34 </View>
··· 1 import { View } from "react-native"; 2 + import { Main } from "streamplace/src/lexicons/types/place/stream/richtext/facet"; 3 + import { SystemMessageType } from "../../lib/system-messages"; 4 + import { colors, flex, gap, layout, ml, pb, pl, px, w } from "../../ui"; 5 import { Code, Text } from "../ui/text"; 6 + import { RichTextMessage } from "./chat-message"; 7 8 interface SystemMessageProps { 9 + variant: SystemMessageType; 10 title: string; 11 timestamp: Date; 12 + facets?: Main[]; 13 } 14 15 + export function SystemMessage({ 16 + variant, 17 + title, 18 + timestamp, 19 + facets, 20 + }: SystemMessageProps) { 21 return ( 22 <View style={[w.percent[100], px[2], pb[2]]}> 23 <Code color="muted" tracking="widest" style={[pl[12], ml[1]]}> ··· 27 <Text 28 style={{ 29 fontVariant: ["tabular-nums"], 30 + color: colors.gray[400], 31 }} 32 > 33 {timestamp.toLocaleTimeString([], { ··· 37 })} 38 </Text> 39 <Text weight="bold" color="default" style={[flex.shrink[1]]}> 40 + <RichTextMessage facets={facets} text={title} /> 41 </Text> 42 </View> 43 </View>
+169
js/components/src/components/chat/update-stream-title-dialog.tsx
···
··· 1 + import { useEffect, useState } from "react"; 2 + import { 3 + atoms, 4 + Button, 5 + DialogFooter, 6 + ResponsiveDialog, 7 + Text, 8 + Textarea, 9 + useToast, 10 + View, 11 + } from "../ui"; 12 + 13 + export interface UpdateStreamTitleDialogProps { 14 + livestream: any; 15 + streamerDID?: string; 16 + updateLivestream: ( 17 + livestreamUri: string, 18 + title: string, 19 + streamerDID?: string, 20 + ) => Promise<any>; 21 + isLoading: boolean; 22 + onClose: () => void; 23 + } 24 + 25 + export function UpdateStreamTitleDialog({ 26 + livestream, 27 + streamerDID, 28 + updateLivestream, 29 + isLoading, 30 + onClose, 31 + }: UpdateStreamTitleDialogProps) { 32 + const [title, setTitle] = useState(livestream?.record?.title || ""); 33 + const [error, setError] = useState<string | null>(null); 34 + const toast = useToast(); 35 + 36 + useEffect(() => { 37 + if (livestream?.record?.title) { 38 + setTitle(livestream.record.title); 39 + } 40 + }, [livestream?.record?.title]); 41 + 42 + const handleUpdate = async () => { 43 + setError(null); 44 + 45 + if (!title.trim()) { 46 + setError("Please enter a stream title"); 47 + return; 48 + } 49 + 50 + if (!livestream?.uri) { 51 + setError("No livestream found"); 52 + return; 53 + } 54 + 55 + try { 56 + await updateLivestream(livestream.uri, title.trim(), streamerDID); 57 + toast.show( 58 + "Stream title updated", 59 + "The stream title has been successfully updated.", 60 + { duration: 3 }, 61 + ); 62 + onClose(); 63 + } catch (err) { 64 + setError( 65 + err instanceof Error ? err.message : "Failed to update stream title", 66 + ); 67 + } 68 + }; 69 + 70 + return ( 71 + <ResponsiveDialog 72 + open={true} 73 + onOpenChange={(open) => { 74 + if (!open) { 75 + onClose(); 76 + setError(null); 77 + setTitle(livestream?.record?.title || ""); 78 + } 79 + }} 80 + title="Update Stream Title" 81 + description="Update the title of the livestream." 82 + size="md" 83 + dismissible={false} 84 + > 85 + <View style={[{ padding: 16, paddingBottom: 0 }]}> 86 + <View style={[{ marginBottom: 16 }]}> 87 + <Text 88 + style={[ 89 + { color: atoms.colors.gray[300], fontSize: 13, marginBottom: 8 }, 90 + ]} 91 + > 92 + Stream Title 93 + </Text> 94 + <Textarea 95 + value={title} 96 + onChangeText={(text) => { 97 + setTitle(text); 98 + setError(null); 99 + }} 100 + placeholder="Enter stream title..." 101 + maxLength={140} 102 + multiline 103 + style={[ 104 + { 105 + padding: 12, 106 + borderRadius: 8, 107 + backgroundColor: atoms.colors.neutral[800], 108 + color: atoms.colors.white, 109 + borderWidth: 1, 110 + borderColor: atoms.colors.neutral[600], 111 + minHeight: 100, 112 + fontSize: 16, 113 + }, 114 + ]} 115 + /> 116 + <Text 117 + style={[ 118 + { color: atoms.colors.gray[400], fontSize: 12, marginTop: 4 }, 119 + ]} 120 + > 121 + {title.length}/140 characters 122 + </Text> 123 + </View> 124 + 125 + {error && ( 126 + <View 127 + style={[ 128 + { 129 + backgroundColor: atoms.colors.red[900], 130 + padding: 12, 131 + borderRadius: 8, 132 + borderWidth: 1, 133 + borderColor: atoms.colors.red[700], 134 + marginBottom: 16, 135 + }, 136 + ]} 137 + > 138 + <Text style={[{ color: atoms.colors.red[400], fontSize: 13 }]}> 139 + {error} 140 + </Text> 141 + </View> 142 + )} 143 + </View> 144 + 145 + <DialogFooter> 146 + <Button 147 + width="min" 148 + variant="secondary" 149 + onPress={() => { 150 + onClose(); 151 + setError(null); 152 + setTitle(livestream?.record?.title || ""); 153 + }} 154 + disabled={isLoading} 155 + > 156 + <Text>Cancel</Text> 157 + </Button> 158 + <Button 159 + variant="primary" 160 + width="min" 161 + onPress={handleUpdate} 162 + disabled={isLoading || !title.trim()} 163 + > 164 + <Text>{isLoading ? "Updating..." : "Update Title"}</Text> 165 + </Button> 166 + </DialogFooter> 167 + </ResponsiveDialog> 168 + ); 169 + }
+37 -10
js/components/src/components/content-metadata/content-metadata-form.tsx
··· 1 import { forwardRef, useCallback, useEffect, useState } from "react"; 2 - import { ScrollView, View } from "react-native"; 3 import { 4 CONTENT_WARNINGS, 5 LICENSE_OPTIONS, 6 } from "../../lib/metadata-constants"; 7 8 import { 9 PlaceStreamMetadataConfiguration, 10 PlaceStreamMetadataContentRights, ··· 21 } from "../../streamplace-store/streamplace-store"; 22 import { usePDSAgent } from "../../streamplace-store/xrpc"; 23 import * as zero from "../../ui"; 24 import { Button } from "../ui/button"; 25 import { Checkbox } from "../ui/checkbox"; 26 import { Input } from "../ui/input"; ··· 41 style?: any; 42 } 43 44 - // ButtonSelector component (same as in livestream-panel) 45 const ButtonSelector = ({ 46 values, 47 selectedValue, ··· 55 disabledValues?: string[]; 56 style?: any[]; 57 }) => ( 58 - <View style={[layout.flex.row, gap.all[1], ...style]}> 59 {values.map(({ label, value }) => ( 60 <Button 61 key={value} 62 variant={selectedValue === value ? "primary" : "secondary"} 63 size="pill" 64 disabled={disabledValues.includes(value)} 65 onPress={() => setSelectedValue(value)} 66 style={[ ··· 71 ]} 72 > 73 <Text 74 - style={[ 75 - selectedValue === value ? text.white : text.gray[300], 76 - { fontSize: 14, fontWeight: "600" }, 77 - ]} 78 > 79 {label} 80 </Text> ··· 93 const getContentMetadata = useGetContentMetadata(); 94 const saveContentMetadata = useSaveContentMetadata(); 95 const toast = useToast(); 96 97 // Local state for metadata 98 const [contentWarnings, setContentWarnings] = useState<string[]>([]); ··· 364 ]} 365 selectedValue={activeSection} 366 setSelectedValue={setActiveSection} 367 - style={[{ marginVertical: -2, flexDirection: "column" }]} 368 /> 369 </View> 370 ··· 379 gap.all[2], 380 ]} 381 > 382 - <Text>Content Warnings</Text> 383 - <Text muted>(optional)</Text> 384 </View> 385 <View style={[gap.all[2], w.percent[100]]}> 386 {CONTENT_WARNINGS.map((warning) => ( ··· 398 </View> 399 ))} 400 </View> 401 </View> 402 )} 403
··· 1 import { forwardRef, useCallback, useEffect, useState } from "react"; 2 + import { Linking, Pressable, ScrollView, View } from "react-native"; 3 import { 4 CONTENT_WARNINGS, 5 LICENSE_OPTIONS, 6 } from "../../lib/metadata-constants"; 7 8 + import { ExternalLink } from "lucide-react-native"; 9 import { 10 PlaceStreamMetadataConfiguration, 11 PlaceStreamMetadataContentRights, ··· 22 } from "../../streamplace-store/streamplace-store"; 23 import { usePDSAgent } from "../../streamplace-store/xrpc"; 24 import * as zero from "../../ui"; 25 + import { Admonition } from "../ui"; 26 import { Button } from "../ui/button"; 27 import { Checkbox } from "../ui/checkbox"; 28 import { Input } from "../ui/input"; ··· 43 style?: any; 44 } 45 46 const ButtonSelector = ({ 47 values, 48 selectedValue, ··· 56 disabledValues?: string[]; 57 style?: any[]; 58 }) => ( 59 + <View style={[layout.flex.row, gap.all[1], layout.flex.wrap.wrap, ...style]}> 60 {values.map(({ label, value }) => ( 61 <Button 62 key={value} 63 variant={selectedValue === value ? "primary" : "secondary"} 64 size="pill" 65 + width="min" 66 disabled={disabledValues.includes(value)} 67 onPress={() => setSelectedValue(value)} 68 style={[ ··· 73 ]} 74 > 75 <Text 76 + size="sm" 77 + style={[selectedValue === value ? text.white : text.gray[300]]} 78 > 79 {label} 80 </Text> ··· 93 const getContentMetadata = useGetContentMetadata(); 94 const saveContentMetadata = useSaveContentMetadata(); 95 const toast = useToast(); 96 + const th = zero.useTheme(); 97 98 // Local state for metadata 99 const [contentWarnings, setContentWarnings] = useState<string[]>([]); ··· 365 ]} 366 selectedValue={activeSection} 367 setSelectedValue={setActiveSection} 368 + style={[{ marginVertical: -2 }]} 369 /> 370 </View> 371 ··· 380 gap.all[2], 381 ]} 382 > 383 + <Text size="lg">Content Warnings</Text> 384 </View> 385 <View style={[gap.all[2], w.percent[100]]}> 386 {CONTENT_WARNINGS.map((warning) => ( ··· 398 </View> 399 ))} 400 </View> 401 + <Admonition variant="info" size="sm"> 402 + <Text size="sm"> 403 + You are required to disclose if your content is not suitable 404 + for certain viewers. 405 + </Text> 406 + </Admonition> 407 + <Admonition variant="warning" size="sm"> 408 + <Text size="sm"> 409 + Your node may prohibit some of this content. Read the 410 + community guidelines to make sure.{" "} 411 + <Pressable 412 + onPress={() => 413 + Linking.openURL( 414 + "https://blog.stream.place/3mcqwibo4ks2w", 415 + ) 416 + } 417 + > 418 + <Text size="sm" color={zero.colors.blue[400]}> 419 + Learn more{" "} 420 + <ExternalLink 421 + size="14" 422 + style={{ marginVertical: -2 }} 423 + /> 424 + </Text> 425 + </Pressable> 426 + </Text> 427 + </Admonition> 428 </View> 429 )} 430
+1 -14
js/components/src/components/dashboard/header.tsx
··· 1 - import { AlertCircle, Car, Radio, Users } from "lucide-react-native"; 2 import { Pressable, Text, View } from "react-native"; 3 import * as zero from "../../ui"; 4 ··· 98 interface HeaderProps { 99 isLive: boolean; 100 streamTitle?: string; 101 - viewers?: number; 102 uptime?: string; 103 bitrate?: string; 104 timeBetweenSegments?: number; ··· 110 export default function Header({ 111 isLive, 112 streamTitle = "Live Stream", 113 - viewers = 0, 114 uptime = "00:00:00", 115 bitrate = "0 mbps", 116 timeBetweenSegments = 0, ··· 179 180 {/* Right side - Stream metrics */} 181 <View style={[layout.flex.row, layout.flex.alignCenter, gap.all[6]]}> 182 - {isLive && ( 183 - <> 184 - <MetricItem 185 - icon={Users} 186 - label="Viewers" 187 - value={viewers.toLocaleString()} 188 - /> 189 - <MetricItem icon={Car} label="Bitrate" value={bitrate} /> 190 - </> 191 - )} 192 - 193 {!isLive && ( 194 <View style={[layout.flex.row, layout.flex.alignCenter, gap.all[2]]}> 195 <Radio size={16} color="#6b7280" />
··· 1 + import { AlertCircle, Radio } from "lucide-react-native"; 2 import { Pressable, Text, View } from "react-native"; 3 import * as zero from "../../ui"; 4 ··· 98 interface HeaderProps { 99 isLive: boolean; 100 streamTitle?: string; 101 uptime?: string; 102 bitrate?: string; 103 timeBetweenSegments?: number; ··· 109 export default function Header({ 110 isLive, 111 streamTitle = "Live Stream", 112 uptime = "00:00:00", 113 bitrate = "0 mbps", 114 timeBetweenSegments = 0, ··· 177 178 {/* Right side - Stream metrics */} 179 <View style={[layout.flex.row, layout.flex.alignCenter, gap.all[6]]}> 180 {!isLive && ( 181 <View style={[layout.flex.row, layout.flex.alignCenter, gap.all[2]]}> 182 <Radio size={16} color="#6b7280" />
+2 -1
js/components/src/components/dashboard/information-widget.tsx
··· 12 import React, { useCallback, useEffect, useMemo, useState } from "react"; 13 import { LayoutChangeEvent, Text, TouchableOpacity, View } from "react-native"; 14 import Svg, { Path, Line as SvgLine, Text as SvgText } from "react-native-svg"; 15 import { 16 useLivestreamStore, 17 useSegment, ··· 38 const [bitrateHistory, setBitrateHistory] = useState<number[]>( 39 Array.from({ length: BITRATE_HISTORY_LENGTH }, () => 0), 40 ); 41 - const [showViewers, setShowViewers] = useState(false); 42 const [componentWidth, setComponentWidth] = useState<number>(220); 43 const [componentHeight, setComponentHeight] = useState<number>(400); 44 const [streamStartTime, setStreamStartTime] = useState<Date | null>(null);
··· 12 import React, { useCallback, useEffect, useMemo, useState } from "react"; 13 import { LayoutChangeEvent, Text, TouchableOpacity, View } from "react-native"; 14 import Svg, { Path, Line as SvgLine, Text as SvgText } from "react-native-svg"; 15 + import { useAQState } from "../../hooks"; 16 import { 17 useLivestreamStore, 18 useSegment, ··· 39 const [bitrateHistory, setBitrateHistory] = useState<number[]>( 40 Array.from({ length: BITRATE_HISTORY_LENGTH }, () => 0), 41 ); 42 + const [showViewers, setShowViewers] = useAQState("showViewers", true); 43 const [componentWidth, setComponentWidth] = useState<number>(220); 44 const [componentHeight, setComponentHeight] = useState<number>(400); 45 const [streamStartTime, setStreamStartTime] = useState<Date | null>(null);
+22 -13
js/components/src/components/mobile-player/player.tsx
··· 1 import { useEffect, useState } from "react"; 2 - import { Platform } from "react-native"; 3 import { flex, h, layout, w, zIndex } from "../../lib/theme/atoms"; 4 - import { useLivestreamStore } from "../../livestream-store"; 5 import { 6 PlayerStatus, 7 PlayerStatusTracker, 8 usePlayerStore, 9 } from "../../player-store"; 10 - import { useDID, useStreamplaceStore } from "../../streamplace-store"; 11 import { Text, View } from "../ui"; 12 import { Fullscreen } from "./fullscreen"; 13 import { PlayerProps } from "./props"; ··· 31 const setReportModalOpen = usePlayerStore((x) => x.setReportModalOpen); 32 const reportSubject = usePlayerStore((x) => x.reportSubject); 33 34 useEffect(() => { 35 setReportingURL(props.reportingURL ?? null); 36 }, [props.reportingURL]); ··· 92 export function usePlayerStatus(): [PlayerStatus] { 93 const playerStatus = usePlayerStore((x) => x.status); 94 const url = useStreamplaceStore((x) => x.url); 95 - const sessionId = useStreamplaceStore((x) => x.sessionId); 96 - const did = useDID(); 97 const playerEvent = usePlayerStore((x) => x.playerEvent); 98 - const streamerDid = useLivestreamStore((x) => x.profile?.did); 99 - const streamId = streamerDid; 100 const [whatDoing, setWhatDoing] = useState<PlayerStatus>(PlayerStatus.START); 101 const [whatDid, setWhatDid] = useState<PlayerStatusTracker>({}); 102 const [doingSince, setDoingSince] = useState(Date.now()); ··· 130 setDoingSince(now.getTime()); 131 playerEvent(url, now.toISOString(), "aq-played", { 132 whatHappened: fullWhatDid, 133 - sessionId, 134 - streamerDid, 135 - ...(did && { did }), 136 - ...(streamId && { streamId }), 137 - clientVersion: "0.9.0", 138 - platform: Platform.OS, 139 }); 140 }, [lastUpdated]); 141
··· 1 import { useEffect, useState } from "react"; 2 import { flex, h, layout, w, zIndex } from "../../lib/theme/atoms"; 3 import { 4 PlayerStatus, 5 PlayerStatusTracker, 6 usePlayerStore, 7 } from "../../player-store"; 8 + import { 9 + useMuted, 10 + useSetMuted, 11 + useStreamplaceStore, 12 + } from "../../streamplace-store"; 13 import { Text, View } from "../ui"; 14 import { Fullscreen } from "./fullscreen"; 15 import { PlayerProps } from "./props"; ··· 33 const setReportModalOpen = usePlayerStore((x) => x.setReportModalOpen); 34 const reportSubject = usePlayerStore((x) => x.reportSubject); 35 36 + const setMuted = useSetMuted(); 37 + const muted = useMuted(); 38 + 39 + // if we set muted, set it and restore after 40 + useEffect(() => { 41 + let wasMuted: null | boolean = null; 42 + setTimeout(() => { 43 + if (props.muted != undefined) { 44 + wasMuted = muted; 45 + setMuted(props.muted); 46 + } 47 + }, 200); 48 + return () => { 49 + wasMuted !== null && setMuted(wasMuted); 50 + }; 51 + }, [props.muted]); 52 + 53 useEffect(() => { 54 setReportingURL(props.reportingURL ?? null); 55 }, [props.reportingURL]); ··· 111 export function usePlayerStatus(): [PlayerStatus] { 112 const playerStatus = usePlayerStore((x) => x.status); 113 const url = useStreamplaceStore((x) => x.url); 114 const playerEvent = usePlayerStore((x) => x.playerEvent); 115 const [whatDoing, setWhatDoing] = useState<PlayerStatus>(PlayerStatus.START); 116 const [whatDid, setWhatDid] = useState<PlayerStatusTracker>({}); 117 const [doingSince, setDoingSince] = useState(Date.now()); ··· 145 setDoingSince(now.getTime()); 146 playerEvent(url, now.toISOString(), "aq-played", { 147 whatHappened: fullWhatDid, 148 }); 149 }, [lastUpdated]); 150
+2 -1
js/components/src/components/mobile-player/shared.tsx
··· 1 import { useMemo } from "react"; 2 - import { PlayerProtocol, useStreamplaceStore } from "../.."; 3 4 const protocolSuffixes = { 5 m3u8: PlayerProtocol.HLS,
··· 1 import { useMemo } from "react"; 2 + import { PlayerProtocol } from "../../player-store/player-state"; 3 + import { useStreamplaceStore } from "../../streamplace-store"; 4 5 const protocolSuffixes = { 6 m3u8: PlayerProtocol.HLS,
+42 -8
js/components/src/components/mobile-player/ui/input.tsx
··· 9 setTitle: (title: string) => void; 10 ingestStarting: boolean; 11 toggleGoLive: () => void; 12 }; 13 14 export function InputPanel({ ··· 16 setTitle, 17 ingestStarting, 18 toggleGoLive, 19 }: InputPanelProps) { 20 const { slideKeyboard } = useKeyboardSlide(); 21 return ( ··· 37 { padding: 10 }, 38 ]} 39 > 40 - <View backgroundColor="rgba(64,64,64,0.8)" borderRadius={12}> 41 - <Input 42 - value={title} 43 - onChange={setTitle} 44 - placeholder="Enter stream title" 45 - onEndEditing={Keyboard.dismiss} 46 - /> 47 - </View> 48 {ingestStarting ? ( 49 <Text>Starting your stream...</Text> 50 ) : ( 51 <View style={[layout.flex.center]}> 52 <Pressable
··· 9 setTitle: (title: string) => void; 10 ingestStarting: boolean; 11 toggleGoLive: () => void; 12 + isLive: boolean; 13 + toggleStopStream?: () => void; 14 }; 15 16 export function InputPanel({ ··· 18 setTitle, 19 ingestStarting, 20 toggleGoLive, 21 + isLive, 22 + toggleStopStream, 23 }: InputPanelProps) { 24 const { slideKeyboard } = useKeyboardSlide(); 25 return ( ··· 41 { padding: 10 }, 42 ]} 43 > 44 + {!isLive && ( 45 + <View backgroundColor="rgba(64,64,64,0.8)" borderRadius={12}> 46 + <Input 47 + value={title} 48 + onChange={setTitle} 49 + placeholder="Enter stream title" 50 + onEndEditing={Keyboard.dismiss} 51 + /> 52 + </View> 53 + )} 54 {ingestStarting ? ( 55 <Text>Starting your stream...</Text> 56 + ) : isLive ? ( 57 + <View style={[layout.flex.center]}> 58 + <Pressable 59 + onPress={toggleStopStream} 60 + style={[ 61 + px[4], 62 + py[2], 63 + layout.flex.row, 64 + layout.flex.center, 65 + gap.all[1], 66 + { 67 + backgroundColor: "rgba(64,64,64, 0.8)", 68 + borderRadius: 12, 69 + }, 70 + ]} 71 + > 72 + <View 73 + style={[ 74 + p[2], 75 + { 76 + backgroundColor: "rgba(256,0,0, 0.8)", 77 + borderRadius: 12, 78 + }, 79 + ]} 80 + /> 81 + <Text center>Stop Stream</Text> 82 + </Pressable> 83 + </View> 84 ) : ( 85 <View style={[layout.flex.center]}> 86 <Pressable
+2
js/components/src/components/mobile-player/ui/report-modal.tsx
··· 173 </View> 174 <DialogFooter> 175 <Button 176 variant="secondary" 177 onPress={handleCancel} 178 disabled={isSubmitting} ··· 180 <Text>Cancel</Text> 181 </Button> 182 <Button 183 variant="primary" 184 onPress={handleSubmit} 185 disabled={!selectedReason || isSubmitting}
··· 173 </View> 174 <DialogFooter> 175 <Button 176 + width="min" 177 variant="secondary" 178 onPress={handleCancel} 179 disabled={isSubmitting} ··· 181 <Text>Cancel</Text> 182 </Button> 183 <Button 184 + width="min" 185 variant="primary" 186 onPress={handleSubmit} 187 disabled={!selectedReason || isSubmitting}
+138 -2
js/components/src/components/mobile-player/ui/streamer-context-menu.tsx
··· 1 - export function StreamContextMenu() { 2 - return <></>; 3 }
··· 1 + import { ChevronRight, Cog } from "lucide-react-native"; 2 + import { useEffect, useState } from "react"; 3 + import Animated, { 4 + Easing, 5 + useAnimatedStyle, 6 + useSharedValue, 7 + withDelay, 8 + withSequence, 9 + withTiming, 10 + } from "react-native-reanimated"; 11 + import { useLivestreamInfo, zero } from "../../.."; 12 + import { usePlayerStore } from "../../../player-store"; 13 + import { 14 + DropdownMenu, 15 + DropdownMenuCheckboxItem, 16 + DropdownMenuGroup, 17 + DropdownMenuItem, 18 + DropdownMenuTrigger, 19 + ResponsiveDropdownMenuContent, 20 + Text, 21 + useTheme, 22 + } from "../../ui"; 23 + 24 + export function StreamContextMenu({ 25 + dropdownPortalContainer, 26 + }: { 27 + dropdownPortalContainer?: string; 28 + }) { 29 + const th = useTheme(); 30 + const debugInfo = usePlayerStore((x) => x.showDebugInfo); 31 + const setShowDebugInfo = usePlayerStore((x) => x.setShowDebugInfo); 32 + const { toggleStopStream } = useLivestreamInfo(); 33 + const ingest = usePlayerStore((x) => x.ingestConnectionState); 34 + const isLive = ingest !== null && ingest !== "new"; 35 + 36 + const [isOpen, setIsOpen] = useState(false); 37 + const [hasShownTooltip, setHasShownTooltip] = useState(false); 38 + 39 + const tooltipOpacity = useSharedValue(0); 40 + const tooltipTranslateX = useSharedValue(20); 41 + 42 + useEffect(() => { 43 + if (isLive && !hasShownTooltip) { 44 + tooltipOpacity.value = withDelay( 45 + 500, 46 + withSequence( 47 + withTiming(1, { duration: 300 }), 48 + withDelay(10000, withTiming(0, { duration: 300 })), 49 + ), 50 + ); 51 + tooltipTranslateX.value = withDelay( 52 + 500, 53 + withSequence( 54 + withTiming(0, { duration: 300 }), 55 + withDelay(10000, withTiming(20, { duration: 300 })), 56 + ), 57 + ); 58 + setHasShownTooltip(true); 59 + } 60 + }, [isLive, hasShownTooltip]); 61 + 62 + const iconRotate = useAnimatedStyle(() => { 63 + return { 64 + transform: [ 65 + { 66 + rotateZ: withTiming(isOpen ? "240deg" : "0deg", { 67 + duration: 650, 68 + easing: Easing.out(Easing.ease), 69 + }), 70 + }, 71 + ], 72 + }; 73 + }); 74 + 75 + const tooltipStyle = useAnimatedStyle(() => { 76 + return { 77 + opacity: tooltipOpacity.value, 78 + transform: [{ translateX: tooltipTranslateX.value }], 79 + }; 80 + }); 81 + 82 + return ( 83 + <DropdownMenu onOpenChange={setIsOpen} key={dropdownPortalContainer}> 84 + <DropdownMenuTrigger> 85 + <Animated.View style={[iconRotate]}> 86 + <Cog color={th.theme.colors.foreground} /> 87 + </Animated.View> 88 + <Animated.View 89 + style={[ 90 + tooltipStyle, 91 + { 92 + position: "absolute", 93 + right: 30, 94 + top: 0, 95 + backgroundColor: "rgba(64,64,64,0.95)", 96 + borderRadius: 8, 97 + paddingHorizontal: 8, 98 + paddingRight: 12, 99 + paddingVertical: 4, 100 + flexDirection: "row", 101 + alignItems: "center", 102 + gap: 6, 103 + zIndex: 9999999, 104 + pointerEvents: "box-none", 105 + width: 120, 106 + }, 107 + ]} 108 + > 109 + <Text size="sm" color="white"> 110 + End stream here 111 + </Text> 112 + <ChevronRight color="white" size={16} style={[zero.mr[4]]} /> 113 + </Animated.View> 114 + </DropdownMenuTrigger> 115 + <ResponsiveDropdownMenuContent side="top" align="end"> 116 + {isLive && ( 117 + <DropdownMenuGroup title="Stream"> 118 + <DropdownMenuItem 119 + closeOnPress={true} 120 + onPress={() => { 121 + toggleStopStream(); 122 + }} 123 + > 124 + <Text color="destructive">Stop Stream</Text> 125 + </DropdownMenuItem> 126 + </DropdownMenuGroup> 127 + )} 128 + <DropdownMenuGroup title="Advanced"> 129 + <DropdownMenuCheckboxItem 130 + checked={debugInfo} 131 + onCheckedChange={() => setShowDebugInfo(!debugInfo)} 132 + > 133 + <Text>Show Debug Info</Text> 134 + </DropdownMenuCheckboxItem> 135 + </DropdownMenuGroup> 136 + </ResponsiveDropdownMenuContent> 137 + </DropdownMenu> 138 + ); 139 }
-1
js/components/src/components/mobile-player/ui/viewer-loading-overlay.tsx
··· 52 position: "absolute", 53 width: "100%", 54 height: "100%", 55 - zIndex: 998, 56 alignItems: "center", 57 justifyContent: "center", 58 backgroundColor: "rgba(0,0,0,0.3)",
··· 52 position: "absolute", 53 width: "100%", 54 height: "100%", 55 alignItems: "center", 56 justifyContent: "center", 57 backgroundColor: "rgba(0,0,0,0.3)",
+7 -33
js/components/src/components/mobile-player/video.tsx
··· 1 import Hls from "hls.js"; 2 - import { 3 - createRef, 4 - forwardRef, 5 - useCallback, 6 - useEffect, 7 - useRef, 8 - useState, 9 - } from "react"; 10 - import { Platform } from "react-native"; 11 import { 12 IngestMediaSource, 13 PlayerProtocol, 14 PlayerStatus, 15 - useDID, 16 useEffectiveVolume, 17 - useLivestreamStore, 18 useMuted, 19 usePlayerStore, 20 useSetMuted, ··· 46 47 type VideoProps = { 48 url: string; 49 - videoRef?: React.RefObject<HTMLVideoElement | null>; 50 objectFit?: "contain" | "cover"; 51 pictureInPictureEnabled?: boolean; 52 }; 53 54 - function useVideoDimensions( 55 - videoRef: React.RefObject<HTMLVideoElement | null>, 56 - ) { 57 const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); 58 59 useEffect(() => { ··· 145 146 const VideoElement = forwardRef< 147 HTMLVideoElement, 148 - VideoProps & { videoRef?: React.RefObject<HTMLVideoElement | null> } 149 >((props, ref) => { 150 const x = usePlayerStore((x) => x); 151 const url = useStreamplaceStore((x) => x.url); 152 - const sessionId = useStreamplaceStore((x) => x.sessionId); 153 - const did = useDID(); 154 const playerEvent = usePlayerStore((x) => x.playerEvent); 155 const setMuteWasForced = usePlayerStore((x) => x.setMuteWasForced); 156 const ingest = usePlayerStore((x) => x.ingestConnectionState !== null); ··· 160 const setStatus = usePlayerStore((x) => x.setStatus); 161 const setUserInteraction = usePlayerStore((x) => x.setUserInteraction); 162 const setVideoRef = usePlayerStore((x) => x.setVideoRef); 163 - const streamerDid = useLivestreamStore((x) => x.profile?.did); 164 - // for e.g. 165 - const streamId = streamerDid; 166 167 const event = (evType) => (e) => { 168 console.log(evType); ··· 171 x.setStatus(evType); 172 } 173 console.log("Sending", evType, "status to", url); 174 - playerEvent(url, now.toISOString(), evType, { 175 - sessionId, 176 - streamerDid, 177 - ...(did && { did }), 178 - ...(streamId && { streamId }), 179 - clientVersion: "0.9.0", 180 - platform: Platform.OS, 181 - }); 182 }; 183 const [firstAttempt, setFirstAttempt] = useState(true); 184 const setAutoplayFailed = usePlayerStore((x) => x.setAutoplayFailed); ··· 383 } 384 385 export function WebRTCPlayer( 386 - props: VideoProps & { videoRef?: React.RefObject<HTMLVideoElement | null> }, 387 ) { 388 const [webrtcError, setWebrtcError] = useState<string | null>(null); 389 const setStatus = usePlayerStore((x) => x.setStatus); 390 const setProtocol = usePlayerStore((x) => x.setProtocol); 391 const diagnostics = useWebRTCDiagnostics(); 392 - // if videoref is undefined set it to a null ref 393 - if (props.videoRef === undefined) props.videoRef = createRef(); 394 // Check WebRTC compatibility on component mount 395 useEffect(() => { 396 try { ··· 458 width, 459 height, 460 }: { 461 - videoRef: React.RefObject<HTMLVideoElement | null>; 462 url: string; 463 width?: string | number; 464 height?: string | number;
··· 1 import Hls from "hls.js"; 2 + import { forwardRef, useCallback, useEffect, useRef, useState } from "react"; 3 import { 4 IngestMediaSource, 5 PlayerProtocol, 6 PlayerStatus, 7 useEffectiveVolume, 8 useMuted, 9 usePlayerStore, 10 useSetMuted, ··· 36 37 type VideoProps = { 38 url: string; 39 + videoRef?: React.RefObject<HTMLVideoElement>; 40 objectFit?: "contain" | "cover"; 41 pictureInPictureEnabled?: boolean; 42 }; 43 44 + function useVideoDimensions(videoRef: React.RefObject<HTMLVideoElement>) { 45 const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); 46 47 useEffect(() => { ··· 133 134 const VideoElement = forwardRef< 135 HTMLVideoElement, 136 + VideoProps & { videoRef?: React.RefObject<HTMLVideoElement> } 137 >((props, ref) => { 138 const x = usePlayerStore((x) => x); 139 const url = useStreamplaceStore((x) => x.url); 140 const playerEvent = usePlayerStore((x) => x.playerEvent); 141 const setMuteWasForced = usePlayerStore((x) => x.setMuteWasForced); 142 const ingest = usePlayerStore((x) => x.ingestConnectionState !== null); ··· 146 const setStatus = usePlayerStore((x) => x.setStatus); 147 const setUserInteraction = usePlayerStore((x) => x.setUserInteraction); 148 const setVideoRef = usePlayerStore((x) => x.setVideoRef); 149 150 const event = (evType) => (e) => { 151 console.log(evType); ··· 154 x.setStatus(evType); 155 } 156 console.log("Sending", evType, "status to", url); 157 + playerEvent(url, now.toISOString(), evType, {}); 158 }; 159 const [firstAttempt, setFirstAttempt] = useState(true); 160 const setAutoplayFailed = usePlayerStore((x) => x.setAutoplayFailed); ··· 359 } 360 361 export function WebRTCPlayer( 362 + props: VideoProps & { videoRef?: React.RefObject<HTMLVideoElement> }, 363 ) { 364 const [webrtcError, setWebrtcError] = useState<string | null>(null); 365 const setStatus = usePlayerStore((x) => x.setStatus); 366 const setProtocol = usePlayerStore((x) => x.setProtocol); 367 const diagnostics = useWebRTCDiagnostics(); 368 // Check WebRTC compatibility on component mount 369 useEffect(() => { 370 try { ··· 432 width, 433 height, 434 }: { 435 + videoRef?: React.RefObject<HTMLVideoElement>; 436 url: string; 437 width?: string | number; 438 height?: string | number;
+5
js/components/src/components/stream-notification/index.ts
···
··· 1 + export { StreamNotificationProvider } from "./stream-notification"; 2 + export { 3 + streamNotification, 4 + streamNotificationManager, 5 + } from "./stream-notification-manager";
+140
js/components/src/components/stream-notification/stream-notification-manager.ts
···
··· 1 + export type NotificationConfig = { 2 + id?: string; 3 + message?: string; 4 + render?: ( 5 + isExiting: boolean, 6 + onDismiss: (reason?: "user" | "auto") => void, 7 + startTime?: number, 8 + ) => React.ReactNode; 9 + duration?: number; // seconds, 0 = manual dismiss only 10 + actionLabel?: string; 11 + onAction?: () => void; 12 + onDismiss?: (reason?: "user" | "auto") => void; 13 + variant?: "default" | "info" | "warning"; 14 + }; 15 + 16 + export type StreamNotification = NotificationConfig & { 17 + id: string; 18 + visible: boolean; 19 + shouldDismiss?: boolean; 20 + dismissReason?: "user" | "auto"; 21 + startTime?: number; 22 + }; 23 + 24 + type Listener = (notifications: StreamNotification[]) => void; 25 + 26 + class StreamNotificationManager { 27 + private notifications: StreamNotification[] = []; 28 + private listeners: Set<Listener> = new Set(); 29 + private dismissTimers: Map<string, NodeJS.Timeout> = new Map(); 30 + 31 + show(config: NotificationConfig) { 32 + const notification: StreamNotification = { 33 + id: config.id || `notification-${Date.now()}`, 34 + message: config.message, 35 + render: config.render, 36 + duration: config.duration ?? 5, 37 + actionLabel: config.actionLabel, 38 + onAction: config.onAction, 39 + onDismiss: config.onDismiss, 40 + variant: config.variant ?? "default", 41 + visible: true, 42 + startTime: Date.now(), 43 + }; 44 + 45 + // if notification with same ID exists, dismiss it first 46 + const existingIndex = this.notifications.findIndex( 47 + (n) => n.id === notification.id, 48 + ); 49 + if (existingIndex !== -1) { 50 + const existingTimer = this.dismissTimers.get(notification.id); 51 + if (existingTimer) { 52 + clearTimeout(existingTimer); 53 + this.dismissTimers.delete(notification.id); 54 + } 55 + this.notifications = this.notifications.filter( 56 + (n) => n.id !== notification.id, 57 + ); 58 + } 59 + 60 + this.notifications = [...this.notifications, notification]; 61 + this.notifyListeners(); 62 + 63 + // auto-dismiss if duration > 0 64 + if (notification.duration && notification.duration > 0) { 65 + const timer = setTimeout(() => { 66 + this.requestDismiss(notification.id, "auto"); 67 + }, notification.duration * 1000); 68 + this.dismissTimers.set(notification.id, timer); 69 + } 70 + } 71 + 72 + requestDismiss(id: string, reason: "user" | "auto" = "user") { 73 + const notification = this.notifications.find((n) => n.id === id); 74 + if (!notification) { 75 + console.log("Notification not found!"); 76 + return; 77 + } 78 + 79 + // mark the notification for dismissal 80 + notification.shouldDismiss = true; 81 + notification.dismissReason = reason; 82 + this.notifyListeners(); 83 + // after 500ms, just hide it for real 84 + setTimeout(() => { 85 + this.hide(id, reason); 86 + }, 500); 87 + } 88 + 89 + hide(id: string, reason: "user" | "auto" = "user") { 90 + console.log("Hide called with id:", id, "reason:", reason); 91 + console.log( 92 + "Current notifications:", 93 + this.notifications.map((n) => n.id), 94 + ); 95 + const notification = this.notifications.find((n) => n.id === id); 96 + if (!notification) { 97 + console.log("Notification not found!"); 98 + return; 99 + } 100 + 101 + const timer = this.dismissTimers.get(id); 102 + if (timer) { 103 + clearTimeout(timer); 104 + this.dismissTimers.delete(id); 105 + } 106 + 107 + this.notifications = this.notifications.filter((n) => n.id !== id); 108 + console.log( 109 + "Remaining notifications:", 110 + this.notifications.map((n) => n.id), 111 + ); 112 + this.notifyListeners(); 113 + 114 + notification.onDismiss?.(reason); 115 + } 116 + 117 + getAll(): StreamNotification[] { 118 + return this.notifications; 119 + } 120 + 121 + subscribe(listener: Listener) { 122 + this.listeners.add(listener); 123 + return () => { 124 + this.listeners.delete(listener); 125 + }; 126 + } 127 + 128 + private notifyListeners() { 129 + this.listeners.forEach((listener) => { 130 + listener(this.notifications); 131 + }); 132 + } 133 + } 134 + 135 + export const streamNotificationManager = new StreamNotificationManager(); 136 + 137 + export const streamNotification = { 138 + show: (config: NotificationConfig) => streamNotificationManager.show(config), 139 + hide: (id: string) => streamNotificationManager.hide(id), 140 + };
+227
js/components/src/components/stream-notification/stream-notification.tsx
···
··· 1 + import { X } from "lucide-react-native"; 2 + import { useEffect, useState } from "react"; 3 + import { Pressable, StyleSheet, View } from "react-native"; 4 + import Animated, { 5 + Easing, 6 + useAnimatedStyle, 7 + useSharedValue, 8 + withTiming, 9 + } from "react-native-reanimated"; 10 + import { Text, useTheme } from "../../"; 11 + import { 12 + StreamNotification, 13 + streamNotificationManager, 14 + } from "./stream-notification-manager"; 15 + 16 + export function StreamNotificationProvider({ 17 + children = <></>, 18 + position = "top", 19 + }: { 20 + children?: React.ReactNode; 21 + position?: "top" | "bottom"; 22 + }) { 23 + const [notifications, setNotifications] = useState( 24 + streamNotificationManager.getAll(), 25 + ); 26 + 27 + useEffect(() => { 28 + return streamNotificationManager.subscribe(setNotifications); 29 + }, []); 30 + 31 + return ( 32 + <View style={styles.container}> 33 + {children} 34 + {notifications.map((notification, index) => ( 35 + <NotificationItem 36 + key={notification.id} 37 + notification={notification} 38 + index={index} 39 + position={position} 40 + /> 41 + ))} 42 + </View> 43 + ); 44 + } 45 + 46 + function NotificationItem({ 47 + notification, 48 + index, 49 + position, 50 + }: { 51 + notification: StreamNotification; 52 + index: number; 53 + position: "top" | "bottom"; 54 + }) { 55 + const { theme } = useTheme(); 56 + const translateY = useSharedValue(position === "top" ? -100 : 100); 57 + const opacity = useSharedValue(0); 58 + const [isExiting, setIsExiting] = useState(false); 59 + 60 + const NOTIFICATION_HEIGHT = 60; 61 + const NOTIFICATION_GAP = 8; 62 + const offset = 16 + index * (NOTIFICATION_HEIGHT + NOTIFICATION_GAP); 63 + 64 + useEffect(() => { 65 + translateY.value = withTiming(position === "top" ? offset : -offset, { 66 + duration: 300, 67 + easing: Easing.out(Easing.cubic), 68 + }); 69 + opacity.value = withTiming(1, { 70 + duration: 200, 71 + }); 72 + }, [offset, position]); 73 + 74 + useEffect(() => { 75 + if (notification.shouldDismiss && !isExiting) { 76 + setIsExiting(true); 77 + setTimeout(() => { 78 + streamNotificationManager.hide( 79 + notification.id, 80 + notification.dismissReason || "auto", 81 + ); 82 + }, 200); 83 + } 84 + }, [ 85 + notification.shouldDismiss, 86 + isExiting, 87 + notification.id, 88 + notification.dismissReason, 89 + ]); 90 + 91 + useEffect(() => { 92 + if (isExiting) { 93 + translateY.value = withTiming(position === "top" ? -100 : 100, { 94 + duration: 200, 95 + easing: Easing.in(Easing.cubic), 96 + }); 97 + opacity.value = withTiming(0, { 98 + duration: 200, 99 + }); 100 + } 101 + }, [isExiting, position]); 102 + 103 + const animatedStyle = useAnimatedStyle(() => ({ 104 + transform: [{ translateY: translateY.value }], 105 + opacity: opacity.value, 106 + })); 107 + 108 + const variantStyles = { 109 + default: { 110 + backgroundColor: theme.colors.card, 111 + borderColor: theme.colors.border, 112 + }, 113 + info: { 114 + backgroundColor: theme.colors.info, 115 + borderColor: theme.colors.info, 116 + }, 117 + warning: { 118 + backgroundColor: theme.colors.warning, 119 + borderColor: theme.colors.warning, 120 + }, 121 + }; 122 + 123 + const handleDismiss = (reason: "user" | "auto" = "user") => { 124 + console.log("Dismissing notification:", notification.id); 125 + setIsExiting(true); 126 + setTimeout(() => { 127 + console.log("Requesting dismiss for notification:", notification.id); 128 + streamNotificationManager.hide(notification.id, reason); 129 + }, 200); 130 + console.log(streamNotificationManager.getAll()); 131 + }; 132 + 133 + const handleAction = () => { 134 + notification.onAction?.(); 135 + streamNotificationManager.hide(notification.id, "user"); 136 + }; 137 + 138 + const positionStyle = position === "top" ? { top: 0 } : { bottom: 0 }; 139 + 140 + return ( 141 + <Animated.View 142 + style={[ 143 + styles.notification, 144 + positionStyle, 145 + notification.render 146 + ? {} 147 + : variantStyles[notification.variant || "default"], 148 + { margin: 0, padding: 0 }, 149 + animatedStyle, 150 + ]} 151 + > 152 + {notification.render ? ( 153 + notification.render(isExiting, handleDismiss, notification.startTime) 154 + ) : ( 155 + <View style={styles.content}> 156 + <Text style={[styles.message, { color: theme.colors.foreground }]}> 157 + {notification.message} 158 + </Text> 159 + 160 + <View style={styles.actions}> 161 + {notification.actionLabel && ( 162 + <Pressable onPress={handleAction}> 163 + <Text 164 + style={[styles.actionButton, { color: theme.colors.primary }]} 165 + > 166 + {notification.actionLabel} 167 + </Text> 168 + </Pressable> 169 + )} 170 + 171 + <Pressable 172 + onPress={() => handleDismiss("user")} 173 + style={styles.closeButton} 174 + > 175 + <X size={16} color={theme.colors.mutedForeground} /> 176 + </Pressable> 177 + </View> 178 + </View> 179 + )} 180 + </Animated.View> 181 + ); 182 + } 183 + 184 + const styles = StyleSheet.create({ 185 + container: { 186 + flex: 1, 187 + pointerEvents: "box-none", 188 + }, 189 + notification: { 190 + position: "absolute", 191 + top: 0, 192 + left: 16, 193 + right: 16, 194 + zIndex: 9999, 195 + borderRadius: 8, 196 + borderWidth: 1, 197 + padding: 12, 198 + shadowColor: "#000", 199 + shadowOffset: { width: 0, height: 2 }, 200 + shadowOpacity: 0.25, 201 + shadowRadius: 8, 202 + elevation: 5, 203 + }, 204 + content: { 205 + flexDirection: "row", 206 + alignItems: "center", 207 + justifyContent: "space-between", 208 + gap: 12, 209 + }, 210 + message: { 211 + flex: 1, 212 + fontSize: 14, 213 + fontWeight: "500", 214 + }, 215 + actions: { 216 + flexDirection: "row", 217 + alignItems: "center", 218 + gap: 12, 219 + }, 220 + actionButton: { 221 + fontSize: 14, 222 + fontWeight: "600", 223 + }, 224 + closeButton: { 225 + padding: 4, 226 + }, 227 + });
+187
js/components/src/components/stream-notification/teleport-notification.tsx
···
··· 1 + import { useEffect, useState } from "react"; 2 + import { useWindowDimensions, View } from "react-native"; 3 + import Animated, { 4 + Easing, 5 + useAnimatedStyle, 6 + useSharedValue, 7 + withRepeat, 8 + withTiming, 9 + } from "react-native-reanimated"; 10 + import { Button, Text, useTheme, zero } from "../../"; 11 + 12 + export function TeleportNotification({ 13 + targetHandle, 14 + countdown, 15 + canCancel, 16 + startTime, 17 + onDismiss, 18 + }: { 19 + targetHandle: string; 20 + countdown: number; 21 + canCancel: boolean; 22 + startTime?: number; 23 + onDismiss: (reason?: "user" | "auto") => void; 24 + }) { 25 + const { zero: z } = useTheme(); 26 + const w = useWindowDimensions().width; 27 + 28 + const [start, setStart] = useState(Date.now()); 29 + const [now, setNow] = useState(Date.now()); 30 + const [dismissed, setDismissed] = useState(false); 31 + 32 + useEffect(() => { 33 + const interval = setInterval(() => { 34 + setNow(Date.now()); 35 + }, 100); 36 + return () => clearInterval(interval); 37 + }, []); 38 + 39 + const timeLeft = Math.max(0, countdown - Math.floor((now - start) / 1000)); 40 + 41 + useEffect(() => { 42 + if (dismissed) { 43 + return; 44 + } 45 + if (timeLeft <= 0) { 46 + setDismissed(true); 47 + onDismiss("auto"); 48 + } 49 + }, [dismissed, onDismiss, timeLeft]); 50 + 51 + // if we're past 5 seconds from start, stripes should already be hidden 52 + const elapsedTime = startTime ? (Date.now() - startTime) / 1000 : 0; 53 + const [showStripes, setShowStripes] = useState(elapsedTime < 5); 54 + 55 + const stripeX = useSharedValue(0); 56 + const stripeOpacity = useSharedValue(1); 57 + const progressWidth = useSharedValue(100); 58 + 59 + useEffect(() => { 60 + // if stripes are already hidden, fade out asap and return 61 + if (!showStripes) { 62 + stripeOpacity.value = withTiming(0, { duration: 0 }); 63 + return; 64 + } 65 + // warning stripes animation 66 + stripeX.value = withRepeat( 67 + withTiming(30 * 2, { 68 + duration: 1000, 69 + easing: Easing.linear, 70 + }), 71 + 3, 72 + false, 73 + ); 74 + 75 + // hide stripes after 500ms 76 + const stripesTimer = setTimeout(() => { 77 + // woosh the stripes off to the right before hiding 78 + stripeX.value = withTiming(30 * 80, { 79 + duration: 1500, 80 + easing: Easing.cubic, 81 + }); 82 + // after animation, set stripes as hidden 83 + setTimeout(() => { 84 + setShowStripes(false); 85 + }, 350); 86 + }, 1500); 87 + 88 + return () => clearTimeout(stripesTimer); 89 + }, []); 90 + 91 + useEffect(() => { 92 + if (showStripes) return; 93 + 94 + // animate progress bar 95 + const percentage = (timeLeft / countdown) * 100; 96 + progressWidth.value = withTiming(percentage, { 97 + duration: 1000, 98 + easing: Easing.linear, 99 + }); 100 + }, [timeLeft, countdown, showStripes]); 101 + 102 + const stripesStyle = useAnimatedStyle(() => ({ 103 + opacity: stripeOpacity.value, 104 + transform: [{ translateX: stripeX.value }], 105 + })); 106 + 107 + const progressStyle = useAnimatedStyle(() => ({ 108 + width: `${progressWidth.value}%`, 109 + })); 110 + 111 + return ( 112 + <View style={[{ overflow: "hidden" }, zero.r.lg, zero.bg.neutral[900]]}> 113 + <View 114 + style={[ 115 + zero.layout.flex.row, 116 + zero.layout.flex.alignCenter, 117 + zero.layout.flex.spaceBetween, 118 + zero.px[3], 119 + w > 650 ? zero.py[4] : zero.py[2], 120 + ]} 121 + > 122 + <Text size={w > 650 ? "xl" : "base"}> 123 + Teleporting to @{targetHandle} 124 + </Text> 125 + <View 126 + style={[ 127 + zero.layout.flex.row, 128 + zero.layout.flex.alignCenter, 129 + zero.gap.all[3], 130 + ]} 131 + > 132 + <Text color="muted">{timeLeft}s</Text> 133 + {canCancel && ( 134 + <Button 135 + onPress={() => onDismiss("user")} 136 + width="min" 137 + variant="destructive" 138 + > 139 + Cancel 140 + </Button> 141 + )} 142 + </View> 143 + </View> 144 + <View 145 + style={{ 146 + height: 4, 147 + width: "100%", 148 + borderRadius: 2, 149 + overflow: "hidden", 150 + backgroundColor: "#0f0f1e", 151 + }} 152 + > 153 + <Animated.View 154 + style={[ 155 + { height: "100%", borderRadius: 2, backgroundColor: "#16f4d0" }, 156 + progressStyle, 157 + ]} 158 + /> 159 + </View> 160 + <Animated.View 161 + style={[ 162 + { 163 + position: "absolute", 164 + flexDirection: "row", 165 + height: 180, 166 + width: "200%", 167 + //clickthrough 168 + pointerEvents: "none", 169 + }, 170 + stripesStyle, 171 + ]} 172 + > 173 + {[...Array(80)].map((_, i) => ( 174 + <View 175 + key={i} 176 + style={{ 177 + width: 30, 178 + height: "100%", 179 + backgroundColor: i % 2 === 0 ? "#FFA500" : "#000000", 180 + transform: [{ skewX: "-45deg" }, { translateX: -30 * 8 }], 181 + }} 182 + /> 183 + ))} 184 + </Animated.View> 185 + </View> 186 + ); 187 + }
+177
js/components/src/components/ui/admonition.tsx
···
··· 1 + import { AlertCircle, CheckCircle, Info, XCircle } from "lucide-react-native"; 2 + import { View, ViewStyle } from "react-native"; 3 + import { useTheme } from "../../ui"; 4 + import { Text } from "./text"; 5 + 6 + type AdmonitionVariant = "default" | "success" | "error" | "info" | "warning"; 7 + type AdmonitionSize = "sm" | "md" | "lg"; 8 + 9 + type AdmonitionProps = { 10 + variant?: AdmonitionVariant; 11 + size?: AdmonitionSize; 12 + title?: string; 13 + children?: React.ReactNode; 14 + iconLeft?: React.ComponentType<any>; 15 + style?: ViewStyle; 16 + }; 17 + 18 + export function Admonition({ 19 + variant = "default", 20 + size = "md", 21 + title, 22 + children, 23 + iconLeft, 24 + style, 25 + }: AdmonitionProps) { 26 + const { theme, icons } = useTheme(); 27 + 28 + const defaultIconLeft = (() => { 29 + if (iconLeft) return iconLeft; 30 + switch (variant) { 31 + case "success": 32 + return CheckCircle; 33 + case "error": 34 + return XCircle; 35 + case "info": 36 + return Info; 37 + case "warning": 38 + return AlertCircle; 39 + default: 40 + return Info; 41 + } 42 + })(); 43 + 44 + const FinalIconLeft = defaultIconLeft; 45 + 46 + const variantStyles: Record<AdmonitionVariant, ViewStyle> = { 47 + default: { 48 + backgroundColor: theme.colors.secondary, 49 + borderColor: theme.colors.border, 50 + }, 51 + success: { 52 + backgroundColor: theme.colors.success + "15", 53 + borderColor: theme.colors.success, 54 + }, 55 + error: { 56 + backgroundColor: theme.colors.destructive + "15", 57 + borderColor: theme.colors.destructive, 58 + }, 59 + info: { 60 + backgroundColor: theme.colors.info + "15", 61 + borderColor: theme.colors.info, 62 + }, 63 + warning: { 64 + backgroundColor: theme.colors.warning + "15", 65 + borderColor: theme.colors.warning, 66 + }, 67 + }; 68 + 69 + const iconColor = (() => { 70 + switch (variant) { 71 + case "success": 72 + return theme.colors.success; 73 + case "error": 74 + return theme.colors.destructive; 75 + case "info": 76 + return theme.colors.info; 77 + case "warning": 78 + return theme.colors.warning; 79 + default: 80 + return theme.colors.foreground; 81 + } 82 + })(); 83 + 84 + const sizeConfig = (() => { 85 + switch (size) { 86 + case "sm": 87 + return { 88 + borderRadius: 8, 89 + padding: 12, 90 + gap: 6, 91 + iconSize: icons.size.md, 92 + titleSize: "base" as const, 93 + contentSize: "sm" as const, 94 + innerGap: 8, 95 + }; 96 + case "lg": 97 + return { 98 + borderRadius: 16, 99 + padding: 20, 100 + gap: 12, 101 + iconSize: icons.size.xl, 102 + titleSize: "xl" as const, 103 + contentSize: "lg" as const, 104 + innerGap: 16, 105 + }; 106 + case "md": 107 + default: 108 + return { 109 + borderRadius: 12, 110 + padding: 16, 111 + gap: 8, 112 + iconSize: icons.size.lg, 113 + titleSize: "lg" as const, 114 + contentSize: "base" as const, 115 + innerGap: 12, 116 + }; 117 + } 118 + })(); 119 + 120 + let childrenIn = ( 121 + <View 122 + style={{ 123 + paddingLeft: title ? sizeConfig.iconSize + sizeConfig.innerGap : 0, 124 + }} 125 + > 126 + {typeof children === "string" ? ( 127 + <Text 128 + size={sizeConfig.contentSize} 129 + style={{ color: theme.colors.cardForeground, flexWrap: "wrap" }} 130 + > 131 + {children} 132 + </Text> 133 + ) : ( 134 + children 135 + )} 136 + </View> 137 + ); 138 + 139 + return ( 140 + <View 141 + style={[ 142 + { 143 + borderRadius: sizeConfig.borderRadius, 144 + borderWidth: 1, 145 + padding: sizeConfig.padding, 146 + gap: sizeConfig.gap, 147 + }, 148 + variantStyles[variant], 149 + style, 150 + ]} 151 + > 152 + <View 153 + style={{ 154 + flexDirection: "row", 155 + alignItems: "flex-start", 156 + gap: sizeConfig.innerGap, 157 + }} 158 + > 159 + {FinalIconLeft && ( 160 + <FinalIconLeft size={sizeConfig.iconSize} color={iconColor} /> 161 + )} 162 + {title ? ( 163 + <Text 164 + size={sizeConfig.titleSize} 165 + weight="semibold" 166 + style={{ flex: 1 }} 167 + > 168 + {title} 169 + </Text> 170 + ) : ( 171 + children && <View style={{ flex: 1 }}>{childrenIn}</View> 172 + )} 173 + </View> 174 + {children && title && childrenIn} 175 + </View> 176 + ); 177 + }
+3
js/components/src/components/ui/button.tsx
··· 41 loading?: boolean; 42 loadingText?: string; 43 width?: "full" | "min" | number; 44 } 45 46 export const Button = forwardRef<any, ButtonProps>( ··· 56 disabled, 57 style, 58 width = "full", 59 ...props 60 }, 61 ref, ··· 222 ref={ref} 223 disabled={disabled || loading} 224 style={[buttonStyle, sizeStyles.button, widthStyle, style]} 225 {...props} 226 > 227 <ButtonPrimitive.Content style={sizeStyles.inner}>
··· 41 loading?: boolean; 42 loadingText?: string; 43 width?: "full" | "min" | number; 44 + hoverStyle?: ButtonPrimitiveProps["hoverStyle"]; 45 } 46 47 export const Button = forwardRef<any, ButtonProps>( ··· 57 disabled, 58 style, 59 width = "full", 60 + hoverStyle, 61 ...props 62 }, 63 ref, ··· 224 ref={ref} 225 disabled={disabled || loading} 226 style={[buttonStyle, sizeStyles.button, widthStyle, style]} 227 + hoverStyle={hoverStyle} 228 {...props} 229 > 230 <ButtonPrimitive.Content style={sizeStyles.inner}>
+1
js/components/src/components/ui/index.ts
··· 5 export * from "./primitives/text"; 6 7 // Export styled components 8 export * from "./button"; 9 export * from "./checkbox"; 10 export * from "./dialog";
··· 5 export * from "./primitives/text"; 6 7 // Export styled components 8 + export * from "./admonition"; 9 export * from "./button"; 10 export * from "./checkbox"; 11 export * from "./dialog";
+62 -56
js/components/src/components/ui/menu.tsx
··· 1 - import { forwardRef, ReactNode } from "react"; 2 import { Animated, Platform, View, ViewStyle } from "react-native"; 3 import { Gesture, GestureDetector } from "react-native-gesture-handler"; 4 import { ··· 279 }, 280 ); 281 282 - // export interface MenuDraggableGroupProps { 283 - // children: ReactNode; 284 - // onMove: (fromIndex: number, toIndex: number) => void; 285 - // onDragEnd: (fromIndex: number, toIndex: number) => void; 286 - // dragHandle?: ReactNode; 287 - // style?: ViewStyle; 288 - // } 289 290 - // export const MenuDraggableGroup = forwardRef<View, MenuDraggableGroupProps>( 291 - // ({ children, onMove, onDragEnd, dragHandle, style }, ref) => { 292 - // const { theme } = useTheme(); 293 294 - // const childrenArray = Children.toArray(children); 295 - // const draggableItems = childrenArray.filter( 296 - // (child) => 297 - // isValidElement(child) && 298 - // (child.type === MenuItem || child.type === MenuSeparator), 299 - // ); 300 301 - // let itemIndex = 0; 302 - // const enhancedChildren = Children.map(children, (child) => { 303 - // if (isValidElement(child)) { 304 - // if (child.type === MenuItem) { 305 - // const currentIndex = itemIndex; 306 - // itemIndex++; 307 308 - // return cloneElement(child, { 309 - // draggable: true, 310 - // dragHandle: dragHandle || child.props.dragHandle, 311 - // _dragIndex: currentIndex, 312 - // _dragTotalItems: draggableItems.filter( 313 - // (c) => isValidElement(c) && c.type === MenuItem, 314 - // ).length, 315 - // _onDragMove: onMove, 316 - // _onDragEnd: onDragEnd, 317 - // } as any); 318 - // } 319 - // if (child.type === MenuSeparator) { 320 - // return child; 321 - // } 322 - // } 323 - // return child; 324 - // }); 325 326 - // return ( 327 - // <View 328 - // ref={ref} 329 - // style={[ 330 - // { backgroundColor: theme.colors.muted + "c0" }, 331 - // Platform.OS === "web" ? [px[1], py[1]] : p[1], 332 - // gap.all[1], 333 - // { borderRadius: borderRadius.lg }, 334 - // style, 335 - // ]} 336 - // > 337 - // {enhancedChildren} 338 - // </View> 339 - // ); 340 - // }, 341 - // );
··· 1 + import { 2 + Children, 3 + cloneElement, 4 + forwardRef, 5 + isValidElement, 6 + ReactNode, 7 + } from "react"; 8 import { Animated, Platform, View, ViewStyle } from "react-native"; 9 import { Gesture, GestureDetector } from "react-native-gesture-handler"; 10 import { ··· 285 }, 286 ); 287 288 + export interface MenuDraggableGroupProps { 289 + children: ReactNode; 290 + onMove: (fromIndex: number, toIndex: number) => void; 291 + onDragEnd: (fromIndex: number, toIndex: number) => void; 292 + dragHandle?: ReactNode; 293 + style?: ViewStyle; 294 + } 295 296 + export const MenuDraggableGroup = forwardRef<View, MenuDraggableGroupProps>( 297 + ({ children, onMove, onDragEnd, dragHandle, style }, ref) => { 298 + const { theme } = useTheme(); 299 300 + const childrenArray = Children.toArray(children); 301 + const draggableItems = childrenArray.filter( 302 + (child) => 303 + isValidElement(child) && 304 + (child.type === MenuItem || child.type === MenuSeparator), 305 + ); 306 307 + let itemIndex = 0; 308 + const enhancedChildren = Children.map(children, (child) => { 309 + if (isValidElement(child)) { 310 + if (child.type === MenuItem) { 311 + const currentIndex = itemIndex; 312 + itemIndex++; 313 314 + return cloneElement(child, { 315 + draggable: true, 316 + dragHandle: dragHandle || child.props.dragHandle, 317 + _dragIndex: currentIndex, 318 + _dragTotalItems: draggableItems.filter( 319 + (c) => isValidElement(c) && c.type === MenuItem, 320 + ).length, 321 + _onDragMove: onMove, 322 + _onDragEnd: onDragEnd, 323 + } as any); 324 + } 325 + if (child.type === MenuSeparator) { 326 + return child; 327 + } 328 + } 329 + return child; 330 + }); 331 332 + return ( 333 + <View 334 + ref={ref} 335 + style={[ 336 + { backgroundColor: theme.colors.muted + "c0" }, 337 + Platform.OS === "web" ? [px[1], py[1]] : p[1], 338 + gap.all[1], 339 + { borderRadius: borderRadius.lg }, 340 + style, 341 + ]} 342 + > 343 + {enhancedChildren} 344 + </View> 345 + ); 346 + }, 347 + );
+37 -11
js/components/src/components/ui/primitives/button.tsx
··· 1 - import React, { forwardRef } from "react"; 2 import { 3 AccessibilityRole, 4 GestureResponderEvent, 5 StyleSheet, 6 Text, 7 TextProps, 8 - TouchableOpacity, 9 - TouchableOpacityProps, 10 View, 11 ViewProps, 12 } from "react-native"; 13 14 // Base button primitive interface 15 - export interface ButtonPrimitiveProps 16 - extends Omit<TouchableOpacityProps, "onPress"> { 17 onPress?: (event: GestureResponderEvent) => void; 18 disabled?: boolean; 19 loading?: boolean; ··· 21 accessibilityLabel?: string; 22 accessibilityHint?: string; 23 testID?: string; 24 } 25 26 // Button root primitive - handles all touch interactions 27 export const ButtonRoot = forwardRef< 28 - React.ComponentRef<typeof TouchableOpacity>, 29 ButtonPrimitiveProps 30 >( 31 ( ··· 43 accessibilityState, 44 testID, 45 style, 46 - activeOpacity = 0.7, 47 ...props 48 }, 49 ref, 50 ) => { 51 const handlePress = React.useCallback( 52 (event: GestureResponderEvent) => { 53 if (!disabled && !loading && onPress) { ··· 84 [disabled, loading, onLongPress], 85 ); 86 87 return ( 88 - <TouchableOpacity 89 ref={ref} 90 onPress={handlePress} 91 onPressIn={handlePressIn} 92 onPressOut={handlePressOut} 93 onLongPress={handleLongPress} 94 disabled={disabled || loading} 95 - activeOpacity={disabled || loading ? 1 : activeOpacity} 96 accessibilityRole={accessibilityRole} 97 accessibilityLabel={accessibilityLabel} 98 accessibilityHint={accessibilityHint} ··· 104 testID={testID} 105 style={[ 106 primitiveStyles.button, 107 (disabled || loading) && primitiveStyles.disabled, 108 - style, 109 ]} 110 {...props} 111 > 112 {children} 113 - </TouchableOpacity> 114 ); 115 }, 116 ); ··· 245 alignItems: "center", 246 justifyContent: "center", 247 }, 248 disabled: { 249 opacity: 0.5, 250 },
··· 1 + import React, { forwardRef, useState } from "react"; 2 import { 3 AccessibilityRole, 4 GestureResponderEvent, 5 + Platform, 6 + Pressable, 7 + PressableProps, 8 + StyleProp, 9 StyleSheet, 10 Text, 11 TextProps, 12 View, 13 ViewProps, 14 + ViewStyle, 15 } from "react-native"; 16 17 // Base button primitive interface 18 + export interface ButtonPrimitiveProps extends Omit<PressableProps, "onPress"> { 19 onPress?: (event: GestureResponderEvent) => void; 20 disabled?: boolean; 21 loading?: boolean; ··· 23 accessibilityLabel?: string; 24 accessibilityHint?: string; 25 testID?: string; 26 + hoverStyle?: StyleProp<ViewStyle>; 27 } 28 29 // Button root primitive - handles all touch interactions 30 export const ButtonRoot = forwardRef< 31 + React.ComponentRef<typeof Pressable>, 32 ButtonPrimitiveProps 33 >( 34 ( ··· 46 accessibilityState, 47 testID, 48 style, 49 + hoverStyle, 50 ...props 51 }, 52 ref, 53 ) => { 54 + const [isHovered, setIsHovered] = useState(false); 55 + 56 const handlePress = React.useCallback( 57 (event: GestureResponderEvent) => { 58 if (!disabled && !loading && onPress) { ··· 89 [disabled, loading, onLongPress], 90 ); 91 92 + const handleHoverIn = React.useCallback(() => { 93 + if (!disabled && !loading) { 94 + setIsHovered(true); 95 + } 96 + }, [disabled, loading]); 97 + 98 + const handleHoverOut = React.useCallback(() => { 99 + setIsHovered(false); 100 + }, []); 101 + 102 return ( 103 + <Pressable 104 ref={ref} 105 onPress={handlePress} 106 onPressIn={handlePressIn} 107 onPressOut={handlePressOut} 108 onLongPress={handleLongPress} 109 + onHoverIn={handleHoverIn} 110 + onHoverOut={handleHoverOut} 111 disabled={disabled || loading} 112 accessibilityRole={accessibilityRole} 113 accessibilityLabel={accessibilityLabel} 114 accessibilityHint={accessibilityHint} ··· 120 testID={testID} 121 style={[ 122 primitiveStyles.button, 123 + primitiveStyles.transition, 124 (disabled || loading) && primitiveStyles.disabled, 125 + style as any, 126 + isHovered && hoverStyle, 127 ]} 128 {...props} 129 > 130 {children} 131 + </Pressable> 132 ); 133 }, 134 ); ··· 263 alignItems: "center", 264 justifyContent: "center", 265 }, 266 + transition: 267 + Platform.OS === "web" 268 + ? // probably fine if web-only 269 + ({ 270 + transitionDuration: "150ms", 271 + transitionProperty: "background-color, border-color, color", 272 + } as any) 273 + : undefined, 274 disabled: { 275 opacity: 0.5, 276 },
+90 -35
js/components/src/components/ui/resizeable.tsx
··· 1 import { ChevronUp } from "lucide-react-native"; 2 - import { ComponentProps, useEffect } from "react"; 3 import { Dimensions } from "react-native"; 4 import { 5 Gesture, ··· 9 import Animated, { 10 Extrapolation, 11 interpolate, 12 useAnimatedStyle, 13 useSharedValue, 14 withSpring, ··· 27 isPlayerRatioGreater: boolean; 28 style?: ComponentProps<typeof AnimatedView>["style"]; 29 children?: React.ReactNode; 30 }; 31 32 const SPRING_CONFIG = { damping: 20, stiffness: 100 }; ··· 36 isPlayerRatioGreater, 37 style = {}, 38 children, 39 }: ResizableChatSheetProps) { 40 const { slideKeyboard } = useKeyboardSlide(); 41 const { bottom: safeBottom } = useSafeAreaInsets(); ··· 45 46 const sheetHeight = useSharedValue(MIN_HEIGHT); 47 const startHeight = useSharedValue(MIN_HEIGHT); 48 49 useEffect(() => { 50 setTimeout(() => { 51 - sheetHeight.value = withSpring( 52 - startingPercentage ? startingPercentage * SCREEN_HEIGHT : MIN_HEIGHT, 53 - SPRING_CONFIG, 54 - ); 55 }, 1000); 56 }, []); 57 ··· 65 if (newHeight < MIN_HEIGHT) newHeight = MIN_HEIGHT; 66 sheetHeight.value = newHeight; 67 68 - if (newHeight < COLLAPSE_HEIGHT) { 69 sheetHeight.value = withSpring(MIN_HEIGHT, SPRING_CONFIG); 70 } 71 }); 72 ··· 83 translateY: 84 slideKeyboard + 85 Math.max(0, -sheetHeight.value) + 86 - (slideKeyboard < 0 ? 0 : -safeBottom), 87 }, 88 ], 89 })); ··· 97 ], 98 })); 99 100 return ( 101 <> 102 <Animated.View ··· 111 > 112 <Pressable 113 onPress={() => { 114 - sheetHeight.value = 115 - sheetHeight.value === MIN_HEIGHT 116 - ? withSpring(MAX_HEIGHT, SPRING_CONFIG) 117 - : withSpring(MIN_HEIGHT, SPRING_CONFIG); 118 }} 119 > 120 <View ··· 155 ]} 156 > 157 <View style={[layout.flex.row, layout.flex.justifyCenter, h[2]]}> 158 - <GestureDetector gesture={panGesture}> 159 - <View 160 - // Make the touch area much larger, but keep the visible handle small 161 - style={{ 162 - height: 30, // Large touch area 163 - width: 120, // Wide enough for thumbs 164 - alignItems: "center", 165 - justifyContent: "center", 166 - //backgroundColor: "rgba(0,255,255,0.1)", 167 - transform: [{ translateY: -30 }], 168 - }} 169 - > 170 <View 171 - style={[ 172 - w[32], 173 - { 174 - height: 6, 175 - backgroundColor: "#eeeeee66", 176 - borderRadius: 999, 177 178 - transform: [{ translateY: 5 }], 179 - }, 180 - ]} 181 - /> 182 - </View> 183 - </GestureDetector> 184 </View> 185 186 {children} 187 </AnimatedView> 188 </> 189 ); 190 }
··· 1 import { ChevronUp } from "lucide-react-native"; 2 + import { ComponentProps, useEffect, useState } from "react"; 3 import { Dimensions } from "react-native"; 4 import { 5 Gesture, ··· 9 import Animated, { 10 Extrapolation, 11 interpolate, 12 + runOnJS, 13 useAnimatedStyle, 14 useSharedValue, 15 withSpring, ··· 28 isPlayerRatioGreater: boolean; 29 style?: ComponentProps<typeof AnimatedView>["style"]; 30 children?: React.ReactNode; 31 + renderAbove?: (isCollapsed: boolean) => React.ReactNode; 32 }; 33 34 const SPRING_CONFIG = { damping: 20, stiffness: 100 }; ··· 38 isPlayerRatioGreater, 39 style = {}, 40 children, 41 + renderAbove, 42 }: ResizableChatSheetProps) { 43 const { slideKeyboard } = useKeyboardSlide(); 44 const { bottom: safeBottom } = useSafeAreaInsets(); ··· 48 49 const sheetHeight = useSharedValue(MIN_HEIGHT); 50 const startHeight = useSharedValue(MIN_HEIGHT); 51 + const [isCollapsed, setIsCollapsed] = useState(true); 52 + const wasCollapsed = useSharedValue(true); 53 54 useEffect(() => { 55 setTimeout(() => { 56 + const targetHeight = startingPercentage 57 + ? startingPercentage * SCREEN_HEIGHT 58 + : MIN_HEIGHT; 59 + sheetHeight.value = withSpring(targetHeight, SPRING_CONFIG); 60 + setIsCollapsed(targetHeight < COLLAPSE_HEIGHT); 61 }, 1000); 62 }, []); 63 ··· 71 if (newHeight < MIN_HEIGHT) newHeight = MIN_HEIGHT; 72 sheetHeight.value = newHeight; 73 74 + const nowCollapsed = newHeight < COLLAPSE_HEIGHT; 75 + if (nowCollapsed && !wasCollapsed.value) { 76 sheetHeight.value = withSpring(MIN_HEIGHT, SPRING_CONFIG); 77 + wasCollapsed.value = true; 78 + runOnJS(setIsCollapsed)(true); 79 + } else if (!nowCollapsed && wasCollapsed.value) { 80 + wasCollapsed.value = false; 81 + runOnJS(setIsCollapsed)(false); 82 } 83 }); 84 ··· 95 translateY: 96 slideKeyboard + 97 Math.max(0, -sheetHeight.value) + 98 + (slideKeyboard < 0 ? 0 : -safeBottom) - 99 + (Math.abs(slideKeyboard) > 1 ? 32 : 16), 100 }, 101 ], 102 })); ··· 110 ], 111 })); 112 113 + const aboveElementStyle = useAnimatedStyle(() => ({ 114 + // show inside area when not collapsed, and show outside area when collapsed 115 + height: sheetHeight.value < COLLAPSE_HEIGHT ? 0 : sheetHeight.value, 116 + transform: [ 117 + { 118 + translateY: 119 + sheetHeight.value < COLLAPSE_HEIGHT 120 + ? withSpring(-120) 121 + : withSpring(20), 122 + }, 123 + ], 124 + })); 125 + 126 return ( 127 <> 128 <Animated.View ··· 137 > 138 <Pressable 139 onPress={() => { 140 + const isCurrentlyCollapsed = sheetHeight.value === MIN_HEIGHT; 141 + sheetHeight.value = isCurrentlyCollapsed 142 + ? withSpring(MAX_HEIGHT, SPRING_CONFIG) 143 + : withSpring(MIN_HEIGHT, SPRING_CONFIG); 144 + setIsCollapsed(!isCurrentlyCollapsed); 145 }} 146 > 147 <View ··· 182 ]} 183 > 184 <View style={[layout.flex.row, layout.flex.justifyCenter, h[2]]}> 185 + <View style={{ alignItems: "center", width: "100%" }}> 186 + <GestureDetector gesture={panGesture}> 187 <View 188 + // Make the touch area much larger, but keep the visible handle small 189 + style={{ 190 + height: 30, // Large touch area 191 + width: 120, // Wide enough for thumbs 192 + alignItems: "center", 193 + justifyContent: "center", 194 + //backgroundColor: "rgba(0,255,255,0.1)", 195 + transform: [{ translateY: -30 }], 196 + }} 197 + > 198 + <View 199 + style={[ 200 + w[32], 201 + { 202 + height: 6, 203 + backgroundColor: "#eeeeee66", 204 + borderRadius: 999, 205 206 + transform: [{ translateY: 5 }], 207 + }, 208 + ]} 209 + /> 210 + </View> 211 + </GestureDetector> 212 + </View> 213 </View> 214 215 {children} 216 </AnimatedView> 217 + <Animated.View 218 + style={[ 219 + aboveElementStyle, 220 + { 221 + width: "100%", 222 + pointerEvents: "none", 223 + position: "absolute", 224 + bottom: 0, 225 + }, 226 + ]} 227 + > 228 + <View 229 + style={{ 230 + pointerEvents: "auto", 231 + width: "100%", 232 + // hate doing it this way, but can't figure out 233 + // how to make it size to content otherwise 234 + minHeight: 50, 235 + height: "100%", 236 + maxHeight: 75, 237 + flex: 0, 238 + }} 239 + > 240 + {renderAbove?.(isCollapsed)} 241 + </View> 242 + </Animated.View> 243 </> 244 ); 245 }
+11 -1
js/components/src/components/ui/text.tsx
··· 62 63 export interface TextProps 64 extends Omit<TextPrimitiveProps, "variant" | "size" | "weight" | "color">, 65 - VariantProps<typeof textVariants> { 66 // Additional convenience props 67 muted?: boolean; 68 bold?: boolean;
··· 62 63 export interface TextProps 64 extends Omit<TextPrimitiveProps, "variant" | "size" | "weight" | "color">, 65 + Omit<VariantProps<typeof textVariants>, "color"> { 66 + // Override color to accept hex values and custom strings 67 + color?: 68 + | "default" 69 + | "muted" 70 + | "primary" 71 + | "secondary" 72 + | "destructive" 73 + | "success" 74 + | "warning" 75 + | (string & {}); 76 // Additional convenience props 77 muted?: boolean; 78 bold?: boolean;
+5
js/components/src/components/ui/textarea.tsx
··· 5 import * as React from "react"; 6 import { Platform, TextInput, type TextInputProps } from "react-native"; 7 import { bg, borders, flex, p, text } from "../../lib/theme/atoms"; 8 9 const Textarea = React.forwardRef<TextInput, TextInputProps>( 10 ({ style, multiline = true, numberOfLines = 4, ...props }, ref) => { 11 // Detect if we're inside a bottom sheet 12 let isInBottomSheet = false; 13 try { ··· 38 { borderRadius: 10 }, 39 style, 40 ]} 41 multiline={multiline} 42 numberOfLines={numberOfLines} 43 textAlignVertical="top" 44 {...props} 45 /> 46 );
··· 5 import * as React from "react"; 6 import { Platform, TextInput, type TextInputProps } from "react-native"; 7 import { bg, borders, flex, p, text } from "../../lib/theme/atoms"; 8 + import { useTheme } from "../../ui"; 9 10 const Textarea = React.forwardRef<TextInput, TextInputProps>( 11 ({ style, multiline = true, numberOfLines = 4, ...props }, ref) => { 12 + let th = useTheme(); 13 // Detect if we're inside a bottom sheet 14 let isInBottomSheet = false; 15 try { ··· 40 { borderRadius: 10 }, 41 style, 42 ]} 43 + autoComplete={props.autoComplete || "off"} 44 + textContentType={props.textContentType || "none"} 45 multiline={multiline} 46 numberOfLines={numberOfLines} 47 textAlignVertical="top" 48 + placeholderTextColor={th.theme.colors.textMuted} 49 {...props} 50 /> 51 );
+1
js/components/src/hooks/index.ts
··· 1 // barrel file :) 2 export * from "./useAvatars"; 3 export * from "./useCameraToggle"; 4 export * from "./useDocumentTitle";
··· 1 // barrel file :) 2 + export * from "./useAQState"; 3 export * from "./useAvatars"; 4 export * from "./useCameraToggle"; 5 export * from "./useDocumentTitle";
+37
js/components/src/hooks/useAQState.ts
···
··· 1 + import { useEffect, useState } from "react"; 2 + import storage from "../storage"; 3 + 4 + export function useAQState<T>( 5 + key: string, 6 + defaultValue: T, 7 + ): [T, (value: T) => void] { 8 + const [state, setState] = useState<T>(defaultValue); 9 + const [isLoaded, setIsLoaded] = useState(false); 10 + 11 + useEffect(() => { 12 + const loadFromStorage = async () => { 13 + try { 14 + const stored = await storage.getItem(key); 15 + if (stored !== null) { 16 + setState(JSON.parse(stored)); 17 + } 18 + } catch (error) { 19 + console.error(`Failed to load ${key} from storage:`, error); 20 + } finally { 21 + setIsLoaded(true); 22 + } 23 + }; 24 + loadFromStorage(); 25 + }, [key]); 26 + 27 + const setStoredState = (value: T) => { 28 + setState(value); 29 + if (isLoaded) { 30 + storage.setItem(key, JSON.stringify(value)).catch((error) => { 31 + console.error(`Failed to save ${key} to storage:`, error); 32 + }); 33 + } 34 + }; 35 + 36 + return [state, setStoredState]; 37 + }
+8
js/components/src/hooks/useLivestreamInfo.ts
··· 9 const ingestStarting = usePlayerStore((x) => x.ingestStarting); 10 const setIngestStarting = usePlayerStore((x) => x.setIngestStarting); 11 const setIngestLive = usePlayerStore((x) => x.setIngestLive); 12 13 const createStreamRecord = useCreateStreamRecord(); 14 ··· 54 } 55 }; 56 57 return { 58 ingest, 59 profile, ··· 67 setIngestStarting, 68 handleSubmit, 69 toggleGoLive, 70 }; 71 }
··· 9 const ingestStarting = usePlayerStore((x) => x.ingestStarting); 10 const setIngestStarting = usePlayerStore((x) => x.setIngestStarting); 11 const setIngestLive = usePlayerStore((x) => x.setIngestLive); 12 + const stopIngest = usePlayerStore((x) => x.stopIngest); 13 14 const createStreamRecord = useCreateStreamRecord(); 15 ··· 55 } 56 }; 57 58 + // Stop the current broadcast 59 + const toggleStopStream = () => { 60 + console.log("Stopping stream..."); 61 + stopIngest(); 62 + }; 63 + 64 return { 65 ingest, 66 profile, ··· 74 setIngestStarting, 75 handleSubmit, 76 toggleGoLive, 77 + toggleStopStream, 78 }; 79 }
+1 -1
js/components/src/hooks/useSegmentTiming.tsx
··· 22 export function useSegmentTiming() { 23 const latestSegment = useLivestreamStore((x) => x.segment); 24 const [segmentDeltas, setSegmentDeltas] = useState<number[]>([]); 25 - const prevSegmentRef = useRef<any>(null); 26 const prevTimestampRef = useRef<number | null>(null); 27 28 // Dummy state to force update every second
··· 22 export function useSegmentTiming() { 23 const latestSegment = useLivestreamStore((x) => x.segment); 24 const [segmentDeltas, setSegmentDeltas] = useState<number[]>([]); 25 + const prevSegmentRef = useRef<any>(); 26 const prevTimestampRef = useRef<number | null>(null); 27 28 // Dummy state to force update every second
+5
js/components/src/index.tsx
··· 34 export * from "./components/chat/chat"; 35 export * from "./components/chat/chat-box"; 36 export * from "./components/chat/system-message"; 37 export { default as VideoRetry } from "./components/mobile-player/video-retry"; 38 export * from "./lib/system-messages"; 39 40 export * from "./utils/format-handle"; 41 42 export { DanmuOverlay } from "./components/danmu/danmu-overlay";
··· 34 export * from "./components/chat/chat"; 35 export * from "./components/chat/chat-box"; 36 export * from "./components/chat/system-message"; 37 + export * from "./components/chat/update-stream-title-dialog"; 38 export { default as VideoRetry } from "./components/mobile-player/video-retry"; 39 export * from "./lib/system-messages"; 40 41 + export * from "./components/stream-notification"; 42 + export * from "./lib/stream-notifications"; 43 + 44 + export * from "./utils/did"; 45 export * from "./utils/format-handle"; 46 47 export { DanmuOverlay } from "./components/danmu/danmu-overlay";
+136
js/components/src/lib/slash-commands/teleport.ts
···
··· 1 + import { PlaceStreamLiveTeleport, StreamplaceAgent } from "streamplace"; 2 + import { 3 + registerSlashCommand, 4 + SlashCommandHandler, 5 + SlashCommandResult, 6 + } from "../slash-commands"; 7 + 8 + export async function deleteTeleport( 9 + pdsAgent: StreamplaceAgent, 10 + userDID: string, 11 + uri: string, 12 + ) { 13 + const rkey = uri.split("/").pop(); 14 + if (!rkey) { 15 + throw new Error("No rkey found in teleport URI"); 16 + } 17 + return await pdsAgent.com.atproto.repo.deleteRecord({ 18 + repo: userDID, 19 + collection: "place.stream.live.teleport", 20 + rkey: rkey, 21 + }); 22 + } 23 + 24 + export function registerTeleportCommand( 25 + pdsAgent: StreamplaceAgent, 26 + userDID: string, 27 + setActiveTeleportUri?: (uri: string | null) => void, 28 + ) { 29 + const teleportHandler: SlashCommandHandler = async ( 30 + args, 31 + rawInput, 32 + ): Promise<SlashCommandResult> => { 33 + if (args.length === 0) { 34 + return { 35 + handled: true, 36 + error: "Usage: /teleport @handle.bsky.social [duration_seconds]", 37 + }; 38 + } 39 + 40 + let targetHandle = args[0]; 41 + 42 + if (targetHandle.startsWith("@")) { 43 + targetHandle = targetHandle.slice(1); 44 + } 45 + 46 + if (!targetHandle.includes(".")) { 47 + return { 48 + handled: true, 49 + error: "Invalid handle format. Expected: handle.bsky.social", 50 + }; 51 + } 52 + 53 + let countdownSeconds = 10; 54 + if (args.length > 1) { 55 + const parsedDuration = parseInt(args[1], 10); 56 + if (isNaN(parsedDuration)) { 57 + return { 58 + handled: true, 59 + error: "Countdown must be a number (seconds)", 60 + }; 61 + } 62 + if (parsedDuration < 5 || parsedDuration > 300) { 63 + return { 64 + handled: true, 65 + error: "Countdown must be between 5 seconds and 5 minutes", 66 + }; 67 + } 68 + countdownSeconds = parsedDuration; 69 + } 70 + 71 + let targetDID: string; 72 + try { 73 + const resolution = await pdsAgent.resolveHandle({ 74 + handle: targetHandle, 75 + }); 76 + targetDID = resolution.data.did; 77 + } catch (err) { 78 + return { 79 + handled: true, 80 + error: `Could not resolve handle: ${targetHandle}`, 81 + }; 82 + } 83 + 84 + if (targetDID === userDID) { 85 + return { 86 + handled: true, 87 + error: "You cannot teleport to yourself", 88 + }; 89 + } 90 + 91 + const startsAt = new Date( 92 + Date.now() + countdownSeconds * 1000, 93 + ).toISOString(); 94 + 95 + const record: PlaceStreamLiveTeleport.Record = { 96 + $type: "place.stream.live.teleport", 97 + streamer: targetDID, 98 + startsAt, 99 + countdownSeconds, 100 + }; 101 + 102 + try { 103 + const result = await pdsAgent.com.atproto.repo.createRecord({ 104 + repo: userDID, 105 + collection: "place.stream.live.teleport", 106 + record, 107 + }); 108 + 109 + // store the URI in the livestream store 110 + if (setActiveTeleportUri) { 111 + setActiveTeleportUri(result.data.uri); 112 + } 113 + 114 + return { handled: true }; 115 + } catch (err) { 116 + return { 117 + handled: true, 118 + error: err instanceof Error ? err.message : "Failed to create teleport", 119 + }; 120 + } 121 + }; 122 + 123 + registerSlashCommand({ 124 + name: "teleport", 125 + description: "Start a teleport to another streamer", 126 + usage: "/teleport @handle.bsky.social [duration_seconds]", 127 + handler: teleportHandler, 128 + }); 129 + 130 + registerSlashCommand({ 131 + name: "tp", 132 + description: "Start a teleport to another streamer (alias for /teleport)", 133 + usage: "/tp @handle.bsky.social [duration_seconds]", 134 + handler: teleportHandler, 135 + }); 136 + }
+65
js/components/src/lib/slash-commands.ts
···
··· 1 + export interface SlashCommandResult { 2 + handled: boolean; 3 + error?: string; 4 + } 5 + 6 + export type SlashCommandHandler = ( 7 + args: string[], 8 + rawInput: string, 9 + ) => Promise<SlashCommandResult>; 10 + 11 + export interface SlashCommand { 12 + name: string; 13 + description: string; 14 + usage: string; 15 + handler: SlashCommandHandler; 16 + } 17 + 18 + const commands = new Map<string, SlashCommand>(); 19 + 20 + export function registerSlashCommand(command: SlashCommand) { 21 + commands.set(command.name, command); 22 + } 23 + 24 + export function unregisterSlashCommand(name: string) { 25 + commands.delete(name); 26 + } 27 + 28 + export async function handleSlashCommand( 29 + input: string, 30 + ): Promise<SlashCommandResult> { 31 + const trimmed = input.trim(); 32 + if (!trimmed.startsWith("/")) { 33 + return { handled: false }; 34 + } 35 + 36 + const parts = trimmed.slice(1).split(/\s+/); 37 + const commandName = parts[0]?.toLowerCase(); 38 + const args = parts.slice(1); 39 + 40 + if (!commandName) { 41 + return { handled: false }; 42 + } 43 + 44 + const command = commands.get(commandName); 45 + if (!command) { 46 + return { 47 + // for now - return false 48 + handled: false, 49 + error: `Unknown command: /${commandName}`, 50 + }; 51 + } 52 + 53 + try { 54 + return await command.handler(args, trimmed); 55 + } catch (err) { 56 + return { 57 + handled: true, 58 + error: err instanceof Error ? err.message : "Command failed", 59 + }; 60 + } 61 + } 62 + 63 + export function getRegisteredCommands(): SlashCommand[] { 64 + return Array.from(commands.values()); 65 + }
+51
js/components/src/lib/stream-notifications.ts
···
··· 1 + import React from "react"; 2 + import { streamNotification } from "../components/stream-notification"; 3 + import { TeleportNotification } from "../components/stream-notification/teleport-notification"; 4 + 5 + export const StreamNotifications = { 6 + teleport: (params: { 7 + targetHandle: string; 8 + targetDID: string; 9 + countdown: number; 10 + canCancel: boolean; 11 + onDismiss?: (reason?: "user" | "auto") => void; 12 + }) => { 13 + streamNotification.show({ 14 + id: "teleport", 15 + render: (isExiting, onDismiss, startTime) => { 16 + return React.createElement(TeleportNotification, { 17 + targetHandle: params.targetHandle, 18 + countdown: params.countdown, 19 + canCancel: params.canCancel, 20 + startTime: startTime, 21 + onDismiss: onDismiss, 22 + }); 23 + }, 24 + duration: 0, // manually dismissed by countdown or user cancel 25 + variant: "warning", 26 + onDismiss: params.onDismiss, 27 + }); 28 + }, 29 + 30 + teleportCancelled: () => { 31 + streamNotification.hide("teleport"); 32 + }, 33 + 34 + teleportNow: (targetHandle: string) => { 35 + streamNotification.show({ 36 + id: "teleport-now", 37 + message: `Teleporting to @${targetHandle}...`, 38 + duration: 2, 39 + variant: "info", 40 + }); 41 + }, 42 + 43 + activate: (message: string) => { 44 + streamNotification.show({ 45 + id: "stream-activate", 46 + message: message, 47 + duration: 3, 48 + variant: "info", 49 + }); 50 + }, 51 + };
+52 -2
js/components/src/lib/system-messages.ts
··· 4 stream_start = "stream_start", 5 stream_end = "stream_end", 6 notification = "notification", 7 } 8 9 export interface SystemMessageMetadata { ··· 22 * @param metadata Optional metadata for the message 23 * @returns A properly formatted ChatMessageViewHydrated object 24 */ 25 export const createSystemMessage = ( 26 type: SystemMessageType, 27 text: string, ··· 29 date: Date = new Date(), 30 ): ChatMessageViewHydrated => { 31 const now = date; 32 33 return { 34 - uri: `at://did:sys:system/place.stream.chat.message/${now.getTime()}`, 35 - cid: `system-${now.getTime()}`, 36 author: { 37 did: "did:sys:system", 38 handle: type, // Use handle to specify the type of system message ··· 73 { duration }, 74 ), 75 76 notification: (message: string): ChatMessageViewHydrated => 77 createSystemMessage(SystemMessageType.notification, message), 78 }; 79 80 /**
··· 4 stream_start = "stream_start", 5 stream_end = "stream_end", 6 notification = "notification", 7 + command_error = "command_error", 8 } 9 10 export interface SystemMessageMetadata { ··· 23 * @param metadata Optional metadata for the message 24 * @returns A properly formatted ChatMessageViewHydrated object 25 */ 26 + let systemMessageCounter = 0; 27 + 28 export const createSystemMessage = ( 29 type: SystemMessageType, 30 text: string, ··· 32 date: Date = new Date(), 33 ): ChatMessageViewHydrated => { 34 const now = date; 35 + const uniqueId = `${now.getTime()}-${systemMessageCounter++}`; 36 37 return { 38 + uri: `at://did:sys:system/place.stream.chat.message/${uniqueId}`, 39 + cid: `system-${uniqueId}`, 40 author: { 41 did: "did:sys:system", 42 handle: type, // Use handle to specify the type of system message ··· 77 { duration }, 78 ), 79 80 + teleportArrival: ( 81 + streamerName: string, 82 + streamerDid: string, 83 + count: number, 84 + chatProfile?: any, 85 + ): ChatMessageViewHydrated => { 86 + const text = 87 + count > 0 88 + ? `${count} viewer${count !== 1 ? "s" : ""} teleported from ${streamerName}'s stream! Say hi!` 89 + : `Someone teleported from ${streamerName}'s stream! Say hi!`; 90 + const message = createSystemMessage(SystemMessageType.notification, text, { 91 + streamerName, 92 + count, 93 + }); 94 + 95 + // create a mention facet for the streamer name so it gets colored using existing mention rendering 96 + if (chatProfile && streamerDid) { 97 + const nameStart = text.indexOf(streamerName); 98 + 99 + // encode byte positions 100 + const encoder = new TextEncoder(); 101 + const byteStart = encoder.encode(text.substring(0, nameStart)).length; 102 + const byteEnd = byteStart + encoder.encode(streamerName).length; 103 + 104 + message.record.facets = [ 105 + { 106 + index: { 107 + byteStart, 108 + byteEnd, 109 + }, 110 + features: [ 111 + { 112 + $type: "app.bsky.richtext.facet#mention", 113 + did: streamerDid, 114 + }, 115 + ], 116 + }, 117 + ]; 118 + } 119 + 120 + return message; 121 + }, 122 + 123 notification: (message: string): ChatMessageViewHydrated => 124 createSystemMessage(SystemMessageType.notification, message), 125 + 126 + commandError: (message: string): ChatMessageViewHydrated => 127 + createSystemMessage(SystemMessageType.command_error, message), 128 }; 129 130 /**
+11 -11
js/components/src/lib/theme/tokens.ts
··· 337 }, 338 339 warning: { 340 - 50: "#fffbeb", 341 - 100: "#fef3c7", 342 - 200: "#fde68a", 343 - 300: "#fcd34d", 344 - 400: "#fbbf24", 345 - 500: "#f59e0b", 346 - 600: "#d97706", 347 - 700: "#b45309", 348 - 800: "#92400e", 349 - 900: "#78350f", 350 - 950: "#451a03", 351 }, 352 353 // iOS system colors (adaptive)
··· 337 }, 338 339 warning: { 340 + 50: "#fffaf0", 341 + 100: "#ffe6c7", 342 + 200: "#ffd99e", 343 + 300: "#ffcc75", 344 + 400: "#ffb94e", 345 + 500: "#ff9e1f", 346 + 600: "#e67e00", 347 + 700: "#cc6600", 348 + 800: "#998c00", 349 + 900: "#664200", 350 + 950: "#332900", 351 }, 352 353 // iOS system colors (adaptive)
-20
js/components/src/lib/uuid.ts
··· 1 - export const uuidv4 = () => { 2 - return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { 3 - const r = Math.trunc(Math.random() * 16); 4 - const v = c == "x" ? r : (r & 0x3) | 0x8; 5 - return v.toString(16); 6 - }); 7 - }; 8 - 9 - export const uuidv7 = () => { 10 - return "tttttttt-tttt-7xxx-yxxx-xxxxxxxxxxxx" 11 - .replace(/[xy]/g, function (c) { 12 - const r = Math.trunc(Math.random() * 16); 13 - const v = c == "x" ? r : (r & 0x3) | 0x8; 14 - return v.toString(16); 15 - }) 16 - .replace(/^[t]{8}-[t]{4}/, function () { 17 - const unixtimestamp = Date.now().toString(16).padStart(12, "0"); 18 - return unixtimestamp.slice(0, 8) + "-" + unixtimestamp.slice(8); 19 - }); 20 - };
···
+106 -3
js/components/src/livestream-provider/index.tsx
··· 1 - import React, { useContext, useRef } from "react"; 2 - import { LivestreamContext, makeLivestreamStore } from "../livestream-store"; 3 import { useLivestreamWebsocket } from "./websocket"; 4 5 export function LivestreamProvider({ 6 children, 7 src, 8 ignoreOuterContext = false, 9 }: { 10 children: React.ReactNode; 11 src: string; 12 ignoreOuterContext?: boolean; 13 }) { 14 const context = useContext(LivestreamContext); ··· 24 (window as any).livestreamStore = store; 25 return ( 26 <LivestreamContext.Provider value={{ store: store }}> 27 - <LivestreamPoller src={src}>{children}</LivestreamPoller> 28 </LivestreamContext.Provider> 29 ); 30 } ··· 34 return <></>; 35 } 36 37 export function LivestreamPoller({ 38 children, 39 src, 40 }: { 41 children: React.ReactNode; 42 src: string; 43 }) { 44 // Websocket watcher is a sibling instead of a parent to avoid 45 // re-rendering when the websocket does stuff 46 return ( 47 <> 48 <WebsocketWatcher src={src} /> 49 {children} 50 </> 51 );
··· 1 + import React, { useContext, useEffect, useRef } from "react"; 2 + import { useAvatars } from "../hooks"; 3 + import { deleteTeleport } from "../lib/slash-commands/teleport"; 4 + import { StreamNotifications } from "../lib/stream-notifications"; 5 + import { 6 + LivestreamContext, 7 + makeLivestreamStore, 8 + useLivestreamStore, 9 + } from "../livestream-store"; 10 + import { useDID, usePDSAgent } from "../streamplace-store"; 11 import { useLivestreamWebsocket } from "./websocket"; 12 13 export function LivestreamProvider({ 14 children, 15 src, 16 + onTeleport, 17 ignoreOuterContext = false, 18 }: { 19 children: React.ReactNode; 20 src: string; 21 + onTeleport?: (targetHandle: string, targetDID: string) => void; 22 ignoreOuterContext?: boolean; 23 }) { 24 const context = useContext(LivestreamContext); ··· 34 (window as any).livestreamStore = store; 35 return ( 36 <LivestreamContext.Provider value={{ store: store }}> 37 + <LivestreamPoller src={src} onTeleport={onTeleport}> 38 + {children} 39 + </LivestreamPoller> 40 </LivestreamContext.Provider> 41 ); 42 } ··· 46 return <></>; 47 } 48 49 + export function TeleportWatcher({ 50 + onTeleport, 51 + }: { 52 + onTeleport?: (targetHandle: string, targetDID: string) => void; 53 + }) { 54 + const activeTeleport = useLivestreamStore((state) => state.activeTeleport); 55 + const activeTeleportUri = useLivestreamStore( 56 + (state) => state.activeTeleportUri, 57 + ); 58 + const profile = useAvatars(activeTeleport ? [activeTeleport.streamer] : []); 59 + const livestreamProfile = useLivestreamStore((state) => state.profile); 60 + const pdsAgent = usePDSAgent(); 61 + const userDID = useDID(); 62 + const prevActiveTeleportRef = useRef(activeTeleport); 63 + 64 + useEffect(() => { 65 + if (!activeTeleport || !profile[activeTeleport.streamer]) return; 66 + 67 + const startsAt = new Date(activeTeleport.startsAt); 68 + const now = new Date(); 69 + const countdown = Math.max( 70 + 0, 71 + Math.floor((startsAt.getTime() - now.getTime()) / 1000), 72 + ); 73 + 74 + // resolve the DID to a handle for display 75 + const targetHandle = 76 + profile[activeTeleport.streamer]?.handle || activeTeleport.streamer; 77 + 78 + // check if the current user is the streamer of the current livestream 79 + const canCancel = livestreamProfile?.did === userDID; 80 + 81 + StreamNotifications.teleport({ 82 + targetHandle: targetHandle, 83 + targetDID: activeTeleport.streamer, 84 + countdown: countdown, 85 + canCancel: canCancel, 86 + onDismiss: async (reason) => { 87 + console.log( 88 + "๐Ÿ” StreamNotifications.onDismiss called with reason:", 89 + reason, 90 + ); 91 + if (reason === "user" && activeTeleportUri && pdsAgent && userDID) { 92 + try { 93 + await deleteTeleport(pdsAgent, userDID, activeTeleportUri); 94 + } catch (err) { 95 + console.error("Failed to delete teleport:", err); 96 + } 97 + } 98 + if (reason === "auto" && onTeleport) { 99 + console.log( 100 + "๐Ÿ” Calling onTeleport with:", 101 + targetHandle, 102 + activeTeleport.streamer, 103 + ); 104 + onTeleport(targetHandle, activeTeleport.streamer); 105 + } else if (reason === "auto" && !onTeleport) { 106 + console.log("๐Ÿ” onTeleport is not defined!"); 107 + } else if (reason === "auto") { 108 + console.log( 109 + "๐Ÿ” Reason is auto but teleport function not called for unknown reason", 110 + ); 111 + } 112 + }, 113 + }); 114 + }, [ 115 + activeTeleport, 116 + activeTeleportUri, 117 + profile, 118 + onTeleport, 119 + pdsAgent, 120 + userDID, 121 + ]); 122 + 123 + useEffect(() => { 124 + if ( 125 + prevActiveTeleportRef.current && 126 + !activeTeleport && 127 + !activeTeleportUri 128 + ) { 129 + StreamNotifications.teleportCancelled(); 130 + } 131 + prevActiveTeleportRef.current = activeTeleport; 132 + }, [activeTeleport, activeTeleportUri]); 133 + 134 + return <></>; 135 + } 136 + 137 export function LivestreamPoller({ 138 children, 139 src, 140 + onTeleport, 141 }: { 142 children: React.ReactNode; 143 src: string; 144 + onTeleport?: (targetHandle: string, targetDID: string) => void; 145 }) { 146 // Websocket watcher is a sibling instead of a parent to avoid 147 // re-rendering when the websocket does stuff 148 return ( 149 <> 150 <WebsocketWatcher src={src} /> 151 + <TeleportWatcher onTeleport={onTeleport} /> 152 {children} 153 </> 154 );
+4
js/components/src/livestream-store/livestream-state.tsx
··· 3 ChatMessageViewHydrated, 4 LivestreamViewHydrated, 5 PlaceStreamDefs, 6 PlaceStreamModerationPermission, 7 PlaceStreamSegment, 8 } from "streamplace"; ··· 22 replyToMessage: ChatMessageViewHydrated | null; 23 streamKey: string | null; 24 setStreamKey: (key: string | null) => void; 25 websocketConnected: boolean; 26 hasReceivedSegment: boolean; 27 moderationPermissions: PlaceStreamModerationPermission.Record[];
··· 3 ChatMessageViewHydrated, 4 LivestreamViewHydrated, 5 PlaceStreamDefs, 6 + PlaceStreamLiveTeleport, 7 PlaceStreamModerationPermission, 8 PlaceStreamSegment, 9 } from "streamplace"; ··· 23 replyToMessage: ChatMessageViewHydrated | null; 24 streamKey: string | null; 25 setStreamKey: (key: string | null) => void; 26 + activeTeleport: PlaceStreamLiveTeleport.Record | null; 27 + activeTeleportUri: string | null; 28 + setActiveTeleportUri: (uri: string | null) => void; 29 websocketConnected: boolean; 30 hasReceivedSegment: boolean; 31 moderationPermissions: PlaceStreamModerationPermission.Record[];
+3
js/components/src/livestream-store/livestream-store.tsx
··· 22 authors: {}, 23 recentSegments: [], 24 problems: [], 25 websocketConnected: false, 26 hasReceivedSegment: false, 27 moderationPermissions: [],
··· 22 authors: {}, 23 recentSegments: [], 24 problems: [], 25 + activeTeleport: null, 26 + activeTeleportUri: null, 27 + setActiveTeleportUri: (uri) => set({ activeTeleportUri: uri }), 28 websocketConnected: false, 29 hasReceivedSegment: false, 30 moderationPermissions: [],
+36 -54
js/components/src/livestream-store/websocket-consumer.tsx
··· 7 PlaceStreamChatMessage, 8 PlaceStreamDefs, 9 PlaceStreamLivestream, 10 - PlaceStreamModerationPermission, 11 PlaceStreamSegment, 12 } from "streamplace"; 13 import { SystemMessages } from "../lib/system-messages"; 14 import { reduceChat } from "./chat"; 15 import { LivestreamState } from "./livestream-state"; 16 import { findProblems } from "./problems"; ··· 79 chatProfile: (message as any).chatProfile, 80 replyTo: (message as any).replyTo, 81 deleted: message.deleted, 82 }; 83 state = reduceChat(state, [hydrated], [], []); 84 } else if (PlaceStreamSegment.isRecord(message)) { ··· 121 pendingHides: newPendingHides, 122 }; 123 state = reduceChat(state, [], [], [hiddenMessageUri]); 124 - } else if ( 125 - PlaceStreamModerationPermission.isRecord(message) || 126 - (message && 127 - typeof message === "object" && 128 - "$type" in message && 129 - (message as { $type?: string }).$type === 130 - "place.stream.moderation.permission") 131 - ) { 132 - // Handle moderation permission record updates 133 - // This can be a new permission or a deletion marker 134 - const permRecord = message as 135 - | PlaceStreamModerationPermission.Record 136 - | { deleted?: boolean; rkey?: string; streamer?: string }; 137 138 - if ((permRecord as any).deleted) { 139 - // Handle deletion: clear permissions to trigger refetch 140 - // The useCanModerate hook will refetch and repopulate 141 state = { 142 ...state, 143 - moderationPermissions: [], 144 }; 145 - } else { 146 - // Handle new/updated permission: add or update in the list 147 - // Use createdAt as a unique identifier since multiple records can exist for the same moderator 148 - // (e.g., one record with "ban" permission, another with "hide" permission) 149 - // Note: rkey would be ideal but isn't always present in the WebSocket message 150 - const newPerm = 151 - permRecord as PlaceStreamModerationPermission.Record & { 152 - rkey?: string; 153 - }; 154 - const existingIndex = state.moderationPermissions.findIndex((p) => { 155 - const pWithRkey = p as PlaceStreamModerationPermission.Record & { 156 - rkey?: string; 157 - }; 158 - // Prefer matching by rkey if available, fall back to createdAt 159 - if (newPerm.rkey && pWithRkey.rkey) { 160 - return pWithRkey.rkey === newPerm.rkey; 161 - } 162 - return ( 163 - p.moderator === newPerm.moderator && 164 - p.createdAt === newPerm.createdAt 165 - ); 166 - }); 167 168 - let newPermissions: PlaceStreamModerationPermission.Record[]; 169 - if (existingIndex >= 0) { 170 - // Update existing record with same moderator AND createdAt 171 - newPermissions = [...state.moderationPermissions]; 172 - newPermissions[existingIndex] = newPerm; 173 - } else { 174 - // Add new record (could be a new record for an existing moderator with different permissions) 175 - newPermissions = [...state.moderationPermissions, newPerm]; 176 - } 177 178 - state = { 179 - ...state, 180 - moderationPermissions: newPermissions, 181 - }; 182 - } 183 } 184 } 185 }
··· 7 PlaceStreamChatMessage, 8 PlaceStreamDefs, 9 PlaceStreamLivestream, 10 + PlaceStreamLiveTeleport, 11 PlaceStreamSegment, 12 } from "streamplace"; 13 import { SystemMessages } from "../lib/system-messages"; 14 + import { formatHandleWithAt } from "../utils/format-handle"; 15 import { reduceChat } from "./chat"; 16 import { LivestreamState } from "./livestream-state"; 17 import { findProblems } from "./problems"; ··· 80 chatProfile: (message as any).chatProfile, 81 replyTo: (message as any).replyTo, 82 deleted: message.deleted, 83 + badges: message.badges, 84 }; 85 state = reduceChat(state, [hydrated], [], []); 86 } else if (PlaceStreamSegment.isRecord(message)) { ··· 123 pendingHides: newPendingHides, 124 }; 125 state = reduceChat(state, [], [], [hiddenMessageUri]); 126 + } else if (PlaceStreamLiveTeleport.isRecord(message)) { 127 + const teleportRecord = message as PlaceStreamLiveTeleport.Record; 128 + state = { 129 + ...state, 130 + activeTeleport: teleportRecord, 131 + }; 132 + } else if (PlaceStreamLivestream.isTeleportArrival(message)) { 133 + // teleport has succeeded, we are now at the target stream 134 + const arrival = message as PlaceStreamLivestream.TeleportArrival; 135 136 + // add the teleporter's chat profile to the authors cache FIRST so mention rendering works 137 + if (arrival.chatProfile && arrival.source.did) { 138 state = { 139 ...state, 140 + authors: { 141 + ...state.authors, 142 + [arrival.source.did]: arrival.chatProfile, 143 + }, 144 }; 145 + } 146 147 + const systemMessage = SystemMessages.teleportArrival( 148 + formatHandleWithAt(arrival.source), 149 + arrival.source.did, 150 + arrival.viewerCount, 151 + arrival.chatProfile, 152 + ); 153 + // set proper times 154 + systemMessage.indexedAt = arrival.startsAt; 155 + systemMessage.record.createdAt = arrival.startsAt; 156 157 + state = reduceChat(state, [systemMessage], []); 158 + } else if (PlaceStreamLivestream.isTeleportCanceled(message)) { 159 + // teleport was canceled (deleted or denied) 160 + state = { 161 + ...state, 162 + activeTeleport: null, 163 + activeTeleportUri: null, 164 + }; 165 } 166 } 167 }
+3
js/components/src/player-store/player-state.tsx
··· 63 ingestAutoStart?: boolean; 64 setIngestAutoStart?: (autoStart: boolean) => void; 65 66 /** Timestamp (number) when ingest started, or null if not started */ 67 ingestStarted: number | null; 68
··· 63 ingestAutoStart?: boolean; 64 setIngestAutoStart?: (autoStart: boolean) => void; 65 66 + /** stop ingest process, again with a slight delay to allow UI to update */ 67 + stopIngest: () => void; 68 + 69 /** Timestamp (number) when ingest started, or null if not started */ 70 ingestStarted: number | null; 71
+17 -11
js/components/src/player-store/player-store.tsx
··· 53 setIngestStarted: (timestamp: number | null) => 54 set(() => ({ ingestStarted: timestamp })), 55 56 fullscreen: false, 57 setFullscreen: (isFullscreen: boolean) => 58 set(() => ({ fullscreen: isFullscreen })), ··· 121 meta: { [key: string]: any }, 122 ) => 123 set((x) => { 124 - // Try to get device ID from localStorage 125 - let deviceId = meta.deviceId; 126 - if (!deviceId && typeof window !== "undefined") { 127 - try { 128 - deviceId = localStorage.getItem("deviceId"); 129 - } catch (e) { 130 - // localStorage might not be available 131 - } 132 - } 133 - 134 const data: PlayerEvent = { 135 time: time, 136 playerId: x.id, 137 eventType: eventType, 138 meta: { 139 ...meta, 140 - ...(deviceId && { deviceId }), 141 }, 142 }; 143 try {
··· 53 setIngestStarted: (timestamp: number | null) => 54 set(() => ({ ingestStarted: timestamp })), 55 56 + stopIngest: () => { 57 + set(() => ({ 58 + ingestLive: false, 59 + ingestConnectionState: "new", 60 + ingestStarted: null, 61 + })), 62 + setTimeout( 63 + () => 64 + set(() => ({ 65 + ingestLive: false, 66 + ingestConnectionState: "new", 67 + ingestStarted: null, 68 + })), 69 + 200, 70 + ); 71 + }, 72 + 73 fullscreen: false, 74 setFullscreen: (isFullscreen: boolean) => 75 set(() => ({ fullscreen: isFullscreen })), ··· 138 meta: { [key: string]: any }, 139 ) => 140 set((x) => { 141 const data: PlayerEvent = { 142 time: time, 143 playerId: x.id, 144 eventType: eventType, 145 meta: { 146 ...meta, 147 }, 148 }; 149 try {
+60 -1
js/components/src/streamplace-store/branding.tsx
··· 25 }); 26 }; 27 28 // hook to fetch broadcaster DID (unauthenticated) 29 export function useFetchBroadcasterDID() { 30 const streamplaceAgent = usePossiblyUnauthedPDSAgent(); 31 const store = getStreamplaceStoreFromContext(); 32 33 return useCallback(async () => { 34 try { ··· 140 141 // hook to get a specific branding asset by key 142 export function useBrandingAsset(key: string): BrandingAsset | undefined { 143 - return useStreamplaceStore((state) => state.branding?.[key]); 144 } 145 146 // convenience hook for main logo
··· 25 }); 26 }; 27 28 + const PropsInHeader = [ 29 + "siteTitle", 30 + "siteDescription", 31 + "primaryColor", 32 + "accentColor", 33 + "defaultStreamer", 34 + "mainLogo", 35 + "favicon", 36 + "sidebarBg", 37 + "legalLinks", 38 + ]; 39 + 40 + function getMetaContent(key: string): BrandingAsset | null { 41 + if (typeof window === "undefined" || !window.document) return null; 42 + const meta = document.querySelector(`meta[name="internal-brand:${key}`); 43 + if (meta && meta.getAttribute("content")) { 44 + let content = meta.getAttribute("content"); 45 + if (content) return JSON.parse(content) as BrandingAsset; 46 + } 47 + 48 + return null; 49 + } 50 + 51 // hook to fetch broadcaster DID (unauthenticated) 52 export function useFetchBroadcasterDID() { 53 const streamplaceAgent = usePossiblyUnauthedPDSAgent(); 54 const store = getStreamplaceStoreFromContext(); 55 + 56 + // prefetch from meta records, if on web 57 + useEffect(() => { 58 + if (typeof window !== "undefined" && window.document) { 59 + try { 60 + const metaRecords = PropsInHeader.reduce( 61 + (acc, key) => { 62 + const meta = document.querySelector( 63 + `meta[name="internal-brand:${key}`, 64 + ); 65 + // hrmmmmmmmmmmmm 66 + if (meta && meta.getAttribute("content")) { 67 + let content = meta.getAttribute("content"); 68 + if (content) acc[key] = JSON.parse(content) as BrandingAsset; 69 + } 70 + return acc; 71 + }, 72 + {} as Record<string, BrandingAsset>, 73 + ); 74 + 75 + console.log("Found meta records for broadcaster DID:", metaRecords); 76 + // filter out all non-text values, can get on second fetch? 77 + for (const key of Object.keys(metaRecords)) { 78 + if (metaRecords[key].mimeType != "text/plain") { 79 + delete metaRecords[key]; 80 + } 81 + } 82 + } catch (e) { 83 + console.warn("Failed to parse broadcaster DID from meta tags", e); 84 + } 85 + } 86 + }, []); 87 88 return useCallback(async () => { 89 try { ··· 195 196 // hook to get a specific branding asset by key 197 export function useBrandingAsset(key: string): BrandingAsset | undefined { 198 + return ( 199 + useStreamplaceStore((state) => state.branding?.[key]) || 200 + getMetaContent(key) || 201 + undefined 202 + ); 203 } 204 205 // convenience hook for main logo
+1
js/components/src/streamplace-store/index.tsx
··· 5 export * from "./stream"; 6 export * from "./streamplace-store"; 7 export * from "./user";
··· 5 export * from "./stream"; 6 export * from "./streamplace-store"; 7 export * from "./user"; 8 + export * from "./xrpc";
-5
js/components/src/streamplace-store/streamplace-store.tsx
··· 2 import { useContext } from "react"; 3 import { PlaceStreamChatProfile, PlaceStreamLivestream } from "streamplace"; 4 import { createStore, StoreApi, useStore } from "zustand"; 5 - import { uuidv4 } from "../lib/uuid"; 6 import storage from "../storage"; 7 import { StreamplaceContext } from "../streamplace-provider/context"; 8 import { BrandingAsset } from "./branding"; ··· 41 oauthSession: SessionManager | null | undefined; 42 handle: string | null; 43 chatProfile: PlaceStreamChatProfile.Record | null; 44 - 45 - sessionId: string | null; 46 47 // Content metadata state 48 contentMetadata: ContentMetadataResult | null; ··· 116 oauthSession: null, 117 handle: null, 118 chatProfile: null, 119 - 120 - sessionId: uuidv4(), 121 122 broadcasterDID: null, 123 setBroadcasterDID: (broadcasterDID: string | null) =>
··· 2 import { useContext } from "react"; 3 import { PlaceStreamChatProfile, PlaceStreamLivestream } from "streamplace"; 4 import { createStore, StoreApi, useStore } from "zustand"; 5 import storage from "../storage"; 6 import { StreamplaceContext } from "../streamplace-provider/context"; 7 import { BrandingAsset } from "./branding"; ··· 40 oauthSession: SessionManager | null | undefined; 41 handle: string | null; 42 chatProfile: PlaceStreamChatProfile.Record | null; 43 44 // Content metadata state 45 contentMetadata: ContentMetadataResult | null; ··· 113 oauthSession: null, 114 handle: null, 115 chatProfile: null, 116 117 broadcasterDID: null, 118 setBroadcasterDID: (broadcasterDID: string | null) =>
+61
js/components/src/utils/did.ts
···
··· 1 + export interface DIDDocument { 2 + id: string; 3 + service?: Array<{ 4 + id: string; 5 + type?: string; 6 + serviceEndpoint?: string; 7 + }>; 8 + [key: string]: any; 9 + } 10 + 11 + export async function resolveDIDDocument(did: string): Promise<DIDDocument> { 12 + let didDocUrl: string; 13 + 14 + if (did.startsWith("did:web:")) { 15 + // For did:web, construct the URL directly 16 + const domain = did.replace("did:web:", "").replace(/:/g, "/"); 17 + didDocUrl = `https://${domain}/.well-known/did.json`; 18 + } else if (did.startsWith("did:plc:")) { 19 + // For did:plc, use plc.directory 20 + didDocUrl = `https://plc.directory/${did}`; 21 + } else { 22 + throw new Error(`Unsupported DID method: ${did}`); 23 + } 24 + 25 + const response = await fetch(didDocUrl); 26 + if (!response.ok) { 27 + throw new Error( 28 + `Failed to resolve DID document for ${did}: ${response.status}`, 29 + ); 30 + } 31 + 32 + return response.json(); 33 + } 34 + 35 + export function getPDSServiceEndpoint(didDoc: DIDDocument): string { 36 + const pdsService = didDoc.service?.find((s) => s.id === "#atproto_pds"); 37 + 38 + if (!pdsService?.serviceEndpoint) { 39 + throw new Error("No PDS service endpoint found in DID document"); 40 + } 41 + 42 + return pdsService.serviceEndpoint; 43 + } 44 + 45 + export async function getBlob( 46 + did: string, 47 + cid: string, 48 + didDoc?: DIDDocument, 49 + ): Promise<Blob> { 50 + const doc = didDoc || (await resolveDIDDocument(did)); 51 + const pdsEndpoint = getPDSServiceEndpoint(doc); 52 + 53 + const blobUrl = `${pdsEndpoint}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}`; 54 + 55 + const response = await fetch(blobUrl); 56 + if (!response.ok) { 57 + throw new Error(`Failed to fetch blob: ${response.status}`); 58 + } 59 + 60 + return response.blob(); 61 + }
+2
js/docs/_redirects
···
··· 1 + / /docs 301 2 + /docs/favicon.ico https://stream.place/favicon.ico 301
+71 -37
js/docs/astro.config.mjs
··· 1 // @ts-check 2 import starlight from "@astrojs/starlight"; 3 - import { defineConfig } from "astro/config"; 4 import starlightOpenAPI, { openAPISidebarGroups } from "starlight-openapi"; 5 6 // https://astro.build/config 7 export default defineConfig({ 8 base: "/docs", 9 integrations: [ 10 starlight({ 11 title: "Streamplace Docs", ··· 29 }, 30 favicon: "/favicon.ico", 31 plugins: [ 32 starlightOpenAPI([ 33 { 34 - base: "api", 35 label: "Related XRPC API endpoints", 36 schema: "./src/content/docs/lex-reference/openapi.json", // or your json generated from swagger 37 sidebar: { ··· 42 }, 43 }, 44 ]), 45 - ], 46 - sidebar: [ 47 - { label: "โ† Back to Streamplace", link: "/../" }, 48 - { 49 - label: "How Streamplace Works (Blog)", 50 - link: "https://blog.stream.place/", 51 - attrs: { target: "_blank" }, 52 - }, 53 - { 54 - label: "Guides", 55 - items: [ 56 { 57 - label: "Start Streaming", 58 - autogenerate: { directory: "guides/start-streaming" }, 59 }, 60 { 61 - label: "Installing Streamplace", 62 - autogenerate: { directory: "guides/installing" }, 63 }, 64 { 65 - label: "Start Contributing", 66 - autogenerate: { directory: "guides/start-contributing" }, 67 }, 68 ], 69 - }, 70 - { 71 - label: "Features", 72 - autogenerate: { directory: "features" }, 73 - }, 74 - { 75 - label: "Video Metadata", 76 - autogenerate: { directory: "video-metadata" }, 77 - }, 78 - { 79 - label: "Components", 80 - autogenerate: { directory: "components" }, 81 - }, 82 - { 83 - label: "Lexicon Reference", 84 - autogenerate: { directory: "lex-reference" }, 85 - }, 86 - ...openAPISidebarGroups, 87 ], 88 }), 89 ],
··· 1 // @ts-check 2 import starlight from "@astrojs/starlight"; 3 + import { defineConfig, passthroughImageService } from "astro/config"; 4 import starlightOpenAPI, { openAPISidebarGroups } from "starlight-openapi"; 5 + import starlightSidebarSwipe from "starlight-sidebar-swipe"; 6 + import starlightSidebarTopics from "starlight-sidebar-topics"; 7 8 // https://astro.build/config 9 export default defineConfig({ 10 base: "/docs", 11 + image: { 12 + service: passthroughImageService(), 13 + }, 14 integrations: [ 15 starlight({ 16 title: "Streamplace Docs", ··· 34 }, 35 favicon: "/favicon.ico", 36 plugins: [ 37 + //starlightLinksValidator(), 38 + starlightSidebarSwipe(), 39 starlightOpenAPI([ 40 { 41 + base: "/api", 42 label: "Related XRPC API endpoints", 43 schema: "./src/content/docs/lex-reference/openapi.json", // or your json generated from swagger 44 sidebar: { ··· 49 }, 50 }, 51 ]), 52 + starlightSidebarTopics( 53 + [ 54 { 55 + label: "For Streamers & Viewers", 56 + link: "/", 57 + icon: "open-book", 58 + items: [ 59 + { 60 + label: "Start Streaming", 61 + autogenerate: { directory: "guides/start-streaming" }, 62 + }, 63 + { 64 + label: "Features", 65 + autogenerate: { directory: "features" }, 66 + }, 67 + ], 68 }, 69 { 70 + label: "For Developers", 71 + link: "/developers/", 72 + icon: "seti:config", 73 + id: "developers", 74 + items: [ 75 + { 76 + label: "Start Contributing", 77 + autogenerate: { directory: "guides/start-contributing" }, 78 + }, 79 + { 80 + label: "Installing Streamplace", 81 + autogenerate: { directory: "guides/installing" }, 82 + }, 83 + { 84 + label: "Features (Dev)", 85 + autogenerate: { directory: "features-dev" }, 86 + }, 87 + { 88 + label: "Video Metadata", 89 + autogenerate: { directory: "video-metadata" }, 90 + }, 91 + { 92 + label: "Components", 93 + autogenerate: { directory: "components" }, 94 + }, 95 + { 96 + label: "Localize Streamplace", 97 + autogenerate: { directory: "guides/localizing" }, 98 + }, 99 + ], 100 }, 101 { 102 + label: "API Reference", 103 + link: "/reference/", 104 + icon: "seti:json", 105 + id: "ref", 106 + items: [ 107 + { 108 + label: "Lexicon Reference", 109 + autogenerate: { directory: "lex-reference" }, 110 + }, 111 + ...openAPISidebarGroups, 112 + ], 113 }, 114 ], 115 + { 116 + topics: { 117 + ref: ["/api", "/api/**/*"], 118 + }, 119 + }, 120 + ), 121 ], 122 }), 123 ],
+8 -2
js/docs/package.json
··· 1 { 2 "name": "streamplace-docs", 3 "type": "module", 4 - "version": "0.9.0", 5 "scripts": { 6 "dev": "astro dev --host 0.0.0.0 --port 38082", 7 "start": "astro dev --host 0.0.0.0 --port 38082", ··· 15 "@streamplace/app": "workspace:*", 16 "astro": "^5.6.1", 17 "sharp": "^0.32.5", 18 "starlight-openapi": "^0.17.0", 19 "starlight-openapi-rapidoc": "^0.8.1-beta", 20 "streamplace": "workspace:*" 21 - } 22 }
··· 1 { 2 "name": "streamplace-docs", 3 "type": "module", 4 + "version": "0.9.9", 5 "scripts": { 6 "dev": "astro dev --host 0.0.0.0 --port 38082", 7 "start": "astro dev --host 0.0.0.0 --port 38082", ··· 15 "@streamplace/app": "workspace:*", 16 "astro": "^5.6.1", 17 "sharp": "^0.32.5", 18 + "starlight-links-validator": "^0.19.2", 19 "starlight-openapi": "^0.17.0", 20 "starlight-openapi-rapidoc": "^0.8.1-beta", 21 + "starlight-sidebar-swipe": "^0.1.1", 22 "streamplace": "workspace:*" 23 + }, 24 + "devDependencies": { 25 + "starlight-sidebar-topics": "^0.6.2" 26 + }, 27 + "private": true 28 }
+60
js/docs/src/components/HelpDesk.astro
···
··· 1 + --- 2 + import { Card, CardGrid } from "@astrojs/starlight/components"; 3 + 4 + interface Props { 5 + searchPlaceholder?: string; 6 + } 7 + --- 8 + 9 + <div class="helpdesk"> 10 + 11 + <h2>How can we help?</h2> 12 + <p>Search the knowledge base, or check out topics below.</p> 13 + 14 + <CardGrid> 15 + <Card title="Getting Started" icon="rocket"> 16 + <p>New to Streamplace? Start here to set up your first stream.</p> 17 + <ul> 18 + <li><a href="/docs/guides/start-streaming/quick-start">Quick start guide</a></li> 19 + <li><a href="/docs/guides/start-streaming/obs">Stream with OBS</a></li> 20 + </ul> 21 + </Card> 22 + 23 + <Card title="Developers & Self-Hosters" icon="laptop"> 24 + <p>Building with Streamplace or running your own node?</p> 25 + <ul> 26 + <li><a href="/docs/developers">Developer documentation</a></li> 27 + </ul> 28 + </Card> 29 + </CardGrid> 30 + </div> 31 + 32 + <style> 33 + .helpdesk { 34 + margin: 0 auto; 35 + } 36 + 37 + .helpdesk-search { 38 + margin-bottom: 2rem; 39 + } 40 + 41 + .search-input { 42 + width: 100%; 43 + padding: 1rem 1.5rem; 44 + font-size: 1.125rem; 45 + border: 2px solid var(--sl-color-gray-5); 46 + border-radius: 0.5rem; 47 + background: var(--sl-color-bg); 48 + color: var(--sl-color-text); 49 + transition: border-color 0.2s; 50 + } 51 + 52 + .search-input:focus { 53 + outline: none; 54 + border-color: var(--sl-color-accent); 55 + } 56 + 57 + .helpdesk h2 { 58 + margin-bottom: 1.5rem; 59 + } 60 + </style>
+1 -2
js/docs/src/content/docs/components/custom_ui.md
··· 1 --- 2 title: Creating your own player UI 3 - description: 4 - How to set up your player UI with components from @streamplace/components. 5 --- 6 7 # Building a Custom Player UI
··· 1 --- 2 title: Creating your own player UI 3 + description: How to set up your player UI with components from @streamplace/components. 4 --- 5 6 # Building a Custom Player UI
+40
js/docs/src/content/docs/developers.mdx
···
··· 1 + --- 2 + title: Developers & Self-Hosters 3 + description: Build with Streamplace or run your own infrastructure. 4 + template: doc 5 + --- 6 + 7 + import { Card, CardGrid } from "@astrojs/starlight/components"; 8 + 9 + ## Learn how to deploy, or contribute to Streamplace. 10 + 11 + <br /> 12 + 13 + <CardGrid stagger> 14 + <Card title="Building an Application" icon="laptop"> 15 + Integrate live video into your project. - [API 16 + reference](/docs/lex-reference/place-stream-defs) - [Our component 17 + library](/docs/components/custom_ui/) 18 + </Card> 19 + 20 + {" "} 21 + 22 + <Card title="Self-Hosting" icon="seti:config"> 23 + Run your own Streamplace infrastructure. - [Installation 24 + guide](/docs/guides/installing/installing-streamplace) 25 + </Card> 26 + 27 + {" "} 28 + 29 + <Card title="Contributing" icon="github"> 30 + Help improve Streamplace. - [Development 31 + setup](/docs/guides/streamplace-dev-setup) - [Video 32 + signing](/docs/video-metadata/intro/) 33 + </Card> 34 + 35 + <Card title="Support & Community" icon="information"> 36 + Get help and connect with other developers. - [GitHub 37 + issues](https://github.com/streamplace/streamplace/issues) - [Discord 38 + community](https://discord.stream.place) 39 + </Card> 40 + </CardGrid>
+3 -1
js/docs/src/content/docs/features/danmu.md
··· 3 description: Add flying bullet-style chat comments to the player, or your stream 4 --- 5 6 - :::note This feature is experimental and may change in future releases. ::: 7 8 [Danmu (or Danmaku)](https://en.wikipedia.org/wiki/Danmaku_subtitling) (ๅผนๅน•, 9 "bullet curtain") is a comment style where messages fly across the video
··· 3 description: Add flying bullet-style chat comments to the player, or your stream 4 --- 5 6 + :::note 7 + This feature is experimental and may change in future releases. 8 + ::: 9 10 [Danmu (or Danmaku)](https://en.wikipedia.org/wiki/Danmaku_subtitling) (ๅผนๅน•, 11 "bullet curtain") is a comment style where messages fly across the video
+27
js/docs/src/content/docs/features/embed.md
···
··· 1 + --- 2 + title: Embedding your livestream 3 + description: How to embed your livestream on your website, blog, etc. 4 + --- 5 + 6 + Streamplace provides an easy way to embed your livestream on any website or 7 + blog. 8 + 9 + You can access the embedded livestream page by putting `/embed` in the URL of 10 + your livestream. For example, if your livestream URL is 11 + `https://stream.place/iame.li`, the embed URL will be 12 + `https://stream.place/embed/iame.li`. 13 + 14 + You can use the following HTML snippet to embed your livestream: 15 + 16 + ```html 17 + <iframe 18 + src="https://stream.place/embed/your-handle" 19 + width="560" 20 + height="315" 21 + frameborder="0" 22 + allowfullscreen 23 + ></iframe> 24 + ``` 25 + 26 + Alternatively, you can use the share sheet located on your livestream page. 27 + Click the "Share" button, and you'll find the embed code ready to copy.
+52
js/docs/src/content/docs/features/multistreaming.md
···
··· 1 + --- 2 + title: Multistreaming 3 + description: Forward your Streamplace stream to other providers. 4 + --- 5 + 6 + :::note 7 + This guide isn't about setting up Streamplace as an OBS destination. See [OBS Multistreaming to Streamplace](/docs/guides/start-streaming/obs-multistreaming/) for information on that. 8 + ::: 9 + 10 + Multistreaming lets you forward your Streamplace stream to multiple platforms at the same time. Instead of streaming only to Streamplace, you can forward your stream to any platform that accepts RTMP input. 11 + 12 + ## Setting up multistream targets 13 + 14 + 1. Go to **Settings** > **Streaming** > **Multistream Targets** 15 + 2. Click **Create Multistream Target** 16 + 3. Enter the RTMP or RTMPS URL from your destination platform 17 + 4. Optionally give it a name to identify it later 18 + 5. Click **Create** 19 + 20 + ### Finding your multistream URL 21 + 22 + Different platforms will provide their own RTMP URLs. Some common examples: 23 + 24 + - **YouTube Live**: Format `rtmp://a.rtmp.youtube.com/live2/your-stream-key` 25 + - Find your stream key at https://studio.youtube.com/channel/UC/livestreaming (click the copy icon in the top right corner of the 'connect your encoder to go live' box) 26 + - **Twitch**: Format `rtmp://usw20.contribute.live-video.net/app/your-stream-key` 27 + - You can get a valid RTMPS url at https://help.twitch.tv/s/twitch-ingest-recommendation 28 + - Find your stream key at https://dashboard.twitch.tv/settings/stream (your 'primary stream key') 29 + 30 + :::note 31 + Your stream key should automatically be hidden once you confirm. Make sure you've entered it correctly! 32 + ::: 33 + 34 + ## Managing targets during a stream 35 + 36 + When you're live, you can see all your multistream targets on the Live Dashboard with their current status: 37 + 38 + - **Green (Active)**: Successfully streaming to this target 39 + - **Yellow (Pending)**: Connecting to this target 40 + - **Red (Error)**: Connection failed; check your URL and credentials 41 + - **Gray (Inactive)**: This target is disabled 42 + 43 + You can toggle any target on or off with the switch next to its name. Changes take effect immediately. 44 + 45 + ## Limits 46 + 47 + - **Maximum targets**: 100 total per account 48 + - **Maximum active targets**: 5 simultaneous streams 49 + 50 + ### Credits 51 + 52 + A portion of this documentation was taken from [ndroo.tv](https://bsky.app/profile/ndroo.tv)'s [guide on Streamplace](https://ndroo.tv/streamplace.html#2-configuring-your-account).
+83
js/docs/src/content/docs/features/webhooks.md
···
··· 1 + --- 2 + title: Discord Webhooks 3 + description: Configure Discord webhooks for livestream announcements and chat 4 + sidebar: 5 + order: 30 6 + --- 7 + 8 + Streamplace supports Discord webhooks for receiving livestream 9 + notifications and chat messages. You can create, manage, and configure webhooks 10 + to customize how events are delivered to your Discord channels. 11 + 12 + ## Webhook Events 13 + 14 + You can configure webhooks to listen for specific events. For right now, the 15 + following events are supported: 16 + 17 + - `Chat`: Triggered when a chat message is sent. 18 + - `Livestream`: Triggered when a livestream starts. 19 + 20 + ## Creating a Webhook 21 + 22 + To create a webhook, go to the "Settings" page of the Streamplace web app, then 23 + navigate to the "Webhooks" section. Click on "Create Webhook". The following 24 + fields are required: 25 + 26 + - Name: Webhook URL. For example, 27 + `https://discord.com/api/webhooks/{webhook.id}/{webhook.token}` 28 + - Events: Select the events you want to subscribe to (e.g., `Chat Messages`, 29 + `Livestream Started`). `Livestream Started` is pre-checked by default. 30 + 31 + We'd recommend also filling out these optional fields: 32 + 33 + - Name: A name for the webhook (e.g., "Discord Livestream Notifications") that 34 + you can remember. 35 + - Description: A description of what this webhook is for (e.g., "Sends 36 + livestream start notifications to Discord channel"). 37 + - Prefix: A prefix to add to each message sent by this webhook (e.g., 38 + "[Streamplace] "). Will apply to both Chat and Livestream events! 39 + - Suffix: A suffix to add to each message sent by this webhook (e.g., "is now 40 + live!"). Will apply to both Chat and Livestream events! 41 + - Text replacements: A list of text replacements to apply to chat messages sent 42 + by this webhook. Each replacement consists of a "from" string and a "to" 43 + string. For example, you could replace all instances of "foo" with "bar". 44 + 45 + After filling out the form, click "Create" to save your webhook. You should see 46 + it listed in the "Webhooks" section. 47 + 48 + ## Updating a Webhook 49 + 50 + To update a webhook, go to the "Settings" page of the Streamplace web app, then 51 + navigate to the "Webhooks" section. Find the webhook you want to update and 52 + click on the "pen" icon next to it. This will open the webhook edit form, where 53 + you can modify the fields as needed. After making your changes, click "Update" 54 + to save your changes. 55 + 56 + ## Deleting a Webhook 57 + 58 + To delete a webhook, go to the "Settings" page of the Streamplace web app, then 59 + navigate to the "Webhooks" section. Find the webhook you want to delete and 60 + click on the "trash" icon next to it. A confirmation dialog will appear; click 61 + "Delete" to confirm. The webhook will be removed from the list. 62 + 63 + ## Recommendations 64 + 65 + We'd recommend: 66 + 67 + - Creating separate Discord channels for livestream notifications and chat 68 + messages to keep them organized. 69 + - If you want to have one webhook for both chat and livestream events, you can 70 + create multiple webhooks with the same URL but different event subscriptions 71 + and prefixes/suffixes/replacements. 72 + - Testing your webhook by starting a livestream or sending a chat message to 73 + ensure that notifications are being sent correctly. 74 + 75 + ## API Documentation 76 + 77 + See these endpoint pages: 78 + 79 + - [Create Webhook](/docs/api/operations/placestreamservercreatewebhook) 80 + - [Get Webhook](/docs/api/operations/placestreamservergetwebhook) 81 + - [List Webhooks](/docs/api/operations/placestreamserverlistwebhooks) 82 + - [Update Webhook](/docs/api/operations/placestreamserverupdatewebhook) 83 + - [Delete Webhook](/docs/api/operations/placestreamserverdeletewebhook)
+39
js/docs/src/content/docs/features-dev/badges.md
···
··· 1 + --- 2 + title: badges system 3 + description: user badges for chat messages 4 + --- 5 + 6 + ## Overview 7 + 8 + Badges appear next to usernames in chat messages. they're small icons that indicate status (streamer, mod, vip, etc.). There will be max 3 badges shown at once. One of the badges is server-based (e.g. streamer, mod, node staff badge), but the other two can be selected from a pool of cosmetic badges (such as subscription badges, event badges et al.). These cosmetic badges are cryptographically signed by the issuing party, and all the user needs to do is apply them to their chat profile. Note that certain badges may appear/disappear based on the current streamer's chat tktk. 9 + 10 + ## Lexicon schemas 11 + 12 + We have three relevant lexicons. 13 + 14 + 1. **`place.stream.badge.defs`** - badge definitions and view model 15 + 16 + - defines known badge types: `mod`, `streamer`, `vip` 17 + - `badgeView` object: `{badgeType, issuer, recipient, signature?}` 18 + 19 + 2. **`place.stream.badge.issuance`** - record of badge grant 20 + 21 + - stored as atproto record (key: tid) 22 + - issued by streamer or other authorized entity 23 + - example: streamer issues vip badge to a user 24 + 25 + 3. **`place.stream.badge.display`** - user's badge selection 26 + - user-controlled record defining which badges to show 27 + - array of up to 3 `badgeSelection` objects 28 + - first slot server-controlled (mod/streamer/staff), second slot is streamer-specific (vip, subscription), third slot is user-set (event, staff2, node subscription, etc.) 29 + 30 + :::note 31 + This may get changed to be in the user's chat profile? Maybe we could have a "main" chat profile and a streamer-specific profile? 32 + ::: 33 + 34 + ## TODO 35 + 36 + - [ ] implement cryptographic signatures for badge issuance 37 + - [ ] implement badge issuance ui (streamer grants vip badges) 38 + - [ ] implement badge selection ui (users choose which badges to display) 39 + - [ ] add more badge types (subscriber, founder, staff, etc)
+1 -2
js/docs/src/content/docs/guides/start-contributing/styling-quick-reference.md
··· 1 --- 2 title: ZeroCSS Quick Reference 3 - description: 4 - Quick reference for Streamplace ZeroCSS - common patterns and utilities. 5 sidebar: 6 order: 31 7 ---
··· 1 --- 2 title: ZeroCSS Quick Reference 3 + description: Quick reference for Streamplace ZeroCSS - common patterns and utilities. 4 sidebar: 5 order: 31 6 ---
-83
js/docs/src/content/docs/guides/start-streaming/discord-hooks.md
··· 1 - --- 2 - title: Discord Webhooks 3 - description: Configure Discord webhooks for livestream announcements and chat 4 - sidebar: 5 - order: 30 6 - --- 7 - 8 - Streamplace supports Discord webhook integration for receiving livestream 9 - notifications and chat messages. You can create, manage, and configure webhooks 10 - to customize how events are delivered to your Discord channels. 11 - 12 - ## Webhook Events 13 - 14 - You can configure webhooks to listen for specific events. For right now, the 15 - following events are supported: 16 - 17 - - `Chat`: Triggered when a chat message is sent. 18 - - `Livestream`: Triggered when a livestream starts. 19 - 20 - ## Creating a Webhook 21 - 22 - To create a webhook, go to the "Settings" page of the Streamplace web app, then 23 - navigate to the "Webhooks" section. Click on "Create Webhook". The following 24 - fields are required: 25 - 26 - - Name: Webhook URL. For example, 27 - `https://discord.com/api/webhooks/{webhook.id}/{webhook.token}` 28 - - Events: Select the events you want to subscribe to (e.g., `Chat Messages`, 29 - `Livestream Started`). `Livestream Started` is pre-checked by default. 30 - 31 - We'd recommend also filling out these optional fields: 32 - 33 - - Name: A name for the webhook (e.g., "Discord Livestream Notifications") that 34 - you can remember. 35 - - Description: A description of what this webhook is for (e.g., "Sends 36 - livestream start notifications to Discord channel"). 37 - - Prefix: A prefix to add to each message sent by this webhook (e.g., 38 - "[Streamplace] "). Will apply to both Chat and Livestream events! 39 - - Suffix: A suffix to add to each message sent by this webhook (e.g., "is now 40 - live!"). Will apply to both Chat and Livestream events! 41 - - Text replacements: A list of text replacements to apply to chat messages sent 42 - by this webhook. Each replacement consists of a "from" string and a "to" 43 - string. For example, you could replace all instances of "foo" with "bar". 44 - 45 - After filling out the form, click "Create" to save your webhook. You should see 46 - it listed in the "Webhooks" section. 47 - 48 - ## Updating a Webhook 49 - 50 - To update a webhook, go to the "Settings" page of the Streamplace web app, then 51 - navigate to the "Webhooks" section. Find the webhook you want to update and 52 - click on the "pen" icon next to it. This will open the webhook edit form, where 53 - you can modify the fields as needed. After making your changes, click "Update" 54 - to save your changes. 55 - 56 - ## Deleting a Webhook 57 - 58 - To delete a webhook, go to the "Settings" page of the Streamplace web app, then 59 - navigate to the "Webhooks" section. Find the webhook you want to delete and 60 - click on the "trash" icon next to it. A confirmation dialog will appear; click 61 - "Delete" to confirm. The webhook will be removed from the list. 62 - 63 - ## Recommendations 64 - 65 - We'd recommend: 66 - 67 - - Creating separate Discord channels for livestream notifications and chat 68 - messages to keep them organized. 69 - - If you want to have one webhook for both chat and livestream events, you can 70 - create multiple webhooks with the same URL but different event subscriptions 71 - and prefixes/suffixes/replacements. 72 - - Testing your webhook by starting a livestream or sending a chat message to 73 - ensure that notifications are being sent correctly. 74 - 75 - ## API Documentation 76 - 77 - See these endpoint pages: 78 - 79 - - [Create Webhook](/docs/api/operations/placestreamservercreatewebhook) 80 - - [Get Webhook](/docs/api/operations/placestreamservergetwebhook) 81 - - [List Webhooks](/docs/api/operations/placestreamserverlistwebhooks) 82 - - [Update Webhook](/docs/api/operations/placestreamserverupdatewebhook) 83 - - [Delete Webhook](/docs/api/operations/placestreamserverdeletewebhook)
···
-27
js/docs/src/content/docs/guides/start-streaming/embed.md
··· 1 - --- 2 - title: Embedding your livestream 3 - description: How to embed your livestream on your website, blog, etc. 4 - --- 5 - 6 - Streamplace provides an easy way to embed your livestream on any website or 7 - blog. 8 - 9 - You can access the embedded livestream page by putting `/embed` in the URL of 10 - your livestream. For example, if your livestream URL is 11 - `https://stream.place/iame.li`, the embed URL will be 12 - `https://stream.place/embed/iame.li`. 13 - 14 - You can use the following HTML snippet to embed your livestream: 15 - 16 - ```html 17 - <iframe 18 - src="https://stream.place/embed/your-handle" 19 - width="560" 20 - height="315" 21 - frameborder="0" 22 - allowfullscreen 23 - ></iframe> 24 - ``` 25 - 26 - Alternatively, you can use the share sheet located on your livestream page. 27 - Click the "Share" button, and you'll find the embed code ready to copy.
···
+7 -1
js/docs/src/content/docs/guides/start-streaming/obs-multistreaming.md
··· 1 --- 2 - title: OBS Multistreaming with Streamplace 3 description: 4 Configure OBS for multistreaming to Streamplace and other platforms using the 5 obs-multi-rtmp plugin. 6 sidebar: 7 order: 20 8 --- 9 10 This guide explains how to configure Open Broadcaster Software (OBS) for 11 simultaneous streaming to Streamplace and other platforms using the
··· 1 --- 2 + title: OBS Multistreaming to Streamplace 3 description: 4 Configure OBS for multistreaming to Streamplace and other platforms using the 5 obs-multi-rtmp plugin. 6 sidebar: 7 order: 20 8 --- 9 + 10 + :::note 11 + This guide is not about the multistreaming feature. Check 12 + [the multistreaming guide](/docs/features/multistreaming) out for more 13 + information. 14 + ::: 15 16 This guide explains how to configure Open Broadcaster Software (OBS) for 17 simultaneous streaming to Streamplace and other platforms using the
+21 -2
js/docs/src/content/docs/guides/start-streaming/obs.md
··· 58 - Audio Encoder: 59 - For `RTMP`, choose an appropriate AAC encoder. 60 - For `WHIP`, use `ffmpeg_opus`. 61 - Video Encoder: _(Select appropriate encoder, e.g. libx264/nvenc_h264)_ 62 63 #### 2e. Suggested Video Encoder Settings 64 65 - Rate Control: `CBR` 66 - - Keyframe Interval: `1s` 67 - x264 Options: `bframes=0` 68 - - If available, there also may be a 'no bframes' checkbox which should be 69 checked 70 71 ### 3. Announce your stream 72 73 1. Once you're live, go back to the live dashboard. ··· 85 86 2. [**Aitum Multistream Plugin**](https://aitum.tv/products/multi) 87 88 ## Best Practices 89 90 - Test your stream settings before going live ··· 96 ## Additional Resources 97 98 - [OBS Official Documentation](https://obsproject.com/docs/)
··· 58 - Audio Encoder: 59 - For `RTMP`, choose an appropriate AAC encoder. 60 - For `WHIP`, use `ffmpeg_opus`. 61 + - If you are using a server that supports the SRT protocol (e.g. 62 + multistreaming via NGINX) please check below for an example config. 63 - Video Encoder: _(Select appropriate encoder, e.g. libx264/nvenc_h264)_ 64 65 #### 2e. Suggested Video Encoder Settings 66 67 + - Video Encoder: x264/h264 (**must** be an x/h.264 encoder) 68 - Rate Control: `CBR` 69 + - Keyframe Interval: `1s` (or anything less than once every ~7s) 70 + - This is _one keyframe per second_ 71 + - In some situations (e.g. 'keyframe interval (**frames**)'), this should be 72 + set to your FPS. 73 - x264 Options: `bframes=0` 74 + - If available, there also may be a 'bframes' checkbox which should **NOT** be 75 checked 76 77 + :::caution 78 + These last two options are very important! Your viewers' experience may be choppy or otherwise subpar if you don't have them correct. 79 + ::: 80 + 81 ### 3. Announce your stream 82 83 1. Once you're live, go back to the live dashboard. ··· 95 96 2. [**Aitum Multistream Plugin**](https://aitum.tv/products/multi) 97 98 + Alternatively, you can 99 + [multistream through Streamplace itself.](/docs/features/multistreaming) 100 + 101 ## Best Practices 102 103 - Test your stream settings before going live ··· 109 ## Additional Resources 110 111 - [OBS Official Documentation](https://obsproject.com/docs/) 112 + 113 + ### Example Settings 114 + 115 + ![SRT settings in OBS.](srt.png "OBS SRT Settings") 116 + 117 + > Multistreaming via a server that supports the SRT protocol
+73
js/docs/src/content/docs/guides/start-streaming/quick-start.md
···
··· 1 + --- 2 + title: Quick Start 3 + description: Get up and streaming on Streamplace quickly. 4 + sidebar: 5 + order: 1 6 + --- 7 + 8 + This guide gets you from zero to streaming. If you get stuck, check out the full [OBS setup guide](/docs/guides/start-streaming/obs). 9 + 10 + :::tip 11 + You will want to check out our [community guidelines](https://blog.stream.place/3mcqwibo4ks2w) first for guidance on what you can and cannot do on Streamplace. 12 + ::: 13 + 14 + ## So, what is Streamplace? 15 + 16 + Streamplace is a video streaming service built on top of the AT Protocol (Authenticated Transfer Protocol), the same protocol Bluesky is built on. 17 + 18 + ## Step 1: Create your account 19 + 20 + 1. Go to [stream.place](https://stream.place) 21 + 2. Click "Sign in" in the top right. 22 + 3. Use your Atmosphere credentials to log in (ex. your Bluesky handle) 23 + - You'll need to use your actual password here - we're using OAuth so you enter your password on your PDS. We do not receive your password at all. 24 + 4. You're done! Your stream profile is live at `stream.place/your-handle` 25 + 26 + ## Step 2: Get your stream key 27 + 28 + 1. Click **Live Dashboard** (or go to [stream.place/dashboard](https://stream.place/dashboard)) 29 + 2. Click **Stream from OBS** 30 + 3. Click **Generate Stream Key** 31 + 4. Your key is copied to clipboard automatically 32 + 33 + Keep this key private. It's like a password, but for your stream. 34 + 35 + ## Step 3: Configure OBS 36 + 37 + Open OBS and go to **Settings โ†’ Stream**: 38 + 39 + - **Service**: `Custom...` 40 + - **Server**: `rtmps://stream.place:1935/live` 41 + - **Stream Key**: Paste what you copied in Step 2 42 + 43 + Then go to **Settings โ†’ Output โ†’ Streaming**: 44 + 45 + - **Video Encoder**: `libx264` (or `NVIDIA NVENC H.264` if you have an NVIDIA GPU) 46 + - **Rate Control**: `CBR` 47 + - **Bitrate**: `6000` Kbps (adjust down if you drop frames) 48 + - **Keyframe Interval**: `1` 49 + - **x264 Options**: `bframes=0`. If there's a 'bframes' option, you'll want to have that at '0' or unchecked. 50 + 51 + :::caution 52 + These last two options are very important! Your viewers' experience may be choppy or otherwise subpar if you don't have them correct. 53 + ::: 54 + 55 + ## Step 4: Go live 56 + 57 + 1. In OBS, click **Start Streaming** 58 + 2. Go back to the Live Dashboard at stream.place 59 + 3. Fill in your stream title and optionally pick a thumbnail8 60 + 4. If needed, turn on content warnings. ("Metadata" tab in Stream Settings) 61 + 5. Click **Announce Livestream** 62 + 6. Your stream is now live and visible to the world! 63 + 64 + ## Next steps 65 + 66 + - **Customize your chat**: Change your name color in Settings > Account 67 + - **Stream to other platforms too**: Set your Twitch/YouTube URLs in Settings > Multistream Targets to push your stream there automatically. See the [Multistreaming guide](/docs/features/multistreaming) for more information 68 + - **Improve stream quality**: See the [OBS guide](/docs/guides/start-streaming/obs) for encoder settings and troubleshooting 69 + - **Join the Discord!**: If you need any help, or just want to chat, check out our discord at https://discord.stream.place. 70 + 71 + ### Credits 72 + 73 + A portion of this documentation was taken from [ndroo.tv](https://bsky.app/profile/ndroo.tv)'s excellent [guide on Streamplace](https://ndroo.tv/streamplace.html#2-configuring-your-account).
js/docs/src/content/docs/guides/start-streaming/srt.png

This is a binary file and will not be displayed.

+2 -32
js/docs/src/content/docs/index.mdx
··· 2 title: Welcome to Streamplace! 3 description: Begin your development journey with the Streamplace documentation. 4 template: doc 5 - hero: 6 - tagline: Solve live video for your project with Streamplace. 7 - image: 8 - file: ../../assets/cube.png 9 - alt: Streamplace logo. A pink 3d box viewed from a top corner. 10 - actions: 11 - - text: Get Started 12 - link: /docs/guides/start-streaming/obs 13 - icon: right-arrow 14 - - text: Visit Streamplace 15 - link: / 16 - icon: external 17 - variant: minimal 18 --- 19 20 - import { Card, CardGrid } from "@astrojs/starlight/components"; 21 - 22 - ## Next Steps 23 24 - <CardGrid> 25 - <Card title="Read the Docs" icon="open-book"> 26 - Learn how to start streaming with 27 - [Streamplace](/docs/guides/start-streaming/obs). 28 - </Card> 29 - <Card title="Install Streamplace" icon="download"> 30 - [Run your own Streamplace 31 - node](/docs/guides/installing/installing-streamplace). 32 - </Card> 33 - <Card title="API Reference" icon="document"> 34 - Explore the [Lexicon API reference](/docs/lex-reference/place-stream-defs). 35 - </Card> 36 - <Card title="Developer Setup" icon="setting"> 37 - Set up your [development environment](/docs/guides/streamplace-dev-setup). 38 - </Card> 39 - </CardGrid>
··· 2 title: Welcome to Streamplace! 3 description: Begin your development journey with the Streamplace documentation. 4 template: doc 5 --- 6 7 + import HelpDesk from "../../components/HelpDesk.astro"; 8 9 + <HelpDesk />
+108
js/docs/src/content/docs/lex-reference/badge/place-stream-badge-defs.md
···
··· 1 + --- 2 + title: place.stream.badge.defs 3 + description: Reference for the place.stream.badge.defs lexicon 4 + --- 5 + 6 + **Lexicon Version:** 1 7 + 8 + ## Definitions 9 + 10 + <a name="badgeview"></a> 11 + 12 + ### `badgeView` 13 + 14 + **Type:** `object` 15 + 16 + View of a badge record, with fields resolved for display. If the DID in issuer is not the current streamplace node, the signature field shall be required. 17 + 18 + **Properties:** 19 + 20 + | Name | Type | Req'd | Description | Constraints | 21 + | ----------- | -------- | ----- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------- | 22 + | `badgeType` | `string` | โœ… | | Known Values: `place.stream.badge.defs#mod`, `place.stream.badge.defs#streamer` | 23 + | `issuer` | `string` | โœ… | DID of the badge issuer. | Format: `did` | 24 + | `recipient` | `string` | โœ… | DID of the badge recipient. | Format: `did` | 25 + | `signature` | `string` | โŒ | TODO: Cryptographic signature of the badge (of a place.stream.key). | | 26 + 27 + --- 28 + 29 + <a name="mod"></a> 30 + 31 + ### `mod` 32 + 33 + **Type:** `token` 34 + 35 + This user is a moderator. Displayed with a sword icon. 36 + 37 + --- 38 + 39 + <a name="streamer"></a> 40 + 41 + ### `streamer` 42 + 43 + **Type:** `token` 44 + 45 + This user is the streamer. Displayed with a star icon. 46 + 47 + --- 48 + 49 + <a name="vip"></a> 50 + 51 + ### `vip` 52 + 53 + **Type:** `token` 54 + 55 + This user is a very important person. 56 + 57 + --- 58 + 59 + ## Lexicon Source 60 + 61 + ```json 62 + { 63 + "lexicon": 1, 64 + "id": "place.stream.badge.defs", 65 + "defs": { 66 + "badgeView": { 67 + "type": "object", 68 + "required": ["badgeType", "issuer", "recipient"], 69 + "description": "View of a badge record, with fields resolved for display. If the DID in issuer is not the current streamplace node, the signature field shall be required.", 70 + "properties": { 71 + "badgeType": { 72 + "type": "string", 73 + "knownValues": [ 74 + "place.stream.badge.defs#mod", 75 + "place.stream.badge.defs#streamer" 76 + ] 77 + }, 78 + "issuer": { 79 + "type": "string", 80 + "format": "did", 81 + "description": "DID of the badge issuer." 82 + }, 83 + "recipient": { 84 + "type": "string", 85 + "format": "did", 86 + "description": "DID of the badge recipient." 87 + }, 88 + "signature": { 89 + "type": "string", 90 + "description": "TODO: Cryptographic signature of the badge (of a place.stream.key)." 91 + } 92 + } 93 + }, 94 + "mod": { 95 + "type": "token", 96 + "description": "This user is a moderator. Displayed with a sword icon." 97 + }, 98 + "streamer": { 99 + "type": "token", 100 + "description": "This user is the streamer. Displayed with a star icon." 101 + }, 102 + "vip": { 103 + "type": "token", 104 + "description": "This user is a very important person." 105 + } 106 + } 107 + } 108 + ```
+90
js/docs/src/content/docs/lex-reference/badge/place-stream-badge-display.md
···
··· 1 + --- 2 + title: place.stream.badge.display 3 + description: Reference for the place.stream.badge.display lexicon 4 + --- 5 + 6 + **Lexicon Version:** 1 7 + 8 + ## Definitions 9 + 10 + <a name="main"></a> 11 + 12 + ### `main` 13 + 14 + **Type:** `record` 15 + 16 + Record issuing a badge to a user. 17 + 18 + **Record Properties:** 19 + 20 + | Name | Type | Req'd | Description | Constraints | 21 + | -------- | --------------------------------------------- | ----- | ----------------------------------------------------------------------------------------------------------------------- | ------------ | 22 + | `badges` | Array of [`#badgeSelection`](#badgeselection) | โœ… | Up to 3 badge tokens to display with the message. First badge is server-controlled, remaining badges are user-settable. | Max Items: 3 | 23 + 24 + --- 25 + 26 + <a name="badgeselection"></a> 27 + 28 + ### `badgeSelection` 29 + 30 + **Type:** `object` 31 + 32 + A badge selected for display. May be a full badgeView from the server, or a token representing a badge type that the client can look up for display info. 33 + 34 + **Properties:** 35 + 36 + | Name | Type | Req'd | Description | Constraints | 37 + | ----------- | -------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | 38 + | `badgeType` | `string` | โœ… | | Known Values: `place.stream.badge.defs#mod`, `place.stream.badge.defs#vip` | 39 + | `issuance` | `string` | โŒ | URI of the badge issuance record (place.stream.badge.issuance) that represents this badge. Required if badgeType is not recognized. | Format: `at-uri` | 40 + 41 + --- 42 + 43 + ## Lexicon Source 44 + 45 + ```json 46 + { 47 + "lexicon": 1, 48 + "id": "place.stream.badge.display", 49 + "defs": { 50 + "main": { 51 + "type": "record", 52 + "description": "Record issuing a badge to a user.", 53 + "record": { 54 + "type": "object", 55 + "required": ["badges"], 56 + "properties": { 57 + "badges": { 58 + "type": "array", 59 + "description": "Up to 3 badge tokens to display with the message. First badge is server-controlled, remaining badges are user-settable.", 60 + "maxLength": 3, 61 + "items": { 62 + "type": "ref", 63 + "ref": "#badgeSelection" 64 + } 65 + } 66 + } 67 + } 68 + }, 69 + "badgeSelection": { 70 + "type": "object", 71 + "description": "A badge selected for display. May be a full badgeView from the server, or a token representing a badge type that the client can look up for display info.", 72 + "required": ["badgeType"], 73 + "properties": { 74 + "badgeType": { 75 + "type": "string", 76 + "knownValues": [ 77 + "place.stream.badge.defs#mod", 78 + "place.stream.badge.defs#vip" 79 + ] 80 + }, 81 + "issuance": { 82 + "type": "string", 83 + "format": "at-uri", 84 + "description": "URI of the badge issuance record (place.stream.badge.issuance) that represents this badge. Required if badgeType is not recognized." 85 + } 86 + } 87 + } 88 + } 89 + } 90 + ```
+63
js/docs/src/content/docs/lex-reference/badge/place-stream-badge-issuance.md
···
··· 1 + --- 2 + title: place.stream.badge.issuance 3 + description: Reference for the place.stream.badge.issuance lexicon 4 + --- 5 + 6 + **Lexicon Version:** 1 7 + 8 + ## Definitions 9 + 10 + <a name="main"></a> 11 + 12 + ### `main` 13 + 14 + **Type:** `record` 15 + 16 + Record issuing a badge to a user. 17 + 18 + **Record Key:** `tid` 19 + 20 + **Record Properties:** 21 + 22 + | Name | Type | Req'd | Description | Constraints | 23 + | ----------- | -------- | ----- | ------------------------------------------------------------------- | ------------------------------------------- | 24 + | `badgeType` | `string` | โœ… | | Known Values: `place.stream.badge.defs#vip` | 25 + | `recipient` | `string` | โœ… | DID of the badge recipient. | Format: `did` | 26 + | `signature` | `string` | โœ… | TODO: Cryptographic signature of the badge (of a place.stream.key). | | 27 + 28 + --- 29 + 30 + ## Lexicon Source 31 + 32 + ```json 33 + { 34 + "lexicon": 1, 35 + "id": "place.stream.badge.issuance", 36 + "defs": { 37 + "main": { 38 + "type": "record", 39 + "key": "tid", 40 + "description": "Record issuing a badge to a user.", 41 + "record": { 42 + "type": "object", 43 + "required": ["badgeType", "recipient", "signature"], 44 + "properties": { 45 + "badgeType": { 46 + "type": "string", 47 + "knownValues": ["place.stream.badge.defs#vip"] 48 + }, 49 + "recipient": { 50 + "type": "string", 51 + "format": "did", 52 + "description": "DID of the badge recipient." 53 + }, 54 + "signature": { 55 + "type": "string", 56 + "description": "TODO: Cryptographic signature of the badge (of a place.stream.key)." 57 + } 58 + } 59 + } 60 + } 61 + } 62 + } 63 + ```
+2 -1
js/docs/src/content/docs/lex-reference/branding/place-stream-branding-getblob.md
··· 28 - **Description:** Raw blob data with appropriate content-type 29 - **Schema:** 30 31 - _Schema not defined._ **Possible Errors:** 32 33 - `BrandingNotFound`: The requested branding asset does not exist 34
··· 28 - **Description:** Raw blob data with appropriate content-type 29 - **Schema:** 30 31 + _Schema not defined._ 32 + **Possible Errors:** 33 34 - `BrandingNotFound`: The requested branding asset does not exist 35
+1 -2
js/docs/src/content/docs/lex-reference/broadcast/place-stream-broadcast-origin.md
··· 13 14 **Type:** `record` 15 16 - Record indicating a livestream is published and available for replication at a 17 - given address. By convention, the record key is streamer::server 18 19 **Record Key:** `any` 20
··· 13 14 **Type:** `record` 15 16 + Record indicating a livestream is published and available for replication at a given address. By convention, the record key is streamer::server 17 18 **Record Key:** `any` 19
+1 -2
js/docs/src/content/docs/lex-reference/broadcast/place-stream-broadcast-syndication.md
··· 13 14 **Type:** `record` 15 16 - Record created by a Streamplace broadcaster to indicate that they will be 17 - replicating a livestream. NYI 18 19 **Record Key:** `tid` 20
··· 13 14 **Type:** `record` 15 16 + Record created by a Streamplace broadcaster to indicate that they will be replicating a livestream. NYI 17 18 **Record Key:** `tid` 19
+20 -10
js/docs/src/content/docs/lex-reference/chat/place-stream-chat-defs.md
··· 15 16 **Properties:** 17 18 - | Name | Type | Req'd | Description | Constraints | 19 - | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----- | -------------------------------------------------------------------------------------- | ------------------ | 20 - | `uri` | `string` | โœ… | | Format: `at-uri` | 21 - | `cid` | `string` | โœ… | | Format: `cid` | 22 - | `author` | [`app.bsky.actor.defs#profileViewBasic`](https://github.com/bluesky-social/atproto/tree/main/lexicons/app/bsky/actor/defs.json#profileViewBasic) | โœ… | | | 23 - | `record` | `unknown` | โœ… | | | 24 - | `indexedAt` | `string` | โœ… | | Format: `datetime` | 25 - | `chatProfile` | [`place.stream.chat.profile`](/lex-reference/place-stream-chat-profile) | โŒ | | | 26 - | `replyTo` | Union of:<br/>&nbsp;&nbsp;[`#messageView`](#messageview) | โŒ | | | 27 - | `deleted` | `boolean` | โŒ | If true, this message has been deleted or labeled and should be cleared from the cache | | 28 29 --- 30 ··· 69 "deleted": { 70 "type": "boolean", 71 "description": "If true, this message has been deleted or labeled and should be cleared from the cache" 72 } 73 } 74 }
··· 15 16 **Properties:** 17 18 + | Name | Type | Req'd | Description | Constraints | 19 + | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | 20 + | `uri` | `string` | โœ… | | Format: `at-uri` | 21 + | `cid` | `string` | โœ… | | Format: `cid` | 22 + | `author` | [`app.bsky.actor.defs#profileViewBasic`](https://github.com/bluesky-social/atproto/tree/main/lexicons/app/bsky/actor/defs.json#profileViewBasic) | โœ… | | | 23 + | `record` | `unknown` | โœ… | | | 24 + | `indexedAt` | `string` | โœ… | | Format: `datetime` | 25 + | `chatProfile` | [`place.stream.chat.profile`](/lex-reference/place-stream-chat-profile) | โŒ | | | 26 + | `replyTo` | Union of:<br/>&nbsp;&nbsp;[`#messageView`](#messageview) | โŒ | | | 27 + | `deleted` | `boolean` | โŒ | If true, this message has been deleted or labeled and should be cleared from the cache | | 28 + | `badges` | Array of [`place.stream.badge.defs#badgeView`](/lex-reference/place-stream-badge-defs#badgeview) | โŒ | Up to 3 badge tokens to display with the message. First badge is server-controlled, remaining badges are user-settable. Tokens are looked up in badges.json for display info. | Max Items: 3 | 29 30 --- 31 ··· 70 "deleted": { 71 "type": "boolean", 72 "description": "If true, this message has been deleted or labeled and should be cleared from the cache" 73 + }, 74 + "badges": { 75 + "type": "array", 76 + "description": "Up to 3 badge tokens to display with the message. First badge is server-controlled, remaining badges are user-settable. Tokens are looked up in badges.json for display info.", 77 + "maxLength": 3, 78 + "items": { 79 + "type": "ref", 80 + "ref": "place.stream.badge.defs#badgeView" 81 + } 82 } 83 } 84 }
+99
js/docs/src/content/docs/lex-reference/live/place-stream-live-denyteleport.md
···
··· 1 + --- 2 + title: place.stream.live.denyTeleport 3 + description: Reference for the place.stream.live.denyTeleport lexicon 4 + --- 5 + 6 + **Lexicon Version:** 1 7 + 8 + ## Definitions 9 + 10 + <a name="main"></a> 11 + 12 + ### `main` 13 + 14 + **Type:** `procedure` 15 + 16 + Deny an incoming teleport request. 17 + 18 + **Parameters:** _(None defined)_ 19 + 20 + **Input:** 21 + 22 + - **Encoding:** `application/json` 23 + - **Schema:** 24 + 25 + **Schema Type:** `object` 26 + 27 + | Name | Type | Req'd | Description | Constraints | 28 + | ----- | -------- | ----- | --------------------------------------- | ---------------- | 29 + | `uri` | `string` | โœ… | The URI of the teleport record to deny. | Format: `at-uri` | 30 + 31 + **Output:** 32 + 33 + - **Encoding:** `application/json` 34 + - **Schema:** 35 + 36 + **Schema Type:** `object` 37 + 38 + | Name | Type | Req'd | Description | Constraints | 39 + | --------- | --------- | ----- | --------------------------------------------- | ----------- | 40 + | `success` | `boolean` | โœ… | Whether the teleport was successfully denied. | | 41 + 42 + **Possible Errors:** 43 + 44 + - `TeleportNotFound`: The specified teleport was not found. 45 + - `Unauthorized`: The authenticated user is not the target of this teleport. 46 + 47 + --- 48 + 49 + ## Lexicon Source 50 + 51 + ```json 52 + { 53 + "lexicon": 1, 54 + "id": "place.stream.live.denyTeleport", 55 + "defs": { 56 + "main": { 57 + "type": "procedure", 58 + "description": "Deny an incoming teleport request.", 59 + "input": { 60 + "encoding": "application/json", 61 + "schema": { 62 + "type": "object", 63 + "required": ["uri"], 64 + "properties": { 65 + "uri": { 66 + "type": "string", 67 + "format": "at-uri", 68 + "description": "The URI of the teleport record to deny." 69 + } 70 + } 71 + } 72 + }, 73 + "output": { 74 + "encoding": "application/json", 75 + "schema": { 76 + "type": "object", 77 + "required": ["success"], 78 + "properties": { 79 + "success": { 80 + "type": "boolean", 81 + "description": "Whether the teleport was successfully denied." 82 + } 83 + } 84 + } 85 + }, 86 + "errors": [ 87 + { 88 + "name": "TeleportNotFound", 89 + "description": "The specified teleport was not found." 90 + }, 91 + { 92 + "name": "Unauthorized", 93 + "description": "The authenticated user is not the target of this teleport." 94 + } 95 + ] 96 + } 97 + } 98 + } 99 + ```
+2 -1
js/docs/src/content/docs/lex-reference/live/place-stream-live-getprofilecard.md
··· 26 - **Encoding:** `*/*` 27 - **Schema:** 28 29 - _Schema not defined._ **Possible Errors:** 30 31 - `RepoNotFound` 32
··· 26 - **Encoding:** `*/*` 27 - **Schema:** 28 29 + _Schema not defined._ 30 + **Possible Errors:** 31 32 - `RepoNotFound` 33
+1 -2
js/docs/src/content/docs/lex-reference/live/place-stream-live-searchactorstypeahead.md
··· 13 14 **Type:** `query` 15 16 - Find actor suggestions for a prefix search term. Expected use is for 17 - auto-completion during text field entry. 18 19 **Parameters:** 20
··· 13 14 **Type:** `query` 15 16 + Find actor suggestions for a prefix search term. Expected use is for auto-completion during text field entry. 17 18 **Parameters:** 19
+66
js/docs/src/content/docs/lex-reference/live/place-stream-live-teleport.md
···
··· 1 + --- 2 + title: place.stream.live.teleport 3 + description: Reference for the place.stream.live.teleport lexicon 4 + --- 5 + 6 + **Lexicon Version:** 1 7 + 8 + ## Definitions 9 + 10 + <a name="main"></a> 11 + 12 + ### `main` 13 + 14 + **Type:** `record` 15 + 16 + Record defining a 'teleport', that is active during a certain time. 17 + 18 + **Record Key:** `tid` 19 + 20 + **Record Properties:** 21 + 22 + | Name | Type | Req'd | Description | Constraints | 23 + | ----------------- | --------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | 24 + | `streamer` | `string` | โœ… | The DID of the streamer to teleport to. | Format: `did` | 25 + | `startsAt` | `string` | โœ… | The time the teleport becomes active. | Format: `datetime` | 26 + | `durationSeconds` | `integer` | โŒ | The time limit in seconds for the teleport. If not set, the teleport is permanent. Must be at least 60 seconds, and no more than 32,400 seconds (9 hours). | Min: 60<br/>Max: 32400 | 27 + 28 + --- 29 + 30 + ## Lexicon Source 31 + 32 + ```json 33 + { 34 + "lexicon": 1, 35 + "id": "place.stream.live.teleport", 36 + "defs": { 37 + "main": { 38 + "type": "record", 39 + "key": "tid", 40 + "description": "Record defining a 'teleport', that is active during a certain time.", 41 + "record": { 42 + "type": "object", 43 + "required": ["streamer", "startsAt"], 44 + "properties": { 45 + "streamer": { 46 + "type": "string", 47 + "format": "did", 48 + "description": "The DID of the streamer to teleport to." 49 + }, 50 + "startsAt": { 51 + "type": "string", 52 + "format": "datetime", 53 + "description": "The time the teleport becomes active." 54 + }, 55 + "durationSeconds": { 56 + "type": "integer", 57 + "description": "The time limit in seconds for the teleport. If not set, the teleport is permanent. Must be at least 60 seconds, and no more than 32,400 seconds (9 hours).", 58 + "minimum": 60, 59 + "maximum": 32400 60 + } 61 + } 62 + } 63 + } 64 + } 65 + } 66 + ```
-133
js/docs/src/content/docs/lex-reference/livestream/place-stream-livestream-update.md
··· 1 - --- 2 - title: place.stream.livestream.update 3 - description: Reference for the place.stream.livestream.update lexicon 4 - --- 5 - 6 - **Lexicon Version:** 1 7 - 8 - ## Definitions 9 - 10 - <a name="main"></a> 11 - 12 - ### `main` 13 - 14 - **Type:** `procedure` 15 - 16 - Update livestream metadata on behalf of a streamer. Requires 'livestream.manage' 17 - permission. Updates a place.stream.livestream record in the streamer's 18 - repository. 19 - 20 - **Parameters:** _(None defined)_ 21 - 22 - **Input:** 23 - 24 - - **Encoding:** `application/json` 25 - - **Schema:** 26 - 27 - **Schema Type:** `object` 28 - 29 - | Name | Type | Req'd | Description | Constraints | 30 - | --------------- | -------- | ----- | ---------------------------------------------- | --------------------------------------- | 31 - | `streamer` | `string` | โœ… | The DID of the streamer. | Format: `did` | 32 - | `livestreamUri` | `string` | โœ… | The AT-URI of the livestream record to update. | Format: `at-uri` | 33 - | `title` | `string` | โŒ | New title for the livestream. | Max Length: 1400<br/>Max Graphemes: 140 | 34 - 35 - **Output:** 36 - 37 - - **Encoding:** `application/json` 38 - - **Schema:** 39 - 40 - **Schema Type:** `object` 41 - 42 - | Name | Type | Req'd | Description | Constraints | 43 - | ----- | -------- | ----- | -------------------------------------------- | ---------------- | 44 - | `uri` | `string` | โœ… | The AT-URI of the updated livestream record. | Format: `at-uri` | 45 - | `cid` | `string` | โœ… | The CID of the updated livestream record. | Format: `cid` | 46 - 47 - **Possible Errors:** 48 - 49 - - `Unauthorized`: The request lacks valid authentication credentials. 50 - - `Forbidden`: The caller does not have permission to update livestream metadata 51 - for this streamer. 52 - - `SessionNotFound`: The streamer's OAuth session could not be found or is 53 - invalid. 54 - - `RecordNotFound`: The specified livestream record does not exist. 55 - 56 - --- 57 - 58 - ## Lexicon Source 59 - 60 - ```json 61 - { 62 - "lexicon": 1, 63 - "id": "place.stream.livestream.update", 64 - "defs": { 65 - "main": { 66 - "type": "procedure", 67 - "description": "Update livestream metadata on behalf of a streamer. Requires 'livestream.manage' permission. Updates a place.stream.livestream record in the streamer's repository.", 68 - "input": { 69 - "encoding": "application/json", 70 - "schema": { 71 - "type": "object", 72 - "required": ["streamer", "livestreamUri"], 73 - "properties": { 74 - "streamer": { 75 - "type": "string", 76 - "format": "did", 77 - "description": "The DID of the streamer." 78 - }, 79 - "livestreamUri": { 80 - "type": "string", 81 - "format": "at-uri", 82 - "description": "The AT-URI of the livestream record to update." 83 - }, 84 - "title": { 85 - "type": "string", 86 - "maxLength": 1400, 87 - "maxGraphemes": 140, 88 - "description": "New title for the livestream." 89 - } 90 - } 91 - } 92 - }, 93 - "output": { 94 - "encoding": "application/json", 95 - "schema": { 96 - "type": "object", 97 - "required": ["uri", "cid"], 98 - "properties": { 99 - "uri": { 100 - "type": "string", 101 - "format": "at-uri", 102 - "description": "The AT-URI of the updated livestream record." 103 - }, 104 - "cid": { 105 - "type": "string", 106 - "format": "cid", 107 - "description": "The CID of the updated livestream record." 108 - } 109 - } 110 - } 111 - }, 112 - "errors": [ 113 - { 114 - "name": "Unauthorized", 115 - "description": "The request lacks valid authentication credentials." 116 - }, 117 - { 118 - "name": "Forbidden", 119 - "description": "The caller does not have permission to update livestream metadata for this streamer." 120 - }, 121 - { 122 - "name": "SessionNotFound", 123 - "description": "The streamer's OAuth session could not be found or is invalid." 124 - }, 125 - { 126 - "name": "RecordNotFound", 127 - "description": "The specified livestream record does not exist." 128 - } 129 - ] 130 - } 131 - } 132 - } 133 - ```
···
+1 -2
js/docs/src/content/docs/lex-reference/metadata/place-stream-metadata-configuration.md
··· 13 14 **Type:** `record` 15 16 - Default metadata record for livestream including content warnings, rights, and 17 - distribution policy 18 19 **Record Key:** `literal:self` 20
··· 13 14 **Type:** `record` 15 16 + Default metadata record for livestream including content warnings, rights, and distribution policy 17 18 **Record Key:** `literal:self` 19
+8 -19
js/docs/src/content/docs/lex-reference/metadata/place-stream-metadata-contentrights.md
··· 33 34 **Type:** `token` 35 36 - All rights reserved to the creator โ€” others cannot use, modify, or share without 37 - explicit authorization. 38 39 --- 40 ··· 44 45 **Type:** `token` 46 47 - Public domain dedication. You waive all copyright and related rights where 48 - possible. Others may copy, modify, distribute, or perform your work for any 49 - purpose without attribution. 50 51 --- 52 ··· 56 57 **Type:** `token` 58 59 - Attribution required. Others may copy, distribute, remix, and build upon your 60 - work, even commercially, if they credit you. 61 62 --- 63 ··· 67 68 **Type:** `token` 69 70 - Attribution + share-alike. Others may adapt and build upon your work, even 71 - commercially, if they credit you and license their new creations under identical 72 - terms. 73 74 --- 75 ··· 79 80 **Type:** `token` 81 82 - Attribution + non-commercial. Others may adapt and build upon your work for 83 - non-commercial purposes only, and must credit you. 84 85 --- 86 ··· 90 91 **Type:** `token` 92 93 - Attribution + non-commercial + share-alike. Others may adapt and build upon your 94 - work for non-commercial purposes only, must credit you, and must license their 95 - new creations under identical terms. 96 97 --- 98 ··· 102 103 **Type:** `token` 104 105 - Attribution + no derivatives. Others may reuse your work, even commercially, but 106 - it must remain unchanged and you must be credited. 107 108 --- 109 ··· 113 114 **Type:** `token` 115 116 - Attribution + non-commercial + no derivatives. Others may download and share 117 - your work with credit, but cannot change it or use it commercially. 118 119 --- 120
··· 33 34 **Type:** `token` 35 36 + All rights reserved to the creator โ€” others cannot use, modify, or share without explicit authorization. 37 38 --- 39 ··· 43 44 **Type:** `token` 45 46 + Public domain dedication. You waive all copyright and related rights where possible. Others may copy, modify, distribute, or perform your work for any purpose without attribution. 47 48 --- 49 ··· 53 54 **Type:** `token` 55 56 + Attribution required. Others may copy, distribute, remix, and build upon your work, even commercially, if they credit you. 57 58 --- 59 ··· 63 64 **Type:** `token` 65 66 + Attribution + share-alike. Others may adapt and build upon your work, even commercially, if they credit you and license their new creations under identical terms. 67 68 --- 69 ··· 73 74 **Type:** `token` 75 76 + Attribution + non-commercial. Others may adapt and build upon your work for non-commercial purposes only, and must credit you. 77 78 --- 79 ··· 83 84 **Type:** `token` 85 86 + Attribution + non-commercial + share-alike. Others may adapt and build upon your work for non-commercial purposes only, must credit you, and must license their new creations under identical terms. 87 88 --- 89 ··· 93 94 **Type:** `token` 95 96 + Attribution + no derivatives. Others may reuse your work, even commercially, but it must remain unchanged and you must be credited. 97 98 --- 99 ··· 103 104 **Type:** `token` 105 106 + Attribution + non-commercial + no derivatives. Others may download and share your work with credit, but cannot change it or use it commercially. 107 108 --- 109
+8 -18
js/docs/src/content/docs/lex-reference/metadata/place-stream-metadata-contentwarnings.md
··· 29 30 **Type:** `token` 31 32 - The content could be perceived as offensive due to the discussion or display of 33 - death. 34 35 --- 36 ··· 40 41 **Type:** `token` 42 43 - The content contains a portrayal of the use or abuse of mind altering 44 - substances. 45 46 --- 47 ··· 51 52 **Type:** `token` 53 54 - The content contains violent actions of a fantasy nature, involving human or 55 - non-human characters in situations easily distinguishable from real life. 56 57 --- 58 ··· 62 63 **Type:** `token` 64 65 - The content contains flashing lights that could be harmful to viewers with 66 - seizure disorders such as photosensitive epilepsy. 67 68 --- 69 ··· 93 94 **Type:** `token` 95 96 - The content contains information that can be used to identify a particular 97 - individual, such as a name, phone number, email address, physical address, or IP 98 - address. 99 100 --- 101 ··· 105 106 **Type:** `token` 107 108 - The content could be perceived as offensive due to the discussion or display of 109 - sexuality. 110 111 --- 112 ··· 116 117 **Type:** `token` 118 119 - The content could be perceived as distressing due to the discussion or display 120 - of suffering or triggering topics, including suicide, eating disorders or self 121 - harm. 122 123 --- 124 ··· 128 129 **Type:** `token` 130 131 - The content could be perceived as offensive due to the discussion or display of 132 - violence. 133 134 --- 135
··· 29 30 **Type:** `token` 31 32 + The content could be perceived as offensive due to the discussion or display of death. 33 34 --- 35 ··· 39 40 **Type:** `token` 41 42 + The content contains a portrayal of the use or abuse of mind altering substances. 43 44 --- 45 ··· 49 50 **Type:** `token` 51 52 + The content contains violent actions of a fantasy nature, involving human or non-human characters in situations easily distinguishable from real life. 53 54 --- 55 ··· 59 60 **Type:** `token` 61 62 + The content contains flashing lights that could be harmful to viewers with seizure disorders such as photosensitive epilepsy. 63 64 --- 65 ··· 89 90 **Type:** `token` 91 92 + The content contains information that can be used to identify a particular individual, such as a name, phone number, email address, physical address, or IP address. 93 94 --- 95 ··· 99 100 **Type:** `token` 101 102 + The content could be perceived as offensive due to the discussion or display of sexuality. 103 104 --- 105 ··· 109 110 **Type:** `token` 111 112 + The content could be perceived as distressing due to the discussion or display of suffering or triggering topics, including suicide, eating disorders or self harm. 113 114 --- 115 ··· 119 120 **Type:** `token` 121 122 + The content could be perceived as offensive due to the discussion or display of violence. 123 124 --- 125
+3 -6
js/docs/src/content/docs/lex-reference/moderation/place-stream-moderation-createblock.md
··· 13 14 **Type:** `procedure` 15 16 - Create a block (ban) on behalf of a streamer. Requires 'ban' permission. Creates 17 - an app.bsky.graph.block record in the streamer's repository. 18 19 **Parameters:** _(None defined)_ 20 ··· 46 **Possible Errors:** 47 48 - `Unauthorized`: The request lacks valid authentication credentials. 49 - - `Forbidden`: The caller does not have permission to create blocks for this 50 - streamer. 51 - - `SessionNotFound`: The streamer's OAuth session could not be found or is 52 - invalid. 53 54 --- 55
··· 13 14 **Type:** `procedure` 15 16 + Create a block (ban) on behalf of a streamer. Requires 'ban' permission. Creates an app.bsky.graph.block record in the streamer's repository. 17 18 **Parameters:** _(None defined)_ 19 ··· 45 **Possible Errors:** 46 47 - `Unauthorized`: The request lacks valid authentication credentials. 48 + - `Forbidden`: The caller does not have permission to create blocks for this streamer. 49 + - `SessionNotFound`: The streamer's OAuth session could not be found or is invalid. 50 51 --- 52
+3 -7
js/docs/src/content/docs/lex-reference/moderation/place-stream-moderation-creategate.md
··· 13 14 **Type:** `procedure` 15 16 - Create a gate (hide message) on behalf of a streamer. Requires 'hide' 17 - permission. Creates a place.stream.chat.gate record in the streamer's 18 - repository. 19 20 **Parameters:** _(None defined)_ 21 ··· 46 **Possible Errors:** 47 48 - `Unauthorized`: The request lacks valid authentication credentials. 49 - - `Forbidden`: The caller does not have permission to hide messages for this 50 - streamer. 51 - - `SessionNotFound`: The streamer's OAuth session could not be found or is 52 - invalid. 53 54 --- 55
··· 13 14 **Type:** `procedure` 15 16 + Create a gate (hide message) on behalf of a streamer. Requires 'hide' permission. Creates a place.stream.chat.gate record in the streamer's repository. 17 18 **Parameters:** _(None defined)_ 19 ··· 44 **Possible Errors:** 45 46 - `Unauthorized`: The request lacks valid authentication credentials. 47 + - `Forbidden`: The caller does not have permission to hide messages for this streamer. 48 + - `SessionNotFound`: The streamer's OAuth session could not be found or is invalid. 49 50 --- 51
+5 -7
js/docs/src/content/docs/lex-reference/moderation/place-stream-moderation-deleteblock.md
··· 13 14 **Type:** `procedure` 15 16 - Delete a block (unban) on behalf of a streamer. Requires 'ban' permission. 17 - Deletes an app.bsky.graph.block record from the streamer's repository. 18 19 **Parameters:** _(None defined)_ 20 ··· 37 38 **Schema Type:** `object` 39 40 - _(No properties defined)_ **Possible Errors:** 41 42 - `Unauthorized`: The request lacks valid authentication credentials. 43 - - `Forbidden`: The caller does not have permission to delete blocks for this 44 - streamer. 45 - - `SessionNotFound`: The streamer's OAuth session could not be found or is 46 - invalid. 47 48 --- 49
··· 13 14 **Type:** `procedure` 15 16 + Delete a block (unban) on behalf of a streamer. Requires 'ban' permission. Deletes an app.bsky.graph.block record from the streamer's repository. 17 18 **Parameters:** _(None defined)_ 19 ··· 36 37 **Schema Type:** `object` 38 39 + _(No properties defined)_ 40 + **Possible Errors:** 41 42 - `Unauthorized`: The request lacks valid authentication credentials. 43 + - `Forbidden`: The caller does not have permission to delete blocks for this streamer. 44 + - `SessionNotFound`: The streamer's OAuth session could not be found or is invalid. 45 46 --- 47
+5 -8
js/docs/src/content/docs/lex-reference/moderation/place-stream-moderation-deletegate.md
··· 13 14 **Type:** `procedure` 15 16 - Delete a gate (unhide message) on behalf of a streamer. Requires 'hide' 17 - permission. Deletes a place.stream.chat.gate record from the streamer's 18 - repository. 19 20 **Parameters:** _(None defined)_ 21 ··· 38 39 **Schema Type:** `object` 40 41 - _(No properties defined)_ **Possible Errors:** 42 43 - `Unauthorized`: The request lacks valid authentication credentials. 44 - - `Forbidden`: The caller does not have permission to unhide messages for this 45 - streamer. 46 - - `SessionNotFound`: The streamer's OAuth session could not be found or is 47 - invalid. 48 49 --- 50
··· 13 14 **Type:** `procedure` 15 16 + Delete a gate (unhide message) on behalf of a streamer. Requires 'hide' permission. Deletes a place.stream.chat.gate record from the streamer's repository. 17 18 **Parameters:** _(None defined)_ 19 ··· 36 37 **Schema Type:** `object` 38 39 + _(No properties defined)_ 40 + **Possible Errors:** 41 42 - `Unauthorized`: The request lacks valid authentication credentials. 43 + - `Forbidden`: The caller does not have permission to unhide messages for this streamer. 44 + - `SessionNotFound`: The streamer's OAuth session could not be found or is invalid. 45 46 --- 47
+3 -7
js/docs/src/content/docs/lex-reference/moderation/place-stream-moderation-updatelivestream.md
··· 13 14 **Type:** `procedure` 15 16 - Update livestream metadata on behalf of a streamer. Requires 'livestream.manage' 17 - permission. Updates a place.stream.livestream record in the streamer's 18 - repository. 19 20 **Parameters:** _(None defined)_ 21 ··· 47 **Possible Errors:** 48 49 - `Unauthorized`: The request lacks valid authentication credentials. 50 - - `Forbidden`: The caller does not have permission to update livestream metadata 51 - for this streamer. 52 - - `SessionNotFound`: The streamer's OAuth session could not be found or is 53 - invalid. 54 - `RecordNotFound`: The specified livestream record does not exist. 55 56 ---
··· 13 14 **Type:** `procedure` 15 16 + Update livestream metadata on behalf of a streamer. Requires 'livestream.manage' permission. Updates a place.stream.livestream record in the streamer's repository. 17 18 **Parameters:** _(None defined)_ 19 ··· 45 **Possible Errors:** 46 47 - `Unauthorized`: The request lacks valid authentication credentials. 48 + - `Forbidden`: The caller does not have permission to update livestream metadata for this streamer. 49 + - `SessionNotFound`: The streamer's OAuth session could not be found or is invalid. 50 - `RecordNotFound`: The specified livestream record does not exist. 51 52 ---
-77
js/docs/src/content/docs/lex-reference/multistream/com-atproto-repo-deletetarget.md
··· 1 - --- 2 - title: com.atproto.repo.deleteTarget 3 - description: Reference for the com.atproto.repo.deleteTarget lexicon 4 - --- 5 - 6 - **Lexicon Version:** 1 7 - 8 - ## Definitions 9 - 10 - <a name="main"></a> 11 - 12 - ### `main` 13 - 14 - **Type:** `procedure` 15 - 16 - Delete a target for rebroadcasting a Streamplace stream. 17 - 18 - **Parameters:** _(None defined)_ 19 - 20 - **Input:** 21 - 22 - - **Encoding:** `application/json` 23 - - **Schema:** 24 - 25 - **Schema Type:** `object` 26 - 27 - | Name | Type | Req'd | Description | Constraints | 28 - | ------ | -------- | ----- | --------------------------------------- | -------------------- | 29 - | `rkey` | `string` | โœ… | The Record Key of the target to delete. | Format: `record-key` | 30 - 31 - **Output:** 32 - 33 - - **Encoding:** `application/json` 34 - - **Schema:** 35 - 36 - **Schema Type:** `object` 37 - 38 - _(No properties defined)_ 39 - 40 - --- 41 - 42 - ## Lexicon Source 43 - 44 - ```json 45 - { 46 - "lexicon": 1, 47 - "id": "com.atproto.repo.deleteTarget", 48 - "defs": { 49 - "main": { 50 - "type": "procedure", 51 - "description": "Delete a target for rebroadcasting a Streamplace stream.", 52 - "input": { 53 - "encoding": "application/json", 54 - "schema": { 55 - "type": "object", 56 - "required": ["rkey"], 57 - "properties": { 58 - "rkey": { 59 - "type": "string", 60 - "format": "record-key", 61 - "description": "The Record Key of the target to delete." 62 - } 63 - } 64 - } 65 - }, 66 - "output": { 67 - "encoding": "application/json", 68 - "schema": { 69 - "type": "object", 70 - "properties": {} 71 - } 72 - }, 73 - "errors": [] 74 - } 75 - } 76 - } 77 - ```
···
+1 -2
js/docs/src/content/docs/lex-reference/multistream/place-stream-multistream-createtarget.md
··· 33 - **Encoding:** `application/json` 34 - **Schema:** 35 36 - **Schema Type:** 37 - [`place.stream.multistream.defs#targetView`](/lex-reference/place-stream-multistream-defs#targetview) 38 39 **Possible Errors:** 40
··· 33 - **Encoding:** `application/json` 34 - **Schema:** 35 36 + **Schema Type:** [`place.stream.multistream.defs#targetView`](/lex-reference/place-stream-multistream-defs#targetview) 37 38 **Possible Errors:** 39
+1 -2
js/docs/src/content/docs/lex-reference/multistream/place-stream-multistream-puttarget.md
··· 34 - **Encoding:** `application/json` 35 - **Schema:** 36 37 - **Schema Type:** 38 - [`place.stream.multistream.defs#targetView`](/lex-reference/place-stream-multistream-defs#targetview) 39 40 **Possible Errors:** 41
··· 34 - **Encoding:** `application/json` 35 - **Schema:** 36 37 + **Schema Type:** [`place.stream.multistream.defs#targetView`](/lex-reference/place-stream-multistream-defs#targetview) 38 39 **Possible Errors:** 40
+145
js/docs/src/content/docs/lex-reference/openapi.json
··· 1147 } 1148 } 1149 }, 1150 "/xrpc/place.stream.live.getLiveUsers": { 1151 "get": { 1152 "summary": "Get a list of livestream segments for a user", ··· 1880 "type": "string", 1881 "description": "Record Key", 1882 "format": "record-key" 1883 } 1884 } 1885 ]
··· 1147 } 1148 } 1149 }, 1150 + "/xrpc/place.stream.live.denyTeleport": { 1151 + "post": { 1152 + "summary": "Deny an incoming teleport request.", 1153 + "operationId": "place.stream.live.denyTeleport", 1154 + "tags": ["place.stream.live"], 1155 + "responses": { 1156 + "200": { 1157 + "description": "Success", 1158 + "content": { 1159 + "application/json": { 1160 + "schema": { 1161 + "type": "object", 1162 + "properties": { 1163 + "success": { 1164 + "type": "boolean", 1165 + "description": "Whether the teleport was successfully denied." 1166 + } 1167 + }, 1168 + "required": ["success"] 1169 + } 1170 + } 1171 + } 1172 + }, 1173 + "400": { 1174 + "description": "Bad Request", 1175 + "content": { 1176 + "application/json": { 1177 + "schema": { 1178 + "type": "object", 1179 + "required": ["error", "message"], 1180 + "properties": { 1181 + "error": { 1182 + "type": "string", 1183 + "oneOf": [ 1184 + { 1185 + "const": "TeleportNotFound" 1186 + }, 1187 + { 1188 + "const": "Unauthorized" 1189 + } 1190 + ] 1191 + }, 1192 + "message": { 1193 + "type": "string" 1194 + } 1195 + } 1196 + } 1197 + } 1198 + } 1199 + } 1200 + }, 1201 + "requestBody": { 1202 + "required": true, 1203 + "content": { 1204 + "application/json": { 1205 + "schema": { 1206 + "type": "object", 1207 + "properties": { 1208 + "uri": { 1209 + "type": "string", 1210 + "description": "The URI of the teleport record to deny.", 1211 + "format": "uri" 1212 + } 1213 + }, 1214 + "required": ["uri"] 1215 + } 1216 + } 1217 + } 1218 + } 1219 + } 1220 + }, 1221 "/xrpc/place.stream.live.getLiveUsers": { 1222 "get": { 1223 "summary": "Get a list of livestream segments for a user", ··· 1951 "type": "string", 1952 "description": "Record Key", 1953 "format": "record-key" 1954 + } 1955 + } 1956 + ] 1957 + } 1958 + }, 1959 + "/xrpc/com.atproto.sync.getRepo": { 1960 + "get": { 1961 + "summary": "Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS.", 1962 + "operationId": "com.atproto.sync.getRepo", 1963 + "tags": ["com.atproto.sync"], 1964 + "responses": { 1965 + "200": { 1966 + "description": "Success", 1967 + "content": { 1968 + "application/vnd.ipld.car": { 1969 + "schema": {} 1970 + } 1971 + } 1972 + }, 1973 + "400": { 1974 + "description": "Bad Request", 1975 + "content": { 1976 + "application/json": { 1977 + "schema": { 1978 + "type": "object", 1979 + "required": ["error", "message"], 1980 + "properties": { 1981 + "error": { 1982 + "type": "string", 1983 + "oneOf": [ 1984 + { 1985 + "const": "RepoNotFound" 1986 + }, 1987 + { 1988 + "const": "RepoTakendown" 1989 + }, 1990 + { 1991 + "const": "RepoSuspended" 1992 + }, 1993 + { 1994 + "const": "RepoDeactivated" 1995 + } 1996 + ] 1997 + }, 1998 + "message": { 1999 + "type": "string" 2000 + } 2001 + } 2002 + } 2003 + } 2004 + } 2005 + } 2006 + }, 2007 + "parameters": [ 2008 + { 2009 + "name": "did", 2010 + "in": "query", 2011 + "required": true, 2012 + "description": "The DID of the repo.", 2013 + "schema": { 2014 + "type": "string", 2015 + "description": "The DID of the repo.", 2016 + "format": "did" 2017 + } 2018 + }, 2019 + { 2020 + "name": "since", 2021 + "in": "query", 2022 + "required": false, 2023 + "description": "The revision ('rev') of the repo to create a diff from.", 2024 + "schema": { 2025 + "type": "string", 2026 + "description": "The revision ('rev') of the repo to create a diff from.", 2027 + "format": "tid" 2028 } 2029 } 2030 ]
+84 -3
js/docs/src/content/docs/lex-reference/place-stream-livestream.md
··· 79 80 --- 81 82 <a name="streamplaceanything"></a> 83 84 ### `streamplaceAnything` ··· 87 88 **Properties:** 89 90 - | Name | Type | Req'd | Description | Constraints | 91 - | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ----------- | ----------- | 92 - | `livestream` | Union of:<br/>&nbsp;&nbsp;[`#livestreamView`](#livestreamview)<br/>&nbsp;&nbsp;[`#viewerCount`](#viewercount)<br/>&nbsp;&nbsp;[`place.stream.defs#blockView`](/lex-reference/place-stream-defs#blockview)<br/>&nbsp;&nbsp;[`place.stream.defs#renditions`](/lex-reference/place-stream-defs#renditions)<br/>&nbsp;&nbsp;[`place.stream.defs#rendition`](/lex-reference/place-stream-defs#rendition)<br/>&nbsp;&nbsp;[`place.stream.chat.defs#messageView`](/lex-reference/place-stream-chat-defs#messageview) | โœ… | | | 93 94 --- 95 ··· 199 } 200 } 201 }, 202 "streamplaceAnything": { 203 "type": "object", 204 "required": ["livestream"], ··· 208 "refs": [ 209 "#livestreamView", 210 "#viewerCount", 211 "place.stream.defs#blockView", 212 "place.stream.defs#renditions", 213 "place.stream.defs#rendition",
··· 79 80 --- 81 82 + <a name="teleportarrival"></a> 83 + 84 + ### `teleportArrival` 85 + 86 + **Type:** `object` 87 + 88 + **Properties:** 89 + 90 + | Name | Type | Req'd | Description | Constraints | 91 + | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----- | -------------------------------------------------- | ------------------ | 92 + | `teleportUri` | `string` | โœ… | The URI of the teleport record | Format: `at-uri` | 93 + | `source` | [`app.bsky.actor.defs#profileViewBasic`](https://github.com/bluesky-social/atproto/tree/main/lexicons/app/bsky/actor/defs.json#profileViewBasic) | โœ… | The streamer who is teleporting their viewers here | | 94 + | `chatProfile` | [`place.stream.chat.profile`](/lex-reference/place-stream-chat-profile) | โŒ | The chat profile of the source streamer | | 95 + | `viewerCount` | `integer` | โœ… | How many viewers are arriving from this teleport | | 96 + | `startsAt` | `string` | โœ… | When this teleport started | Format: `datetime` | 97 + 98 + --- 99 + 100 + <a name="teleportcanceled"></a> 101 + 102 + ### `teleportCanceled` 103 + 104 + **Type:** `object` 105 + 106 + **Properties:** 107 + 108 + | Name | Type | Req'd | Description | Constraints | 109 + | ------------- | -------- | ----- | ------------------------------------------------ | ------------------------------------ | 110 + | `teleportUri` | `string` | โœ… | The URI of the teleport record that was canceled | Format: `at-uri` | 111 + | `reason` | `string` | โœ… | Why this teleport was canceled | Enum: `deleted`, `denied`, `expired` | 112 + 113 + --- 114 + 115 <a name="streamplaceanything"></a> 116 117 ### `streamplaceAnything` ··· 120 121 **Properties:** 122 123 + | Name | Type | Req'd | Description | Constraints | 124 + | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ----------- | ----------- | 125 + | `livestream` | Union of:<br/>&nbsp;&nbsp;[`#livestreamView`](#livestreamview)<br/>&nbsp;&nbsp;[`#viewerCount`](#viewercount)<br/>&nbsp;&nbsp;[`#teleportArrival`](#teleportarrival)<br/>&nbsp;&nbsp;[`#teleportCanceled`](#teleportcanceled)<br/>&nbsp;&nbsp;[`place.stream.defs#blockView`](/lex-reference/place-stream-defs#blockview)<br/>&nbsp;&nbsp;[`place.stream.defs#renditions`](/lex-reference/place-stream-defs#renditions)<br/>&nbsp;&nbsp;[`place.stream.defs#rendition`](/lex-reference/place-stream-defs#rendition)<br/>&nbsp;&nbsp;[`place.stream.chat.defs#messageView`](/lex-reference/place-stream-chat-defs#messageview) | โœ… | | | 126 127 --- 128 ··· 232 } 233 } 234 }, 235 + "teleportArrival": { 236 + "type": "object", 237 + "required": ["teleportUri", "source", "viewerCount", "startsAt"], 238 + "properties": { 239 + "teleportUri": { 240 + "type": "string", 241 + "format": "at-uri", 242 + "description": "The URI of the teleport record" 243 + }, 244 + "source": { 245 + "type": "ref", 246 + "ref": "app.bsky.actor.defs#profileViewBasic", 247 + "description": "The streamer who is teleporting their viewers here" 248 + }, 249 + "chatProfile": { 250 + "type": "ref", 251 + "ref": "place.stream.chat.profile", 252 + "description": "The chat profile of the source streamer" 253 + }, 254 + "viewerCount": { 255 + "type": "integer", 256 + "description": "How many viewers are arriving from this teleport" 257 + }, 258 + "startsAt": { 259 + "type": "string", 260 + "format": "datetime", 261 + "description": "When this teleport started" 262 + } 263 + } 264 + }, 265 + "teleportCanceled": { 266 + "type": "object", 267 + "required": ["teleportUri", "reason"], 268 + "properties": { 269 + "teleportUri": { 270 + "type": "string", 271 + "format": "at-uri", 272 + "description": "The URI of the teleport record that was canceled" 273 + }, 274 + "reason": { 275 + "type": "string", 276 + "enum": ["deleted", "denied", "expired"], 277 + "description": "Why this teleport was canceled" 278 + } 279 + } 280 + }, 281 "streamplaceAnything": { 282 "type": "object", 283 "required": ["livestream"], ··· 287 "refs": [ 288 "#livestreamView", 289 "#viewerCount", 290 + "#teleportArrival", 291 + "#teleportCanceled", 292 "place.stream.defs#blockView", 293 "place.stream.defs#renditions", 294 "place.stream.defs#rendition",
+9
js/docs/src/content/docs/reference.mdx
···
··· 1 + --- 2 + title: API Reference 3 + description: Our XRPC and OpenAPI Reference documentation 4 + template: doc 5 + --- 6 + 7 + import { Card, CardGrid } from "@astrojs/starlight/components"; 8 + 9 + Here contains our XRPC and OpenAPI Reference documentation.
+22
js/docs/src/pages/back-to-home.astro
···
··· 1 + --- 2 + import "../styles/custom-font-face.css" 3 + import "@fontsource/atkinson-hyperlegible-next/400.css" 4 + import "@fontsource/atkinson-hyperlegible-next/600.css" 5 + --- 6 + <style> 7 + * { 8 + font-family: "Atkinson Hyperlegible Next"; 9 + } 10 + </style> 11 + 12 + <script is:inline> 13 + let hostname = window.location.host 14 + const redirectUrl = hostname.endsWith('.stream.place') 15 + ? 'https://stream.place' 16 + : '/'; 17 + window.location.href = redirectUrl; 18 + </script> 19 + <body style="display: flex; color: white; justify-content: center; align-items: center; height: 100vh; background-color: #181818; flex: 1; flex-direction: column;"> 20 + <h1>Redirecting to Streamplace...</h1> 21 + <a href="https://stream.place" style="color: lightskyblue">Click here if you are not redirected automatically</a> 22 + </body>
+1 -1
lerna.json
··· 1 { 2 "$schema": "node_modules/lerna/schemas/lerna-schema.json", 3 - "version": "0.9.0", 4 "npmClient": "pnpm" 5 }
··· 1 { 2 "$schema": "node_modules/lerna/schemas/lerna-schema.json", 3 + "version": "0.9.9", 4 "npmClient": "pnpm" 5 }
+35
lexicons/com/atproto/sync/getRepo.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getRepo", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the repo." 16 + }, 17 + "since": { 18 + "type": "string", 19 + "format": "tid", 20 + "description": "The revision ('rev') of the repo to create a diff from." 21 + } 22 + } 23 + }, 24 + "output": { 25 + "encoding": "application/vnd.ipld.car" 26 + }, 27 + "errors": [ 28 + { "name": "RepoNotFound" }, 29 + { "name": "RepoTakendown" }, 30 + { "name": "RepoSuspended" }, 31 + { "name": "RepoDeactivated" } 32 + ] 33 + } 34 + } 35 + }
+46
lexicons/place/stream/badge/defs.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "place.stream.badge.defs", 4 + "defs": { 5 + "badgeView": { 6 + "type": "object", 7 + "required": ["badgeType", "issuer", "recipient"], 8 + "description": "View of a badge record, with fields resolved for display. If the DID in issuer is not the current streamplace node, the signature field shall be required.", 9 + "properties": { 10 + "badgeType": { 11 + "type": "string", 12 + "knownValues": [ 13 + "place.stream.badge.defs#mod", 14 + "place.stream.badge.defs#streamer" 15 + ] 16 + }, 17 + "issuer": { 18 + "type": "string", 19 + "format": "did", 20 + "description": "DID of the badge issuer." 21 + }, 22 + "recipient": { 23 + "type": "string", 24 + "format": "did", 25 + "description": "DID of the badge recipient." 26 + }, 27 + "signature": { 28 + "type": "string", 29 + "description": "TODO: Cryptographic signature of the badge (of a place.stream.key)." 30 + } 31 + } 32 + }, 33 + "mod": { 34 + "type": "token", 35 + "description": "This user is a moderator. Displayed with a sword icon." 36 + }, 37 + "streamer": { 38 + "type": "token", 39 + "description": "This user is the streamer. Displayed with a star icon." 40 + }, 41 + "vip": { 42 + "type": "token", 43 + "description": "This user is a very important person." 44 + } 45 + } 46 + }
+44
lexicons/place/stream/badge/display.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "place.stream.badge.display", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "description": "Record issuing a badge to a user.", 8 + "record": { 9 + "type": "object", 10 + "required": ["badges"], 11 + "properties": { 12 + "badges": { 13 + "type": "array", 14 + "description": "Up to 3 badge tokens to display with the message. First badge is server-controlled, remaining badges are user-settable.", 15 + "maxLength": 3, 16 + "items": { 17 + "type": "ref", 18 + "ref": "#badgeSelection" 19 + } 20 + } 21 + } 22 + } 23 + }, 24 + "badgeSelection": { 25 + "type": "object", 26 + "description": "A badge selected for display. May be a full badgeView from the server, or a token representing a badge type that the client can look up for display info.", 27 + "required": ["badgeType"], 28 + "properties": { 29 + "badgeType": { 30 + "type": "string", 31 + "knownValues": [ 32 + "place.stream.badge.defs#mod", 33 + "place.stream.badge.defs#vip" 34 + ] 35 + }, 36 + "issuance": { 37 + "type": "string", 38 + "format": "at-uri", 39 + "description": "URI of the badge issuance record (place.stream.badge.issuance) that represents this badge. Required if badgeType is not recognized." 40 + } 41 + } 42 + } 43 + } 44 + }
+30
lexicons/place/stream/badge/issuance.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "place.stream.badge.issuance", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "key": "tid", 8 + "description": "Record issuing a badge to a user.", 9 + "record": { 10 + "type": "object", 11 + "required": ["badgeType", "recipient", "signature"], 12 + "properties": { 13 + "badgeType": { 14 + "type": "string", 15 + "knownValues": ["place.stream.badge.defs#vip"] 16 + }, 17 + "recipient": { 18 + "type": "string", 19 + "format": "did", 20 + "description": "DID of the badge recipient." 21 + }, 22 + "signature": { 23 + "type": "string", 24 + "description": "TODO: Cryptographic signature of the badge (of a place.stream.key)." 25 + } 26 + } 27 + } 28 + } 29 + } 30 + }
+9
lexicons/place/stream/chat/defs.json
··· 25 "deleted": { 26 "type": "boolean", 27 "description": "If true, this message has been deleted or labeled and should be cleared from the cache" 28 } 29 } 30 }
··· 25 "deleted": { 26 "type": "boolean", 27 "description": "If true, this message has been deleted or labeled and should be cleared from the cache" 28 + }, 29 + "badges": { 30 + "type": "array", 31 + "description": "Up to 3 badge tokens to display with the message. First badge is server-controlled, remaining badges are user-settable. Tokens are looked up in badges.json for display info.", 32 + "maxLength": 3, 33 + "items": { 34 + "type": "ref", 35 + "ref": "place.stream.badge.defs#badgeView" 36 + } 37 } 38 } 39 }
+47
lexicons/place/stream/live/denyTeleport.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "place.stream.live.denyTeleport", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Deny an incoming teleport request.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["uri"], 13 + "properties": { 14 + "uri": { 15 + "type": "string", 16 + "format": "at-uri", 17 + "description": "The URI of the teleport record to deny." 18 + } 19 + } 20 + } 21 + }, 22 + "output": { 23 + "encoding": "application/json", 24 + "schema": { 25 + "type": "object", 26 + "required": ["success"], 27 + "properties": { 28 + "success": { 29 + "type": "boolean", 30 + "description": "Whether the teleport was successfully denied." 31 + } 32 + } 33 + } 34 + }, 35 + "errors": [ 36 + { 37 + "name": "TeleportNotFound", 38 + "description": "The specified teleport was not found." 39 + }, 40 + { 41 + "name": "Unauthorized", 42 + "description": "The authenticated user is not the target of this teleport." 43 + } 44 + ] 45 + } 46 + } 47 + }
+33
lexicons/place/stream/live/teleport.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "place.stream.live.teleport", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "key": "tid", 8 + "description": "Record defining a 'teleport', that is active during a certain time.", 9 + "record": { 10 + "type": "object", 11 + "required": ["streamer", "startsAt"], 12 + "properties": { 13 + "streamer": { 14 + "type": "string", 15 + "format": "did", 16 + "description": "The DID of the streamer to teleport to." 17 + }, 18 + "startsAt": { 19 + "type": "string", 20 + "format": "datetime", 21 + "description": "The time the teleport becomes active." 22 + }, 23 + "durationSeconds": { 24 + "type": "integer", 25 + "description": "The time limit in seconds for the teleport. If not set, the teleport is permanent. Must be at least 60 seconds, and no more than 32,400 seconds (9 hours).", 26 + "minimum": 60, 27 + "maximum": 32400 28 + } 29 + } 30 + } 31 + } 32 + } 33 + }
+48
lexicons/place/stream/livestream.json
··· 88 "count": { "type": "integer" } 89 } 90 }, 91 "streamplaceAnything": { 92 "type": "object", 93 "required": ["livestream"], ··· 97 "refs": [ 98 "#livestreamView", 99 "#viewerCount", 100 "place.stream.defs#blockView", 101 "place.stream.defs#renditions", 102 "place.stream.defs#rendition",
··· 88 "count": { "type": "integer" } 89 } 90 }, 91 + "teleportArrival": { 92 + "type": "object", 93 + "required": ["teleportUri", "source", "viewerCount", "startsAt"], 94 + "properties": { 95 + "teleportUri": { 96 + "type": "string", 97 + "format": "at-uri", 98 + "description": "The URI of the teleport record" 99 + }, 100 + "source": { 101 + "type": "ref", 102 + "ref": "app.bsky.actor.defs#profileViewBasic", 103 + "description": "The streamer who is teleporting their viewers here" 104 + }, 105 + "chatProfile": { 106 + "type": "ref", 107 + "ref": "place.stream.chat.profile", 108 + "description": "The chat profile of the source streamer" 109 + }, 110 + "viewerCount": { 111 + "type": "integer", 112 + "description": "How many viewers are arriving from this teleport" 113 + }, 114 + "startsAt": { 115 + "type": "string", 116 + "format": "datetime", 117 + "description": "When this teleport started" 118 + } 119 + } 120 + }, 121 + "teleportCanceled": { 122 + "type": "object", 123 + "required": ["teleportUri", "reason"], 124 + "properties": { 125 + "teleportUri": { 126 + "type": "string", 127 + "format": "at-uri", 128 + "description": "The URI of the teleport record that was canceled" 129 + }, 130 + "reason": { 131 + "type": "string", 132 + "enum": ["deleted", "denied", "expired"], 133 + "description": "Why this teleport was canceled" 134 + } 135 + } 136 + }, 137 "streamplaceAnything": { 138 "type": "object", 139 "required": ["livestream"], ··· 143 "refs": [ 144 "#livestreamView", 145 "#viewerCount", 146 + "#teleportArrival", 147 + "#teleportCanceled", 148 "place.stream.defs#blockView", 149 "place.stream.defs#renditions", 150 "place.stream.defs#rendition",
-8
package.json
··· 45 "prettier-plugin-organize-imports": "^4.1.0", 46 "quicktype": "^23.2.6" 47 }, 48 - "pnpm": { 49 - "overrides": { 50 - "@types/react": "19.0.0", 51 - "@types/react-dom": "19.0.0", 52 - "react": "19.0.0", 53 - "react-dom": "19.0.0" 54 - } 55 - }, 56 "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977" 57 }
··· 45 "prettier-plugin-organize-imports": "^4.1.0", 46 "quicktype": "^23.2.6" 47 }, 48 "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977" 49 }
-144
pkg/analytics/client.go
··· 1 - package analytics 2 - 3 - import ( 4 - "context" 5 - "fmt" 6 - 7 - "google.golang.org/grpc" 8 - "google.golang.org/grpc/credentials/insecure" 9 - pb "stream.place/streamplace/pkg/analytics/pb" 10 - ) 11 - 12 - type Client interface { 13 - IngestEvents(ctx context.Context, events []*Event) error 14 - GetRealtimeStats(ctx context.Context, req *RealtimeStatsRequest) (*RealtimeStatsResponse, error) 15 - GetStreamerStats(ctx context.Context, req *StreamerStatsRequest) (*StreamerStatsResponse, error) 16 - GetViewerHistory(ctx context.Context, req *ViewerHistoryRequest) (*ViewerHistoryResponse, error) 17 - Close() error 18 - } 19 - 20 - type client struct { 21 - conn *grpc.ClientConn 22 - grpcClient pb.AnalyticsClient 23 - } 24 - 25 - func NewClient(ctx context.Context, endpoint string) (Client, error) { 26 - 27 - conn, err := grpc.NewClient(endpoint, 28 - grpc.WithTransportCredentials(insecure.NewCredentials()), 29 - ) 30 - if err != nil { 31 - return nil, fmt.Errorf("failed to connect to analytics service at %s: %w", endpoint, err) 32 - } 33 - 34 - return &client{ 35 - conn: conn, 36 - grpcClient: pb.NewAnalyticsClient(conn), 37 - }, nil 38 - } 39 - 40 - func (c *client) IngestEvents(ctx context.Context, events []*Event) error { 41 - if len(events) == 0 { 42 - return nil 43 - } 44 - 45 - pbEvents := make([]*pb.Event, len(events)) 46 - for i, e := range events { 47 - pbEvents[i] = &pb.Event{ 48 - EventId: e.EventID, 49 - EventType: e.EventType, 50 - DeviceId: e.DeviceID, 51 - Did: e.DID, 52 - SessionId: e.SessionID, 53 - TimestampMs: e.TimestampMs, 54 - StreamerDid: e.StreamerDID, 55 - StreamId: e.StreamID, 56 - PropertiesJson: e.PropertiesJSON, 57 - SchemaVersion: uint32(e.SchemaVersion), 58 - ClientVersion: e.ClientVersion, 59 - Platform: e.Platform, 60 - } 61 - } 62 - 63 - req := &pb.IngestEventsRequest{ 64 - Events: pbEvents, 65 - } 66 - 67 - _, err := c.grpcClient.IngestEvents(ctx, req) 68 - return err 69 - } 70 - 71 - func (c *client) GetRealtimeStats(ctx context.Context, req *RealtimeStatsRequest) (*RealtimeStatsResponse, error) { 72 - pbReq := &pb.RealtimeStatsRequest{ 73 - WindowMinutes: req.WindowMinutes, 74 - StreamerDid: req.StreamerDid, 75 - } 76 - 77 - resp, err := c.grpcClient.GetRealtimeStats(ctx, pbReq) 78 - if err != nil { 79 - return nil, err 80 - } 81 - 82 - return convertRealtimeStatsResponse(resp), nil 83 - } 84 - 85 - func (c *client) GetStreamerStats(ctx context.Context, req *StreamerStatsRequest) (*StreamerStatsResponse, error) { 86 - pbReq := &pb.StreamerStatsRequest{ 87 - StreamerDid: req.StreamerDid, 88 - StartTimeMs: req.StartTimeMs, 89 - EndTimeMs: req.EndTimeMs, 90 - } 91 - 92 - resp, err := c.grpcClient.GetStreamerStats(ctx, pbReq) 93 - if err != nil { 94 - return nil, err 95 - } 96 - 97 - return convertStreamerStatsResponse(resp), nil 98 - } 99 - 100 - func (c *client) GetViewerHistory(ctx context.Context, req *ViewerHistoryRequest) (*ViewerHistoryResponse, error) { 101 - pbReq := &pb.ViewerHistoryRequest{ 102 - Did: req.Did, 103 - StartTimeMs: req.StartTimeMs, 104 - EndTimeMs: req.EndTimeMs, 105 - Limit: req.Limit, 106 - } 107 - 108 - resp, err := c.grpcClient.GetViewerHistory(ctx, pbReq) 109 - if err != nil { 110 - return nil, err 111 - } 112 - 113 - return convertViewerHistoryResponse(resp), nil 114 - } 115 - 116 - func (c *client) Close() error { 117 - if c.conn != nil { 118 - return c.conn.Close() 119 - } 120 - return nil 121 - } 122 - 123 - // NopClient is a no-op implementation of Client for when analytics is disabled 124 - type nopClient struct{} 125 - 126 - func (n *nopClient) IngestEvents(ctx context.Context, events []*Event) error { 127 - return nil 128 - } 129 - 130 - func (n *nopClient) GetRealtimeStats(ctx context.Context, req *RealtimeStatsRequest) (*RealtimeStatsResponse, error) { 131 - return &RealtimeStatsResponse{}, nil 132 - } 133 - 134 - func (n *nopClient) GetStreamerStats(ctx context.Context, req *StreamerStatsRequest) (*StreamerStatsResponse, error) { 135 - return &StreamerStatsResponse{}, nil 136 - } 137 - 138 - func (n *nopClient) GetViewerHistory(ctx context.Context, req *ViewerHistoryRequest) (*ViewerHistoryResponse, error) { 139 - return &ViewerHistoryResponse{}, nil 140 - } 141 - 142 - func (n *nopClient) Close() error { 143 - return nil 144 - }
···
-158
pkg/analytics/handlers.go
··· 1 - package analytics 2 - 3 - import ( 4 - "encoding/json" 5 - "net/http" 6 - "strconv" 7 - 8 - "github.com/julienschmidt/httprouter" 9 - "stream.place/streamplace/pkg/log" 10 - ) 11 - 12 - func HandleRealtimeStats(client Client) http.HandlerFunc { 13 - return func(w http.ResponseWriter, req *http.Request) { 14 - if client == nil { 15 - log.Debug(req.Context(), "analytics not configured, skipping realtime stats") 16 - w.Header().Set("Content-Type", "application/json") 17 - w.WriteHeader(503) 18 - err := json.NewEncoder(w).Encode(map[string]string{"error": "analytics not configured"}) 19 - if err != nil { 20 - log.Error(req.Context(), "Could not send error message to client from HandleRealtimeStats") 21 - } 22 - return 23 - } 24 - 25 - windowMinutes := req.URL.Query().Get("window") 26 - if windowMinutes == "" { 27 - windowMinutes = "5" 28 - } 29 - window, _ := strconv.ParseUint(windowMinutes, 10, 32) 30 - 31 - r := &RealtimeStatsRequest{ 32 - WindowMinutes: uint32(window), 33 - } 34 - 35 - if streamerDid := req.URL.Query().Get("streamer"); streamerDid != "" { 36 - r.StreamerDid = &streamerDid 37 - } 38 - 39 - resp, err := client.GetRealtimeStats(req.Context(), r) 40 - if err != nil { 41 - log.Log(req.Context(), "failed to fetch realtime stats", "error", err) 42 - w.Header().Set("Content-Type", "application/json") 43 - w.WriteHeader(500) 44 - if encErr := json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}); encErr != nil { 45 - log.Error(req.Context(), "failed to encode error response", "error", encErr) 46 - } 47 - return 48 - } 49 - 50 - w.Header().Set("Content-Type", "application/json") 51 - w.WriteHeader(200) 52 - if err := json.NewEncoder(w).Encode(resp); err != nil { 53 - log.Error(req.Context(), "failed to encode realtime stats response", "error", err) 54 - } 55 - } 56 - } 57 - 58 - func HandleStreamerStats(client Client) httprouter.Handle { 59 - return func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { 60 - if client == nil { 61 - log.Debug(req.Context(), "analytics not configured, skipping streamer stats") 62 - w.Header().Set("Content-Type", "application/json") 63 - w.WriteHeader(503) 64 - err := json.NewEncoder(w).Encode(map[string]string{"error": "analytics not configured"}) 65 - if err != nil { 66 - log.Error(req.Context(), "Could not send error message to client from HandleStreamerStats") 67 - } 68 - return 69 - } 70 - 71 - streamerDid := params.ByName("did") 72 - 73 - r := &StreamerStatsRequest{ 74 - StreamerDid: streamerDid, 75 - } 76 - 77 - if start := req.URL.Query().Get("start"); start != "" { 78 - startMs, _ := strconv.ParseInt(start, 10, 64) 79 - r.StartTimeMs = &startMs 80 - } 81 - 82 - if end := req.URL.Query().Get("end"); end != "" { 83 - endMs, _ := strconv.ParseInt(end, 10, 64) 84 - r.EndTimeMs = &endMs 85 - } 86 - 87 - resp, err := client.GetStreamerStats(req.Context(), r) 88 - if err != nil { 89 - log.Log(req.Context(), "failed to fetch streamer stats", "error", err) 90 - w.Header().Set("Content-Type", "application/json") 91 - w.WriteHeader(500) 92 - if encErr := json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}); encErr != nil { 93 - log.Error(req.Context(), "failed to encode error response", "error", encErr) 94 - } 95 - return 96 - } 97 - 98 - w.Header().Set("Content-Type", "application/json") 99 - w.WriteHeader(200) 100 - if err := json.NewEncoder(w).Encode(resp); err != nil { 101 - log.Error(req.Context(), "failed to encode streamer stats response", "error", err) 102 - } 103 - } 104 - } 105 - 106 - func HandleViewerHistory(client Client) httprouter.Handle { 107 - return func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { 108 - if client == nil { 109 - log.Debug(req.Context(), "analytics not configured, skipping viewer history") 110 - w.Header().Set("Content-Type", "application/json") 111 - w.WriteHeader(503) 112 - if err := json.NewEncoder(w).Encode(map[string]string{"error": "analytics not configured"}); err != nil { 113 - log.Error(req.Context(), "failed to encode error response", "error", err) 114 - } 115 - return 116 - } 117 - 118 - did := params.ByName("did") 119 - 120 - limit := req.URL.Query().Get("limit") 121 - if limit == "" { 122 - limit = "50" 123 - } 124 - limitVal, _ := strconv.ParseUint(limit, 10, 32) 125 - 126 - r := &ViewerHistoryRequest{ 127 - Did: did, 128 - Limit: uint32(limitVal), 129 - } 130 - 131 - if start := req.URL.Query().Get("start"); start != "" { 132 - startMs, _ := strconv.ParseInt(start, 10, 64) 133 - r.StartTimeMs = &startMs 134 - } 135 - 136 - if end := req.URL.Query().Get("end"); end != "" { 137 - endMs, _ := strconv.ParseInt(end, 10, 64) 138 - r.EndTimeMs = &endMs 139 - } 140 - 141 - resp, err := client.GetViewerHistory(req.Context(), r) 142 - if err != nil { 143 - log.Log(req.Context(), "failed to fetch viewer history", "error", err) 144 - w.Header().Set("Content-Type", "application/json") 145 - w.WriteHeader(500) 146 - if encErr := json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}); encErr != nil { 147 - log.Error(req.Context(), "failed to encode error response", "error", encErr) 148 - } 149 - return 150 - } 151 - 152 - w.Header().Set("Content-Type", "application/json") 153 - w.WriteHeader(200) 154 - if err := json.NewEncoder(w).Encode(resp); err != nil { 155 - log.Error(req.Context(), "failed to encode viewer history response", "error", err) 156 - } 157 - } 158 - }
···
-1221
pkg/analytics/pb/analytics.pb.go
··· 1 - // Code generated by protoc-gen-go. DO NOT EDIT. 2 - // versions: 3 - // protoc-gen-go v1.36.11 4 - // protoc v6.33.3 5 - // source: rust/sp-analytics/proto/analytics.proto 6 - 7 - package pb 8 - 9 - import ( 10 - protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 - protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 - reflect "reflect" 13 - sync "sync" 14 - unsafe "unsafe" 15 - ) 16 - 17 - const ( 18 - // Verify that this generated code is sufficiently up-to-date. 19 - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 - // Verify that runtime/protoimpl is sufficiently up-to-date. 21 - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 - ) 23 - 24 - type IngestEventsRequest struct { 25 - state protoimpl.MessageState `protogen:"open.v1"` 26 - Events []*Event `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` 27 - unknownFields protoimpl.UnknownFields 28 - sizeCache protoimpl.SizeCache 29 - } 30 - 31 - func (x *IngestEventsRequest) Reset() { 32 - *x = IngestEventsRequest{} 33 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[0] 34 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 35 - ms.StoreMessageInfo(mi) 36 - } 37 - 38 - func (x *IngestEventsRequest) String() string { 39 - return protoimpl.X.MessageStringOf(x) 40 - } 41 - 42 - func (*IngestEventsRequest) ProtoMessage() {} 43 - 44 - func (x *IngestEventsRequest) ProtoReflect() protoreflect.Message { 45 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[0] 46 - if x != nil { 47 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 48 - if ms.LoadMessageInfo() == nil { 49 - ms.StoreMessageInfo(mi) 50 - } 51 - return ms 52 - } 53 - return mi.MessageOf(x) 54 - } 55 - 56 - // Deprecated: Use IngestEventsRequest.ProtoReflect.Descriptor instead. 57 - func (*IngestEventsRequest) Descriptor() ([]byte, []int) { 58 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{0} 59 - } 60 - 61 - func (x *IngestEventsRequest) GetEvents() []*Event { 62 - if x != nil { 63 - return x.Events 64 - } 65 - return nil 66 - } 67 - 68 - type IngestEventsResponse struct { 69 - state protoimpl.MessageState `protogen:"open.v1"` 70 - Accepted uint32 `protobuf:"varint,1,opt,name=accepted,proto3" json:"accepted,omitempty"` 71 - Rejected uint32 `protobuf:"varint,2,opt,name=rejected,proto3" json:"rejected,omitempty"` 72 - Errors []string `protobuf:"bytes,3,rep,name=errors,proto3" json:"errors,omitempty"` 73 - unknownFields protoimpl.UnknownFields 74 - sizeCache protoimpl.SizeCache 75 - } 76 - 77 - func (x *IngestEventsResponse) Reset() { 78 - *x = IngestEventsResponse{} 79 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[1] 80 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 81 - ms.StoreMessageInfo(mi) 82 - } 83 - 84 - func (x *IngestEventsResponse) String() string { 85 - return protoimpl.X.MessageStringOf(x) 86 - } 87 - 88 - func (*IngestEventsResponse) ProtoMessage() {} 89 - 90 - func (x *IngestEventsResponse) ProtoReflect() protoreflect.Message { 91 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[1] 92 - if x != nil { 93 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 94 - if ms.LoadMessageInfo() == nil { 95 - ms.StoreMessageInfo(mi) 96 - } 97 - return ms 98 - } 99 - return mi.MessageOf(x) 100 - } 101 - 102 - // Deprecated: Use IngestEventsResponse.ProtoReflect.Descriptor instead. 103 - func (*IngestEventsResponse) Descriptor() ([]byte, []int) { 104 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{1} 105 - } 106 - 107 - func (x *IngestEventsResponse) GetAccepted() uint32 { 108 - if x != nil { 109 - return x.Accepted 110 - } 111 - return 0 112 - } 113 - 114 - func (x *IngestEventsResponse) GetRejected() uint32 { 115 - if x != nil { 116 - return x.Rejected 117 - } 118 - return 0 119 - } 120 - 121 - func (x *IngestEventsResponse) GetErrors() []string { 122 - if x != nil { 123 - return x.Errors 124 - } 125 - return nil 126 - } 127 - 128 - type Event struct { 129 - state protoimpl.MessageState `protogen:"open.v1"` 130 - EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` 131 - EventType string `protobuf:"bytes,2,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` 132 - DeviceId string `protobuf:"bytes,3,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` 133 - Did *string `protobuf:"bytes,4,opt,name=did,proto3,oneof" json:"did,omitempty"` 134 - SessionId string `protobuf:"bytes,5,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` 135 - TimestampMs int64 `protobuf:"varint,6,opt,name=timestamp_ms,json=timestampMs,proto3" json:"timestamp_ms,omitempty"` 136 - StreamerDid string `protobuf:"bytes,7,opt,name=streamer_did,json=streamerDid,proto3" json:"streamer_did,omitempty"` 137 - StreamId *string `protobuf:"bytes,8,opt,name=stream_id,json=streamId,proto3,oneof" json:"stream_id,omitempty"` 138 - PropertiesJson string `protobuf:"bytes,9,opt,name=properties_json,json=propertiesJson,proto3" json:"properties_json,omitempty"` 139 - SchemaVersion uint32 `protobuf:"varint,10,opt,name=schema_version,json=schemaVersion,proto3" json:"schema_version,omitempty"` 140 - ClientVersion string `protobuf:"bytes,11,opt,name=client_version,json=clientVersion,proto3" json:"client_version,omitempty"` 141 - Platform string `protobuf:"bytes,12,opt,name=platform,proto3" json:"platform,omitempty"` 142 - unknownFields protoimpl.UnknownFields 143 - sizeCache protoimpl.SizeCache 144 - } 145 - 146 - func (x *Event) Reset() { 147 - *x = Event{} 148 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[2] 149 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 150 - ms.StoreMessageInfo(mi) 151 - } 152 - 153 - func (x *Event) String() string { 154 - return protoimpl.X.MessageStringOf(x) 155 - } 156 - 157 - func (*Event) ProtoMessage() {} 158 - 159 - func (x *Event) ProtoReflect() protoreflect.Message { 160 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[2] 161 - if x != nil { 162 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 163 - if ms.LoadMessageInfo() == nil { 164 - ms.StoreMessageInfo(mi) 165 - } 166 - return ms 167 - } 168 - return mi.MessageOf(x) 169 - } 170 - 171 - // Deprecated: Use Event.ProtoReflect.Descriptor instead. 172 - func (*Event) Descriptor() ([]byte, []int) { 173 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{2} 174 - } 175 - 176 - func (x *Event) GetEventId() string { 177 - if x != nil { 178 - return x.EventId 179 - } 180 - return "" 181 - } 182 - 183 - func (x *Event) GetEventType() string { 184 - if x != nil { 185 - return x.EventType 186 - } 187 - return "" 188 - } 189 - 190 - func (x *Event) GetDeviceId() string { 191 - if x != nil { 192 - return x.DeviceId 193 - } 194 - return "" 195 - } 196 - 197 - func (x *Event) GetDid() string { 198 - if x != nil && x.Did != nil { 199 - return *x.Did 200 - } 201 - return "" 202 - } 203 - 204 - func (x *Event) GetSessionId() string { 205 - if x != nil { 206 - return x.SessionId 207 - } 208 - return "" 209 - } 210 - 211 - func (x *Event) GetTimestampMs() int64 { 212 - if x != nil { 213 - return x.TimestampMs 214 - } 215 - return 0 216 - } 217 - 218 - func (x *Event) GetStreamerDid() string { 219 - if x != nil { 220 - return x.StreamerDid 221 - } 222 - return "" 223 - } 224 - 225 - func (x *Event) GetStreamId() string { 226 - if x != nil && x.StreamId != nil { 227 - return *x.StreamId 228 - } 229 - return "" 230 - } 231 - 232 - func (x *Event) GetPropertiesJson() string { 233 - if x != nil { 234 - return x.PropertiesJson 235 - } 236 - return "" 237 - } 238 - 239 - func (x *Event) GetSchemaVersion() uint32 { 240 - if x != nil { 241 - return x.SchemaVersion 242 - } 243 - return 0 244 - } 245 - 246 - func (x *Event) GetClientVersion() string { 247 - if x != nil { 248 - return x.ClientVersion 249 - } 250 - return "" 251 - } 252 - 253 - func (x *Event) GetPlatform() string { 254 - if x != nil { 255 - return x.Platform 256 - } 257 - return "" 258 - } 259 - 260 - type StreamerStatsRequest struct { 261 - state protoimpl.MessageState `protogen:"open.v1"` 262 - StreamerDid string `protobuf:"bytes,1,opt,name=streamer_did,json=streamerDid,proto3" json:"streamer_did,omitempty"` 263 - StartTimeMs *int64 `protobuf:"varint,2,opt,name=start_time_ms,json=startTimeMs,proto3,oneof" json:"start_time_ms,omitempty"` 264 - EndTimeMs *int64 `protobuf:"varint,3,opt,name=end_time_ms,json=endTimeMs,proto3,oneof" json:"end_time_ms,omitempty"` 265 - unknownFields protoimpl.UnknownFields 266 - sizeCache protoimpl.SizeCache 267 - } 268 - 269 - func (x *StreamerStatsRequest) Reset() { 270 - *x = StreamerStatsRequest{} 271 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[3] 272 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 273 - ms.StoreMessageInfo(mi) 274 - } 275 - 276 - func (x *StreamerStatsRequest) String() string { 277 - return protoimpl.X.MessageStringOf(x) 278 - } 279 - 280 - func (*StreamerStatsRequest) ProtoMessage() {} 281 - 282 - func (x *StreamerStatsRequest) ProtoReflect() protoreflect.Message { 283 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[3] 284 - if x != nil { 285 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 286 - if ms.LoadMessageInfo() == nil { 287 - ms.StoreMessageInfo(mi) 288 - } 289 - return ms 290 - } 291 - return mi.MessageOf(x) 292 - } 293 - 294 - // Deprecated: Use StreamerStatsRequest.ProtoReflect.Descriptor instead. 295 - func (*StreamerStatsRequest) Descriptor() ([]byte, []int) { 296 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{3} 297 - } 298 - 299 - func (x *StreamerStatsRequest) GetStreamerDid() string { 300 - if x != nil { 301 - return x.StreamerDid 302 - } 303 - return "" 304 - } 305 - 306 - func (x *StreamerStatsRequest) GetStartTimeMs() int64 { 307 - if x != nil && x.StartTimeMs != nil { 308 - return *x.StartTimeMs 309 - } 310 - return 0 311 - } 312 - 313 - func (x *StreamerStatsRequest) GetEndTimeMs() int64 { 314 - if x != nil && x.EndTimeMs != nil { 315 - return *x.EndTimeMs 316 - } 317 - return 0 318 - } 319 - 320 - type StreamerStatsResponse struct { 321 - state protoimpl.MessageState `protogen:"open.v1"` 322 - StreamerDid string `protobuf:"bytes,1,opt,name=streamer_did,json=streamerDid,proto3" json:"streamer_did,omitempty"` 323 - TotalViews uint64 `protobuf:"varint,2,opt,name=total_views,json=totalViews,proto3" json:"total_views,omitempty"` 324 - TotalWatchTimeMs uint64 `protobuf:"varint,3,opt,name=total_watch_time_ms,json=totalWatchTimeMs,proto3" json:"total_watch_time_ms,omitempty"` 325 - UniqueViewers uint64 `protobuf:"varint,4,opt,name=unique_viewers,json=uniqueViewers,proto3" json:"unique_viewers,omitempty"` 326 - DailyStats []*DailyStats `protobuf:"bytes,5,rep,name=daily_stats,json=dailyStats,proto3" json:"daily_stats,omitempty"` 327 - unknownFields protoimpl.UnknownFields 328 - sizeCache protoimpl.SizeCache 329 - } 330 - 331 - func (x *StreamerStatsResponse) Reset() { 332 - *x = StreamerStatsResponse{} 333 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[4] 334 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 335 - ms.StoreMessageInfo(mi) 336 - } 337 - 338 - func (x *StreamerStatsResponse) String() string { 339 - return protoimpl.X.MessageStringOf(x) 340 - } 341 - 342 - func (*StreamerStatsResponse) ProtoMessage() {} 343 - 344 - func (x *StreamerStatsResponse) ProtoReflect() protoreflect.Message { 345 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[4] 346 - if x != nil { 347 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 348 - if ms.LoadMessageInfo() == nil { 349 - ms.StoreMessageInfo(mi) 350 - } 351 - return ms 352 - } 353 - return mi.MessageOf(x) 354 - } 355 - 356 - // Deprecated: Use StreamerStatsResponse.ProtoReflect.Descriptor instead. 357 - func (*StreamerStatsResponse) Descriptor() ([]byte, []int) { 358 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{4} 359 - } 360 - 361 - func (x *StreamerStatsResponse) GetStreamerDid() string { 362 - if x != nil { 363 - return x.StreamerDid 364 - } 365 - return "" 366 - } 367 - 368 - func (x *StreamerStatsResponse) GetTotalViews() uint64 { 369 - if x != nil { 370 - return x.TotalViews 371 - } 372 - return 0 373 - } 374 - 375 - func (x *StreamerStatsResponse) GetTotalWatchTimeMs() uint64 { 376 - if x != nil { 377 - return x.TotalWatchTimeMs 378 - } 379 - return 0 380 - } 381 - 382 - func (x *StreamerStatsResponse) GetUniqueViewers() uint64 { 383 - if x != nil { 384 - return x.UniqueViewers 385 - } 386 - return 0 387 - } 388 - 389 - func (x *StreamerStatsResponse) GetDailyStats() []*DailyStats { 390 - if x != nil { 391 - return x.DailyStats 392 - } 393 - return nil 394 - } 395 - 396 - type DailyStats struct { 397 - state protoimpl.MessageState `protogen:"open.v1"` 398 - Date string `protobuf:"bytes,1,opt,name=date,proto3" json:"date,omitempty"` 399 - Views uint64 `protobuf:"varint,2,opt,name=views,proto3" json:"views,omitempty"` 400 - WatchTimeMs uint64 `protobuf:"varint,3,opt,name=watch_time_ms,json=watchTimeMs,proto3" json:"watch_time_ms,omitempty"` 401 - UniqueViewers uint64 `protobuf:"varint,4,opt,name=unique_viewers,json=uniqueViewers,proto3" json:"unique_viewers,omitempty"` 402 - unknownFields protoimpl.UnknownFields 403 - sizeCache protoimpl.SizeCache 404 - } 405 - 406 - func (x *DailyStats) Reset() { 407 - *x = DailyStats{} 408 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[5] 409 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 410 - ms.StoreMessageInfo(mi) 411 - } 412 - 413 - func (x *DailyStats) String() string { 414 - return protoimpl.X.MessageStringOf(x) 415 - } 416 - 417 - func (*DailyStats) ProtoMessage() {} 418 - 419 - func (x *DailyStats) ProtoReflect() protoreflect.Message { 420 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[5] 421 - if x != nil { 422 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 423 - if ms.LoadMessageInfo() == nil { 424 - ms.StoreMessageInfo(mi) 425 - } 426 - return ms 427 - } 428 - return mi.MessageOf(x) 429 - } 430 - 431 - // Deprecated: Use DailyStats.ProtoReflect.Descriptor instead. 432 - func (*DailyStats) Descriptor() ([]byte, []int) { 433 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{5} 434 - } 435 - 436 - func (x *DailyStats) GetDate() string { 437 - if x != nil { 438 - return x.Date 439 - } 440 - return "" 441 - } 442 - 443 - func (x *DailyStats) GetViews() uint64 { 444 - if x != nil { 445 - return x.Views 446 - } 447 - return 0 448 - } 449 - 450 - func (x *DailyStats) GetWatchTimeMs() uint64 { 451 - if x != nil { 452 - return x.WatchTimeMs 453 - } 454 - return 0 455 - } 456 - 457 - func (x *DailyStats) GetUniqueViewers() uint64 { 458 - if x != nil { 459 - return x.UniqueViewers 460 - } 461 - return 0 462 - } 463 - 464 - type ViewerHistoryRequest struct { 465 - state protoimpl.MessageState `protogen:"open.v1"` 466 - Did string `protobuf:"bytes,1,opt,name=did,proto3" json:"did,omitempty"` 467 - StartTimeMs *int64 `protobuf:"varint,2,opt,name=start_time_ms,json=startTimeMs,proto3,oneof" json:"start_time_ms,omitempty"` 468 - EndTimeMs *int64 `protobuf:"varint,3,opt,name=end_time_ms,json=endTimeMs,proto3,oneof" json:"end_time_ms,omitempty"` 469 - Limit uint32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"` 470 - unknownFields protoimpl.UnknownFields 471 - sizeCache protoimpl.SizeCache 472 - } 473 - 474 - func (x *ViewerHistoryRequest) Reset() { 475 - *x = ViewerHistoryRequest{} 476 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[6] 477 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 478 - ms.StoreMessageInfo(mi) 479 - } 480 - 481 - func (x *ViewerHistoryRequest) String() string { 482 - return protoimpl.X.MessageStringOf(x) 483 - } 484 - 485 - func (*ViewerHistoryRequest) ProtoMessage() {} 486 - 487 - func (x *ViewerHistoryRequest) ProtoReflect() protoreflect.Message { 488 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[6] 489 - if x != nil { 490 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 491 - if ms.LoadMessageInfo() == nil { 492 - ms.StoreMessageInfo(mi) 493 - } 494 - return ms 495 - } 496 - return mi.MessageOf(x) 497 - } 498 - 499 - // Deprecated: Use ViewerHistoryRequest.ProtoReflect.Descriptor instead. 500 - func (*ViewerHistoryRequest) Descriptor() ([]byte, []int) { 501 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{6} 502 - } 503 - 504 - func (x *ViewerHistoryRequest) GetDid() string { 505 - if x != nil { 506 - return x.Did 507 - } 508 - return "" 509 - } 510 - 511 - func (x *ViewerHistoryRequest) GetStartTimeMs() int64 { 512 - if x != nil && x.StartTimeMs != nil { 513 - return *x.StartTimeMs 514 - } 515 - return 0 516 - } 517 - 518 - func (x *ViewerHistoryRequest) GetEndTimeMs() int64 { 519 - if x != nil && x.EndTimeMs != nil { 520 - return *x.EndTimeMs 521 - } 522 - return 0 523 - } 524 - 525 - func (x *ViewerHistoryRequest) GetLimit() uint32 { 526 - if x != nil { 527 - return x.Limit 528 - } 529 - return 0 530 - } 531 - 532 - type ViewerHistoryResponse struct { 533 - state protoimpl.MessageState `protogen:"open.v1"` 534 - Sessions []*WatchSession `protobuf:"bytes,1,rep,name=sessions,proto3" json:"sessions,omitempty"` 535 - unknownFields protoimpl.UnknownFields 536 - sizeCache protoimpl.SizeCache 537 - } 538 - 539 - func (x *ViewerHistoryResponse) Reset() { 540 - *x = ViewerHistoryResponse{} 541 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[7] 542 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 543 - ms.StoreMessageInfo(mi) 544 - } 545 - 546 - func (x *ViewerHistoryResponse) String() string { 547 - return protoimpl.X.MessageStringOf(x) 548 - } 549 - 550 - func (*ViewerHistoryResponse) ProtoMessage() {} 551 - 552 - func (x *ViewerHistoryResponse) ProtoReflect() protoreflect.Message { 553 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[7] 554 - if x != nil { 555 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 556 - if ms.LoadMessageInfo() == nil { 557 - ms.StoreMessageInfo(mi) 558 - } 559 - return ms 560 - } 561 - return mi.MessageOf(x) 562 - } 563 - 564 - // Deprecated: Use ViewerHistoryResponse.ProtoReflect.Descriptor instead. 565 - func (*ViewerHistoryResponse) Descriptor() ([]byte, []int) { 566 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{7} 567 - } 568 - 569 - func (x *ViewerHistoryResponse) GetSessions() []*WatchSession { 570 - if x != nil { 571 - return x.Sessions 572 - } 573 - return nil 574 - } 575 - 576 - type WatchSession struct { 577 - state protoimpl.MessageState `protogen:"open.v1"` 578 - SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` 579 - StreamerDid string `protobuf:"bytes,2,opt,name=streamer_did,json=streamerDid,proto3" json:"streamer_did,omitempty"` 580 - StreamId *string `protobuf:"bytes,3,opt,name=stream_id,json=streamId,proto3,oneof" json:"stream_id,omitempty"` 581 - StartTimeMs int64 `protobuf:"varint,4,opt,name=start_time_ms,json=startTimeMs,proto3" json:"start_time_ms,omitempty"` 582 - EndTimeMs int64 `protobuf:"varint,5,opt,name=end_time_ms,json=endTimeMs,proto3" json:"end_time_ms,omitempty"` 583 - DurationMs uint64 `protobuf:"varint,6,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` 584 - unknownFields protoimpl.UnknownFields 585 - sizeCache protoimpl.SizeCache 586 - } 587 - 588 - func (x *WatchSession) Reset() { 589 - *x = WatchSession{} 590 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[8] 591 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 592 - ms.StoreMessageInfo(mi) 593 - } 594 - 595 - func (x *WatchSession) String() string { 596 - return protoimpl.X.MessageStringOf(x) 597 - } 598 - 599 - func (*WatchSession) ProtoMessage() {} 600 - 601 - func (x *WatchSession) ProtoReflect() protoreflect.Message { 602 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[8] 603 - if x != nil { 604 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 605 - if ms.LoadMessageInfo() == nil { 606 - ms.StoreMessageInfo(mi) 607 - } 608 - return ms 609 - } 610 - return mi.MessageOf(x) 611 - } 612 - 613 - // Deprecated: Use WatchSession.ProtoReflect.Descriptor instead. 614 - func (*WatchSession) Descriptor() ([]byte, []int) { 615 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{8} 616 - } 617 - 618 - func (x *WatchSession) GetSessionId() string { 619 - if x != nil { 620 - return x.SessionId 621 - } 622 - return "" 623 - } 624 - 625 - func (x *WatchSession) GetStreamerDid() string { 626 - if x != nil { 627 - return x.StreamerDid 628 - } 629 - return "" 630 - } 631 - 632 - func (x *WatchSession) GetStreamId() string { 633 - if x != nil && x.StreamId != nil { 634 - return *x.StreamId 635 - } 636 - return "" 637 - } 638 - 639 - func (x *WatchSession) GetStartTimeMs() int64 { 640 - if x != nil { 641 - return x.StartTimeMs 642 - } 643 - return 0 644 - } 645 - 646 - func (x *WatchSession) GetEndTimeMs() int64 { 647 - if x != nil { 648 - return x.EndTimeMs 649 - } 650 - return 0 651 - } 652 - 653 - func (x *WatchSession) GetDurationMs() uint64 { 654 - if x != nil { 655 - return x.DurationMs 656 - } 657 - return 0 658 - } 659 - 660 - type RealtimeStatsRequest struct { 661 - state protoimpl.MessageState `protogen:"open.v1"` 662 - StreamerDid *string `protobuf:"bytes,1,opt,name=streamer_did,json=streamerDid,proto3,oneof" json:"streamer_did,omitempty"` 663 - WindowMinutes uint32 `protobuf:"varint,2,opt,name=window_minutes,json=windowMinutes,proto3" json:"window_minutes,omitempty"` 664 - unknownFields protoimpl.UnknownFields 665 - sizeCache protoimpl.SizeCache 666 - } 667 - 668 - func (x *RealtimeStatsRequest) Reset() { 669 - *x = RealtimeStatsRequest{} 670 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[9] 671 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 672 - ms.StoreMessageInfo(mi) 673 - } 674 - 675 - func (x *RealtimeStatsRequest) String() string { 676 - return protoimpl.X.MessageStringOf(x) 677 - } 678 - 679 - func (*RealtimeStatsRequest) ProtoMessage() {} 680 - 681 - func (x *RealtimeStatsRequest) ProtoReflect() protoreflect.Message { 682 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[9] 683 - if x != nil { 684 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 685 - if ms.LoadMessageInfo() == nil { 686 - ms.StoreMessageInfo(mi) 687 - } 688 - return ms 689 - } 690 - return mi.MessageOf(x) 691 - } 692 - 693 - // Deprecated: Use RealtimeStatsRequest.ProtoReflect.Descriptor instead. 694 - func (*RealtimeStatsRequest) Descriptor() ([]byte, []int) { 695 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{9} 696 - } 697 - 698 - func (x *RealtimeStatsRequest) GetStreamerDid() string { 699 - if x != nil && x.StreamerDid != nil { 700 - return *x.StreamerDid 701 - } 702 - return "" 703 - } 704 - 705 - func (x *RealtimeStatsRequest) GetWindowMinutes() uint32 { 706 - if x != nil { 707 - return x.WindowMinutes 708 - } 709 - return 0 710 - } 711 - 712 - type RealtimeStatsResponse struct { 713 - state protoimpl.MessageState `protogen:"open.v1"` 714 - Streamers []*StreamerRealtimeStats `protobuf:"bytes,1,rep,name=streamers,proto3" json:"streamers,omitempty"` 715 - unknownFields protoimpl.UnknownFields 716 - sizeCache protoimpl.SizeCache 717 - } 718 - 719 - func (x *RealtimeStatsResponse) Reset() { 720 - *x = RealtimeStatsResponse{} 721 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[10] 722 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 723 - ms.StoreMessageInfo(mi) 724 - } 725 - 726 - func (x *RealtimeStatsResponse) String() string { 727 - return protoimpl.X.MessageStringOf(x) 728 - } 729 - 730 - func (*RealtimeStatsResponse) ProtoMessage() {} 731 - 732 - func (x *RealtimeStatsResponse) ProtoReflect() protoreflect.Message { 733 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[10] 734 - if x != nil { 735 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 736 - if ms.LoadMessageInfo() == nil { 737 - ms.StoreMessageInfo(mi) 738 - } 739 - return ms 740 - } 741 - return mi.MessageOf(x) 742 - } 743 - 744 - // Deprecated: Use RealtimeStatsResponse.ProtoReflect.Descriptor instead. 745 - func (*RealtimeStatsResponse) Descriptor() ([]byte, []int) { 746 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{10} 747 - } 748 - 749 - func (x *RealtimeStatsResponse) GetStreamers() []*StreamerRealtimeStats { 750 - if x != nil { 751 - return x.Streamers 752 - } 753 - return nil 754 - } 755 - 756 - type StreamerRealtimeStats struct { 757 - state protoimpl.MessageState `protogen:"open.v1"` 758 - StreamerDid string `protobuf:"bytes,1,opt,name=streamer_did,json=streamerDid,proto3" json:"streamer_did,omitempty"` 759 - CurrentViewers uint64 `protobuf:"varint,2,opt,name=current_viewers,json=currentViewers,proto3" json:"current_viewers,omitempty"` 760 - TotalWatchTimeMs uint64 `protobuf:"varint,3,opt,name=total_watch_time_ms,json=totalWatchTimeMs,proto3" json:"total_watch_time_ms,omitempty"` 761 - unknownFields protoimpl.UnknownFields 762 - sizeCache protoimpl.SizeCache 763 - } 764 - 765 - func (x *StreamerRealtimeStats) Reset() { 766 - *x = StreamerRealtimeStats{} 767 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[11] 768 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 769 - ms.StoreMessageInfo(mi) 770 - } 771 - 772 - func (x *StreamerRealtimeStats) String() string { 773 - return protoimpl.X.MessageStringOf(x) 774 - } 775 - 776 - func (*StreamerRealtimeStats) ProtoMessage() {} 777 - 778 - func (x *StreamerRealtimeStats) ProtoReflect() protoreflect.Message { 779 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[11] 780 - if x != nil { 781 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 782 - if ms.LoadMessageInfo() == nil { 783 - ms.StoreMessageInfo(mi) 784 - } 785 - return ms 786 - } 787 - return mi.MessageOf(x) 788 - } 789 - 790 - // Deprecated: Use StreamerRealtimeStats.ProtoReflect.Descriptor instead. 791 - func (*StreamerRealtimeStats) Descriptor() ([]byte, []int) { 792 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{11} 793 - } 794 - 795 - func (x *StreamerRealtimeStats) GetStreamerDid() string { 796 - if x != nil { 797 - return x.StreamerDid 798 - } 799 - return "" 800 - } 801 - 802 - func (x *StreamerRealtimeStats) GetCurrentViewers() uint64 { 803 - if x != nil { 804 - return x.CurrentViewers 805 - } 806 - return 0 807 - } 808 - 809 - func (x *StreamerRealtimeStats) GetTotalWatchTimeMs() uint64 { 810 - if x != nil { 811 - return x.TotalWatchTimeMs 812 - } 813 - return 0 814 - } 815 - 816 - type DeleteUserDataRequest struct { 817 - state protoimpl.MessageState `protogen:"open.v1"` 818 - Did string `protobuf:"bytes,1,opt,name=did,proto3" json:"did,omitempty"` 819 - unknownFields protoimpl.UnknownFields 820 - sizeCache protoimpl.SizeCache 821 - } 822 - 823 - func (x *DeleteUserDataRequest) Reset() { 824 - *x = DeleteUserDataRequest{} 825 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[12] 826 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 827 - ms.StoreMessageInfo(mi) 828 - } 829 - 830 - func (x *DeleteUserDataRequest) String() string { 831 - return protoimpl.X.MessageStringOf(x) 832 - } 833 - 834 - func (*DeleteUserDataRequest) ProtoMessage() {} 835 - 836 - func (x *DeleteUserDataRequest) ProtoReflect() protoreflect.Message { 837 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[12] 838 - if x != nil { 839 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 840 - if ms.LoadMessageInfo() == nil { 841 - ms.StoreMessageInfo(mi) 842 - } 843 - return ms 844 - } 845 - return mi.MessageOf(x) 846 - } 847 - 848 - // Deprecated: Use DeleteUserDataRequest.ProtoReflect.Descriptor instead. 849 - func (*DeleteUserDataRequest) Descriptor() ([]byte, []int) { 850 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{12} 851 - } 852 - 853 - func (x *DeleteUserDataRequest) GetDid() string { 854 - if x != nil { 855 - return x.Did 856 - } 857 - return "" 858 - } 859 - 860 - type DeleteUserDataResponse struct { 861 - state protoimpl.MessageState `protogen:"open.v1"` 862 - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` 863 - Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` 864 - unknownFields protoimpl.UnknownFields 865 - sizeCache protoimpl.SizeCache 866 - } 867 - 868 - func (x *DeleteUserDataResponse) Reset() { 869 - *x = DeleteUserDataResponse{} 870 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[13] 871 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 872 - ms.StoreMessageInfo(mi) 873 - } 874 - 875 - func (x *DeleteUserDataResponse) String() string { 876 - return protoimpl.X.MessageStringOf(x) 877 - } 878 - 879 - func (*DeleteUserDataResponse) ProtoMessage() {} 880 - 881 - func (x *DeleteUserDataResponse) ProtoReflect() protoreflect.Message { 882 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[13] 883 - if x != nil { 884 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 885 - if ms.LoadMessageInfo() == nil { 886 - ms.StoreMessageInfo(mi) 887 - } 888 - return ms 889 - } 890 - return mi.MessageOf(x) 891 - } 892 - 893 - // Deprecated: Use DeleteUserDataResponse.ProtoReflect.Descriptor instead. 894 - func (*DeleteUserDataResponse) Descriptor() ([]byte, []int) { 895 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{13} 896 - } 897 - 898 - func (x *DeleteUserDataResponse) GetRequestId() string { 899 - if x != nil { 900 - return x.RequestId 901 - } 902 - return "" 903 - } 904 - 905 - func (x *DeleteUserDataResponse) GetStatus() string { 906 - if x != nil { 907 - return x.Status 908 - } 909 - return "" 910 - } 911 - 912 - type GetDeletionStatusRequest struct { 913 - state protoimpl.MessageState `protogen:"open.v1"` 914 - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` 915 - unknownFields protoimpl.UnknownFields 916 - sizeCache protoimpl.SizeCache 917 - } 918 - 919 - func (x *GetDeletionStatusRequest) Reset() { 920 - *x = GetDeletionStatusRequest{} 921 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[14] 922 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 923 - ms.StoreMessageInfo(mi) 924 - } 925 - 926 - func (x *GetDeletionStatusRequest) String() string { 927 - return protoimpl.X.MessageStringOf(x) 928 - } 929 - 930 - func (*GetDeletionStatusRequest) ProtoMessage() {} 931 - 932 - func (x *GetDeletionStatusRequest) ProtoReflect() protoreflect.Message { 933 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[14] 934 - if x != nil { 935 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 936 - if ms.LoadMessageInfo() == nil { 937 - ms.StoreMessageInfo(mi) 938 - } 939 - return ms 940 - } 941 - return mi.MessageOf(x) 942 - } 943 - 944 - // Deprecated: Use GetDeletionStatusRequest.ProtoReflect.Descriptor instead. 945 - func (*GetDeletionStatusRequest) Descriptor() ([]byte, []int) { 946 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{14} 947 - } 948 - 949 - func (x *GetDeletionStatusRequest) GetRequestId() string { 950 - if x != nil { 951 - return x.RequestId 952 - } 953 - return "" 954 - } 955 - 956 - type DeletionStatusResponse struct { 957 - state protoimpl.MessageState `protogen:"open.v1"` 958 - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` 959 - Did string `protobuf:"bytes,2,opt,name=did,proto3" json:"did,omitempty"` 960 - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` 961 - RequestedAtMs *int64 `protobuf:"varint,4,opt,name=requested_at_ms,json=requestedAtMs,proto3,oneof" json:"requested_at_ms,omitempty"` 962 - CompletedAtMs *int64 `protobuf:"varint,5,opt,name=completed_at_ms,json=completedAtMs,proto3,oneof" json:"completed_at_ms,omitempty"` 963 - unknownFields protoimpl.UnknownFields 964 - sizeCache protoimpl.SizeCache 965 - } 966 - 967 - func (x *DeletionStatusResponse) Reset() { 968 - *x = DeletionStatusResponse{} 969 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[15] 970 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 971 - ms.StoreMessageInfo(mi) 972 - } 973 - 974 - func (x *DeletionStatusResponse) String() string { 975 - return protoimpl.X.MessageStringOf(x) 976 - } 977 - 978 - func (*DeletionStatusResponse) ProtoMessage() {} 979 - 980 - func (x *DeletionStatusResponse) ProtoReflect() protoreflect.Message { 981 - mi := &file_rust_sp_analytics_proto_analytics_proto_msgTypes[15] 982 - if x != nil { 983 - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 984 - if ms.LoadMessageInfo() == nil { 985 - ms.StoreMessageInfo(mi) 986 - } 987 - return ms 988 - } 989 - return mi.MessageOf(x) 990 - } 991 - 992 - // Deprecated: Use DeletionStatusResponse.ProtoReflect.Descriptor instead. 993 - func (*DeletionStatusResponse) Descriptor() ([]byte, []int) { 994 - return file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP(), []int{15} 995 - } 996 - 997 - func (x *DeletionStatusResponse) GetRequestId() string { 998 - if x != nil { 999 - return x.RequestId 1000 - } 1001 - return "" 1002 - } 1003 - 1004 - func (x *DeletionStatusResponse) GetDid() string { 1005 - if x != nil { 1006 - return x.Did 1007 - } 1008 - return "" 1009 - } 1010 - 1011 - func (x *DeletionStatusResponse) GetStatus() string { 1012 - if x != nil { 1013 - return x.Status 1014 - } 1015 - return "" 1016 - } 1017 - 1018 - func (x *DeletionStatusResponse) GetRequestedAtMs() int64 { 1019 - if x != nil && x.RequestedAtMs != nil { 1020 - return *x.RequestedAtMs 1021 - } 1022 - return 0 1023 - } 1024 - 1025 - func (x *DeletionStatusResponse) GetCompletedAtMs() int64 { 1026 - if x != nil && x.CompletedAtMs != nil { 1027 - return *x.CompletedAtMs 1028 - } 1029 - return 0 1030 - } 1031 - 1032 - var File_rust_sp_analytics_proto_analytics_proto protoreflect.FileDescriptor 1033 - 1034 - const file_rust_sp_analytics_proto_analytics_proto_rawDesc = "" + 1035 - "\n" + 1036 - "'rust/sp-analytics/proto/analytics.proto\x12\tanalytics\"?\n" + 1037 - "\x13IngestEventsRequest\x12(\n" + 1038 - "\x06events\x18\x01 \x03(\v2\x10.analytics.EventR\x06events\"f\n" + 1039 - "\x14IngestEventsResponse\x12\x1a\n" + 1040 - "\baccepted\x18\x01 \x01(\rR\baccepted\x12\x1a\n" + 1041 - "\brejected\x18\x02 \x01(\rR\brejected\x12\x16\n" + 1042 - "\x06errors\x18\x03 \x03(\tR\x06errors\"\xa5\x03\n" + 1043 - "\x05Event\x12\x19\n" + 1044 - "\bevent_id\x18\x01 \x01(\tR\aeventId\x12\x1d\n" + 1045 - "\n" + 1046 - "event_type\x18\x02 \x01(\tR\teventType\x12\x1b\n" + 1047 - "\tdevice_id\x18\x03 \x01(\tR\bdeviceId\x12\x15\n" + 1048 - "\x03did\x18\x04 \x01(\tH\x00R\x03did\x88\x01\x01\x12\x1d\n" + 1049 - "\n" + 1050 - "session_id\x18\x05 \x01(\tR\tsessionId\x12!\n" + 1051 - "\ftimestamp_ms\x18\x06 \x01(\x03R\vtimestampMs\x12!\n" + 1052 - "\fstreamer_did\x18\a \x01(\tR\vstreamerDid\x12 \n" + 1053 - "\tstream_id\x18\b \x01(\tH\x01R\bstreamId\x88\x01\x01\x12'\n" + 1054 - "\x0fproperties_json\x18\t \x01(\tR\x0epropertiesJson\x12%\n" + 1055 - "\x0eschema_version\x18\n" + 1056 - " \x01(\rR\rschemaVersion\x12%\n" + 1057 - "\x0eclient_version\x18\v \x01(\tR\rclientVersion\x12\x1a\n" + 1058 - "\bplatform\x18\f \x01(\tR\bplatformB\x06\n" + 1059 - "\x04_didB\f\n" + 1060 - "\n" + 1061 - "_stream_id\"\xa9\x01\n" + 1062 - "\x14StreamerStatsRequest\x12!\n" + 1063 - "\fstreamer_did\x18\x01 \x01(\tR\vstreamerDid\x12'\n" + 1064 - "\rstart_time_ms\x18\x02 \x01(\x03H\x00R\vstartTimeMs\x88\x01\x01\x12#\n" + 1065 - "\vend_time_ms\x18\x03 \x01(\x03H\x01R\tendTimeMs\x88\x01\x01B\x10\n" + 1066 - "\x0e_start_time_msB\x0e\n" + 1067 - "\f_end_time_ms\"\xe9\x01\n" + 1068 - "\x15StreamerStatsResponse\x12!\n" + 1069 - "\fstreamer_did\x18\x01 \x01(\tR\vstreamerDid\x12\x1f\n" + 1070 - "\vtotal_views\x18\x02 \x01(\x04R\n" + 1071 - "totalViews\x12-\n" + 1072 - "\x13total_watch_time_ms\x18\x03 \x01(\x04R\x10totalWatchTimeMs\x12%\n" + 1073 - "\x0eunique_viewers\x18\x04 \x01(\x04R\runiqueViewers\x126\n" + 1074 - "\vdaily_stats\x18\x05 \x03(\v2\x15.analytics.DailyStatsR\n" + 1075 - "dailyStats\"\x81\x01\n" + 1076 - "\n" + 1077 - "DailyStats\x12\x12\n" + 1078 - "\x04date\x18\x01 \x01(\tR\x04date\x12\x14\n" + 1079 - "\x05views\x18\x02 \x01(\x04R\x05views\x12\"\n" + 1080 - "\rwatch_time_ms\x18\x03 \x01(\x04R\vwatchTimeMs\x12%\n" + 1081 - "\x0eunique_viewers\x18\x04 \x01(\x04R\runiqueViewers\"\xae\x01\n" + 1082 - "\x14ViewerHistoryRequest\x12\x10\n" + 1083 - "\x03did\x18\x01 \x01(\tR\x03did\x12'\n" + 1084 - "\rstart_time_ms\x18\x02 \x01(\x03H\x00R\vstartTimeMs\x88\x01\x01\x12#\n" + 1085 - "\vend_time_ms\x18\x03 \x01(\x03H\x01R\tendTimeMs\x88\x01\x01\x12\x14\n" + 1086 - "\x05limit\x18\x04 \x01(\rR\x05limitB\x10\n" + 1087 - "\x0e_start_time_msB\x0e\n" + 1088 - "\f_end_time_ms\"L\n" + 1089 - "\x15ViewerHistoryResponse\x123\n" + 1090 - "\bsessions\x18\x01 \x03(\v2\x17.analytics.WatchSessionR\bsessions\"\xe5\x01\n" + 1091 - "\fWatchSession\x12\x1d\n" + 1092 - "\n" + 1093 - "session_id\x18\x01 \x01(\tR\tsessionId\x12!\n" + 1094 - "\fstreamer_did\x18\x02 \x01(\tR\vstreamerDid\x12 \n" + 1095 - "\tstream_id\x18\x03 \x01(\tH\x00R\bstreamId\x88\x01\x01\x12\"\n" + 1096 - "\rstart_time_ms\x18\x04 \x01(\x03R\vstartTimeMs\x12\x1e\n" + 1097 - "\vend_time_ms\x18\x05 \x01(\x03R\tendTimeMs\x12\x1f\n" + 1098 - "\vduration_ms\x18\x06 \x01(\x04R\n" + 1099 - "durationMsB\f\n" + 1100 - "\n" + 1101 - "_stream_id\"v\n" + 1102 - "\x14RealtimeStatsRequest\x12&\n" + 1103 - "\fstreamer_did\x18\x01 \x01(\tH\x00R\vstreamerDid\x88\x01\x01\x12%\n" + 1104 - "\x0ewindow_minutes\x18\x02 \x01(\rR\rwindowMinutesB\x0f\n" + 1105 - "\r_streamer_did\"W\n" + 1106 - "\x15RealtimeStatsResponse\x12>\n" + 1107 - "\tstreamers\x18\x01 \x03(\v2 .analytics.StreamerRealtimeStatsR\tstreamers\"\x92\x01\n" + 1108 - "\x15StreamerRealtimeStats\x12!\n" + 1109 - "\fstreamer_did\x18\x01 \x01(\tR\vstreamerDid\x12'\n" + 1110 - "\x0fcurrent_viewers\x18\x02 \x01(\x04R\x0ecurrentViewers\x12-\n" + 1111 - "\x13total_watch_time_ms\x18\x03 \x01(\x04R\x10totalWatchTimeMs\")\n" + 1112 - "\x15DeleteUserDataRequest\x12\x10\n" + 1113 - "\x03did\x18\x01 \x01(\tR\x03did\"O\n" + 1114 - "\x16DeleteUserDataResponse\x12\x1d\n" + 1115 - "\n" + 1116 - "request_id\x18\x01 \x01(\tR\trequestId\x12\x16\n" + 1117 - "\x06status\x18\x02 \x01(\tR\x06status\"9\n" + 1118 - "\x18GetDeletionStatusRequest\x12\x1d\n" + 1119 - "\n" + 1120 - "request_id\x18\x01 \x01(\tR\trequestId\"\xe3\x01\n" + 1121 - "\x16DeletionStatusResponse\x12\x1d\n" + 1122 - "\n" + 1123 - "request_id\x18\x01 \x01(\tR\trequestId\x12\x10\n" + 1124 - "\x03did\x18\x02 \x01(\tR\x03did\x12\x16\n" + 1125 - "\x06status\x18\x03 \x01(\tR\x06status\x12+\n" + 1126 - "\x0frequested_at_ms\x18\x04 \x01(\x03H\x00R\rrequestedAtMs\x88\x01\x01\x12+\n" + 1127 - "\x0fcompleted_at_ms\x18\x05 \x01(\x03H\x01R\rcompletedAtMs\x88\x01\x01B\x12\n" + 1128 - "\x10_requested_at_msB\x12\n" + 1129 - "\x10_completed_at_ms2\x95\x04\n" + 1130 - "\tAnalytics\x12O\n" + 1131 - "\fIngestEvents\x12\x1e.analytics.IngestEventsRequest\x1a\x1f.analytics.IngestEventsResponse\x12U\n" + 1132 - "\x10GetStreamerStats\x12\x1f.analytics.StreamerStatsRequest\x1a .analytics.StreamerStatsResponse\x12U\n" + 1133 - "\x10GetViewerHistory\x12\x1f.analytics.ViewerHistoryRequest\x1a .analytics.ViewerHistoryResponse\x12U\n" + 1134 - "\x10GetRealtimeStats\x12\x1f.analytics.RealtimeStatsRequest\x1a .analytics.RealtimeStatsResponse\x12U\n" + 1135 - "\x0eDeleteUserData\x12 .analytics.DeleteUserDataRequest\x1a!.analytics.DeleteUserDataResponse\x12[\n" + 1136 - "\x11GetDeletionStatus\x12#.analytics.GetDeletionStatusRequest\x1a!.analytics.DeletionStatusResponseB!Z\x1fstreamplace/pkg/analytics/pb;pbb\x06proto3" 1137 - 1138 - var ( 1139 - file_rust_sp_analytics_proto_analytics_proto_rawDescOnce sync.Once 1140 - file_rust_sp_analytics_proto_analytics_proto_rawDescData []byte 1141 - ) 1142 - 1143 - func file_rust_sp_analytics_proto_analytics_proto_rawDescGZIP() []byte { 1144 - file_rust_sp_analytics_proto_analytics_proto_rawDescOnce.Do(func() { 1145 - file_rust_sp_analytics_proto_analytics_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_rust_sp_analytics_proto_analytics_proto_rawDesc), len(file_rust_sp_analytics_proto_analytics_proto_rawDesc))) 1146 - }) 1147 - return file_rust_sp_analytics_proto_analytics_proto_rawDescData 1148 - } 1149 - 1150 - var file_rust_sp_analytics_proto_analytics_proto_msgTypes = make([]protoimpl.MessageInfo, 16) 1151 - var file_rust_sp_analytics_proto_analytics_proto_goTypes = []any{ 1152 - (*IngestEventsRequest)(nil), // 0: analytics.IngestEventsRequest 1153 - (*IngestEventsResponse)(nil), // 1: analytics.IngestEventsResponse 1154 - (*Event)(nil), // 2: analytics.Event 1155 - (*StreamerStatsRequest)(nil), // 3: analytics.StreamerStatsRequest 1156 - (*StreamerStatsResponse)(nil), // 4: analytics.StreamerStatsResponse 1157 - (*DailyStats)(nil), // 5: analytics.DailyStats 1158 - (*ViewerHistoryRequest)(nil), // 6: analytics.ViewerHistoryRequest 1159 - (*ViewerHistoryResponse)(nil), // 7: analytics.ViewerHistoryResponse 1160 - (*WatchSession)(nil), // 8: analytics.WatchSession 1161 - (*RealtimeStatsRequest)(nil), // 9: analytics.RealtimeStatsRequest 1162 - (*RealtimeStatsResponse)(nil), // 10: analytics.RealtimeStatsResponse 1163 - (*StreamerRealtimeStats)(nil), // 11: analytics.StreamerRealtimeStats 1164 - (*DeleteUserDataRequest)(nil), // 12: analytics.DeleteUserDataRequest 1165 - (*DeleteUserDataResponse)(nil), // 13: analytics.DeleteUserDataResponse 1166 - (*GetDeletionStatusRequest)(nil), // 14: analytics.GetDeletionStatusRequest 1167 - (*DeletionStatusResponse)(nil), // 15: analytics.DeletionStatusResponse 1168 - } 1169 - var file_rust_sp_analytics_proto_analytics_proto_depIdxs = []int32{ 1170 - 2, // 0: analytics.IngestEventsRequest.events:type_name -> analytics.Event 1171 - 5, // 1: analytics.StreamerStatsResponse.daily_stats:type_name -> analytics.DailyStats 1172 - 8, // 2: analytics.ViewerHistoryResponse.sessions:type_name -> analytics.WatchSession 1173 - 11, // 3: analytics.RealtimeStatsResponse.streamers:type_name -> analytics.StreamerRealtimeStats 1174 - 0, // 4: analytics.Analytics.IngestEvents:input_type -> analytics.IngestEventsRequest 1175 - 3, // 5: analytics.Analytics.GetStreamerStats:input_type -> analytics.StreamerStatsRequest 1176 - 6, // 6: analytics.Analytics.GetViewerHistory:input_type -> analytics.ViewerHistoryRequest 1177 - 9, // 7: analytics.Analytics.GetRealtimeStats:input_type -> analytics.RealtimeStatsRequest 1178 - 12, // 8: analytics.Analytics.DeleteUserData:input_type -> analytics.DeleteUserDataRequest 1179 - 14, // 9: analytics.Analytics.GetDeletionStatus:input_type -> analytics.GetDeletionStatusRequest 1180 - 1, // 10: analytics.Analytics.IngestEvents:output_type -> analytics.IngestEventsResponse 1181 - 4, // 11: analytics.Analytics.GetStreamerStats:output_type -> analytics.StreamerStatsResponse 1182 - 7, // 12: analytics.Analytics.GetViewerHistory:output_type -> analytics.ViewerHistoryResponse 1183 - 10, // 13: analytics.Analytics.GetRealtimeStats:output_type -> analytics.RealtimeStatsResponse 1184 - 13, // 14: analytics.Analytics.DeleteUserData:output_type -> analytics.DeleteUserDataResponse 1185 - 15, // 15: analytics.Analytics.GetDeletionStatus:output_type -> analytics.DeletionStatusResponse 1186 - 10, // [10:16] is the sub-list for method output_type 1187 - 4, // [4:10] is the sub-list for method input_type 1188 - 4, // [4:4] is the sub-list for extension type_name 1189 - 4, // [4:4] is the sub-list for extension extendee 1190 - 0, // [0:4] is the sub-list for field type_name 1191 - } 1192 - 1193 - func init() { file_rust_sp_analytics_proto_analytics_proto_init() } 1194 - func file_rust_sp_analytics_proto_analytics_proto_init() { 1195 - if File_rust_sp_analytics_proto_analytics_proto != nil { 1196 - return 1197 - } 1198 - file_rust_sp_analytics_proto_analytics_proto_msgTypes[2].OneofWrappers = []any{} 1199 - file_rust_sp_analytics_proto_analytics_proto_msgTypes[3].OneofWrappers = []any{} 1200 - file_rust_sp_analytics_proto_analytics_proto_msgTypes[6].OneofWrappers = []any{} 1201 - file_rust_sp_analytics_proto_analytics_proto_msgTypes[8].OneofWrappers = []any{} 1202 - file_rust_sp_analytics_proto_analytics_proto_msgTypes[9].OneofWrappers = []any{} 1203 - file_rust_sp_analytics_proto_analytics_proto_msgTypes[15].OneofWrappers = []any{} 1204 - type x struct{} 1205 - out := protoimpl.TypeBuilder{ 1206 - File: protoimpl.DescBuilder{ 1207 - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 1208 - RawDescriptor: unsafe.Slice(unsafe.StringData(file_rust_sp_analytics_proto_analytics_proto_rawDesc), len(file_rust_sp_analytics_proto_analytics_proto_rawDesc)), 1209 - NumEnums: 0, 1210 - NumMessages: 16, 1211 - NumExtensions: 0, 1212 - NumServices: 1, 1213 - }, 1214 - GoTypes: file_rust_sp_analytics_proto_analytics_proto_goTypes, 1215 - DependencyIndexes: file_rust_sp_analytics_proto_analytics_proto_depIdxs, 1216 - MessageInfos: file_rust_sp_analytics_proto_analytics_proto_msgTypes, 1217 - }.Build() 1218 - File_rust_sp_analytics_proto_analytics_proto = out.File 1219 - file_rust_sp_analytics_proto_analytics_proto_goTypes = nil 1220 - file_rust_sp_analytics_proto_analytics_proto_depIdxs = nil 1221 - }
···
-311
pkg/analytics/pb/analytics_grpc.pb.go
··· 1 - // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 - // versions: 3 - // - protoc-gen-go-grpc v1.6.0 4 - // - protoc v6.33.3 5 - // source: rust/sp-analytics/proto/analytics.proto 6 - 7 - package pb 8 - 9 - import ( 10 - context "context" 11 - grpc "google.golang.org/grpc" 12 - codes "google.golang.org/grpc/codes" 13 - status "google.golang.org/grpc/status" 14 - ) 15 - 16 - // This is a compile-time assertion to ensure that this generated file 17 - // is compatible with the grpc package it is being compiled against. 18 - // Requires gRPC-Go v1.64.0 or later. 19 - const _ = grpc.SupportPackageIsVersion9 20 - 21 - const ( 22 - Analytics_IngestEvents_FullMethodName = "/analytics.Analytics/IngestEvents" 23 - Analytics_GetStreamerStats_FullMethodName = "/analytics.Analytics/GetStreamerStats" 24 - Analytics_GetViewerHistory_FullMethodName = "/analytics.Analytics/GetViewerHistory" 25 - Analytics_GetRealtimeStats_FullMethodName = "/analytics.Analytics/GetRealtimeStats" 26 - Analytics_DeleteUserData_FullMethodName = "/analytics.Analytics/DeleteUserData" 27 - Analytics_GetDeletionStatus_FullMethodName = "/analytics.Analytics/GetDeletionStatus" 28 - ) 29 - 30 - // AnalyticsClient is the client API for Analytics service. 31 - // 32 - // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 33 - type AnalyticsClient interface { 34 - IngestEvents(ctx context.Context, in *IngestEventsRequest, opts ...grpc.CallOption) (*IngestEventsResponse, error) 35 - GetStreamerStats(ctx context.Context, in *StreamerStatsRequest, opts ...grpc.CallOption) (*StreamerStatsResponse, error) 36 - GetViewerHistory(ctx context.Context, in *ViewerHistoryRequest, opts ...grpc.CallOption) (*ViewerHistoryResponse, error) 37 - GetRealtimeStats(ctx context.Context, in *RealtimeStatsRequest, opts ...grpc.CallOption) (*RealtimeStatsResponse, error) 38 - DeleteUserData(ctx context.Context, in *DeleteUserDataRequest, opts ...grpc.CallOption) (*DeleteUserDataResponse, error) 39 - GetDeletionStatus(ctx context.Context, in *GetDeletionStatusRequest, opts ...grpc.CallOption) (*DeletionStatusResponse, error) 40 - } 41 - 42 - type analyticsClient struct { 43 - cc grpc.ClientConnInterface 44 - } 45 - 46 - func NewAnalyticsClient(cc grpc.ClientConnInterface) AnalyticsClient { 47 - return &analyticsClient{cc} 48 - } 49 - 50 - func (c *analyticsClient) IngestEvents(ctx context.Context, in *IngestEventsRequest, opts ...grpc.CallOption) (*IngestEventsResponse, error) { 51 - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 52 - out := new(IngestEventsResponse) 53 - err := c.cc.Invoke(ctx, Analytics_IngestEvents_FullMethodName, in, out, cOpts...) 54 - if err != nil { 55 - return nil, err 56 - } 57 - return out, nil 58 - } 59 - 60 - func (c *analyticsClient) GetStreamerStats(ctx context.Context, in *StreamerStatsRequest, opts ...grpc.CallOption) (*StreamerStatsResponse, error) { 61 - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 62 - out := new(StreamerStatsResponse) 63 - err := c.cc.Invoke(ctx, Analytics_GetStreamerStats_FullMethodName, in, out, cOpts...) 64 - if err != nil { 65 - return nil, err 66 - } 67 - return out, nil 68 - } 69 - 70 - func (c *analyticsClient) GetViewerHistory(ctx context.Context, in *ViewerHistoryRequest, opts ...grpc.CallOption) (*ViewerHistoryResponse, error) { 71 - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 72 - out := new(ViewerHistoryResponse) 73 - err := c.cc.Invoke(ctx, Analytics_GetViewerHistory_FullMethodName, in, out, cOpts...) 74 - if err != nil { 75 - return nil, err 76 - } 77 - return out, nil 78 - } 79 - 80 - func (c *analyticsClient) GetRealtimeStats(ctx context.Context, in *RealtimeStatsRequest, opts ...grpc.CallOption) (*RealtimeStatsResponse, error) { 81 - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 82 - out := new(RealtimeStatsResponse) 83 - err := c.cc.Invoke(ctx, Analytics_GetRealtimeStats_FullMethodName, in, out, cOpts...) 84 - if err != nil { 85 - return nil, err 86 - } 87 - return out, nil 88 - } 89 - 90 - func (c *analyticsClient) DeleteUserData(ctx context.Context, in *DeleteUserDataRequest, opts ...grpc.CallOption) (*DeleteUserDataResponse, error) { 91 - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 92 - out := new(DeleteUserDataResponse) 93 - err := c.cc.Invoke(ctx, Analytics_DeleteUserData_FullMethodName, in, out, cOpts...) 94 - if err != nil { 95 - return nil, err 96 - } 97 - return out, nil 98 - } 99 - 100 - func (c *analyticsClient) GetDeletionStatus(ctx context.Context, in *GetDeletionStatusRequest, opts ...grpc.CallOption) (*DeletionStatusResponse, error) { 101 - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 102 - out := new(DeletionStatusResponse) 103 - err := c.cc.Invoke(ctx, Analytics_GetDeletionStatus_FullMethodName, in, out, cOpts...) 104 - if err != nil { 105 - return nil, err 106 - } 107 - return out, nil 108 - } 109 - 110 - // AnalyticsServer is the server API for Analytics service. 111 - // All implementations must embed UnimplementedAnalyticsServer 112 - // for forward compatibility. 113 - type AnalyticsServer interface { 114 - IngestEvents(context.Context, *IngestEventsRequest) (*IngestEventsResponse, error) 115 - GetStreamerStats(context.Context, *StreamerStatsRequest) (*StreamerStatsResponse, error) 116 - GetViewerHistory(context.Context, *ViewerHistoryRequest) (*ViewerHistoryResponse, error) 117 - GetRealtimeStats(context.Context, *RealtimeStatsRequest) (*RealtimeStatsResponse, error) 118 - DeleteUserData(context.Context, *DeleteUserDataRequest) (*DeleteUserDataResponse, error) 119 - GetDeletionStatus(context.Context, *GetDeletionStatusRequest) (*DeletionStatusResponse, error) 120 - mustEmbedUnimplementedAnalyticsServer() 121 - } 122 - 123 - // UnimplementedAnalyticsServer must be embedded to have 124 - // forward compatible implementations. 125 - // 126 - // NOTE: this should be embedded by value instead of pointer to avoid a nil 127 - // pointer dereference when methods are called. 128 - type UnimplementedAnalyticsServer struct{} 129 - 130 - func (UnimplementedAnalyticsServer) IngestEvents(context.Context, *IngestEventsRequest) (*IngestEventsResponse, error) { 131 - return nil, status.Error(codes.Unimplemented, "method IngestEvents not implemented") 132 - } 133 - func (UnimplementedAnalyticsServer) GetStreamerStats(context.Context, *StreamerStatsRequest) (*StreamerStatsResponse, error) { 134 - return nil, status.Error(codes.Unimplemented, "method GetStreamerStats not implemented") 135 - } 136 - func (UnimplementedAnalyticsServer) GetViewerHistory(context.Context, *ViewerHistoryRequest) (*ViewerHistoryResponse, error) { 137 - return nil, status.Error(codes.Unimplemented, "method GetViewerHistory not implemented") 138 - } 139 - func (UnimplementedAnalyticsServer) GetRealtimeStats(context.Context, *RealtimeStatsRequest) (*RealtimeStatsResponse, error) { 140 - return nil, status.Error(codes.Unimplemented, "method GetRealtimeStats not implemented") 141 - } 142 - func (UnimplementedAnalyticsServer) DeleteUserData(context.Context, *DeleteUserDataRequest) (*DeleteUserDataResponse, error) { 143 - return nil, status.Error(codes.Unimplemented, "method DeleteUserData not implemented") 144 - } 145 - func (UnimplementedAnalyticsServer) GetDeletionStatus(context.Context, *GetDeletionStatusRequest) (*DeletionStatusResponse, error) { 146 - return nil, status.Error(codes.Unimplemented, "method GetDeletionStatus not implemented") 147 - } 148 - func (UnimplementedAnalyticsServer) mustEmbedUnimplementedAnalyticsServer() {} 149 - func (UnimplementedAnalyticsServer) testEmbeddedByValue() {} 150 - 151 - // UnsafeAnalyticsServer may be embedded to opt out of forward compatibility for this service. 152 - // Use of this interface is not recommended, as added methods to AnalyticsServer will 153 - // result in compilation errors. 154 - type UnsafeAnalyticsServer interface { 155 - mustEmbedUnimplementedAnalyticsServer() 156 - } 157 - 158 - func RegisterAnalyticsServer(s grpc.ServiceRegistrar, srv AnalyticsServer) { 159 - // If the following call panics, it indicates UnimplementedAnalyticsServer was 160 - // embedded by pointer and is nil. This will cause panics if an 161 - // unimplemented method is ever invoked, so we test this at initialization 162 - // time to prevent it from happening at runtime later due to I/O. 163 - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { 164 - t.testEmbeddedByValue() 165 - } 166 - s.RegisterService(&Analytics_ServiceDesc, srv) 167 - } 168 - 169 - func _Analytics_IngestEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 170 - in := new(IngestEventsRequest) 171 - if err := dec(in); err != nil { 172 - return nil, err 173 - } 174 - if interceptor == nil { 175 - return srv.(AnalyticsServer).IngestEvents(ctx, in) 176 - } 177 - info := &grpc.UnaryServerInfo{ 178 - Server: srv, 179 - FullMethod: Analytics_IngestEvents_FullMethodName, 180 - } 181 - handler := func(ctx context.Context, req interface{}) (interface{}, error) { 182 - return srv.(AnalyticsServer).IngestEvents(ctx, req.(*IngestEventsRequest)) 183 - } 184 - return interceptor(ctx, in, info, handler) 185 - } 186 - 187 - func _Analytics_GetStreamerStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 188 - in := new(StreamerStatsRequest) 189 - if err := dec(in); err != nil { 190 - return nil, err 191 - } 192 - if interceptor == nil { 193 - return srv.(AnalyticsServer).GetStreamerStats(ctx, in) 194 - } 195 - info := &grpc.UnaryServerInfo{ 196 - Server: srv, 197 - FullMethod: Analytics_GetStreamerStats_FullMethodName, 198 - } 199 - handler := func(ctx context.Context, req interface{}) (interface{}, error) { 200 - return srv.(AnalyticsServer).GetStreamerStats(ctx, req.(*StreamerStatsRequest)) 201 - } 202 - return interceptor(ctx, in, info, handler) 203 - } 204 - 205 - func _Analytics_GetViewerHistory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 206 - in := new(ViewerHistoryRequest) 207 - if err := dec(in); err != nil { 208 - return nil, err 209 - } 210 - if interceptor == nil { 211 - return srv.(AnalyticsServer).GetViewerHistory(ctx, in) 212 - } 213 - info := &grpc.UnaryServerInfo{ 214 - Server: srv, 215 - FullMethod: Analytics_GetViewerHistory_FullMethodName, 216 - } 217 - handler := func(ctx context.Context, req interface{}) (interface{}, error) { 218 - return srv.(AnalyticsServer).GetViewerHistory(ctx, req.(*ViewerHistoryRequest)) 219 - } 220 - return interceptor(ctx, in, info, handler) 221 - } 222 - 223 - func _Analytics_GetRealtimeStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 224 - in := new(RealtimeStatsRequest) 225 - if err := dec(in); err != nil { 226 - return nil, err 227 - } 228 - if interceptor == nil { 229 - return srv.(AnalyticsServer).GetRealtimeStats(ctx, in) 230 - } 231 - info := &grpc.UnaryServerInfo{ 232 - Server: srv, 233 - FullMethod: Analytics_GetRealtimeStats_FullMethodName, 234 - } 235 - handler := func(ctx context.Context, req interface{}) (interface{}, error) { 236 - return srv.(AnalyticsServer).GetRealtimeStats(ctx, req.(*RealtimeStatsRequest)) 237 - } 238 - return interceptor(ctx, in, info, handler) 239 - } 240 - 241 - func _Analytics_DeleteUserData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 242 - in := new(DeleteUserDataRequest) 243 - if err := dec(in); err != nil { 244 - return nil, err 245 - } 246 - if interceptor == nil { 247 - return srv.(AnalyticsServer).DeleteUserData(ctx, in) 248 - } 249 - info := &grpc.UnaryServerInfo{ 250 - Server: srv, 251 - FullMethod: Analytics_DeleteUserData_FullMethodName, 252 - } 253 - handler := func(ctx context.Context, req interface{}) (interface{}, error) { 254 - return srv.(AnalyticsServer).DeleteUserData(ctx, req.(*DeleteUserDataRequest)) 255 - } 256 - return interceptor(ctx, in, info, handler) 257 - } 258 - 259 - func _Analytics_GetDeletionStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 260 - in := new(GetDeletionStatusRequest) 261 - if err := dec(in); err != nil { 262 - return nil, err 263 - } 264 - if interceptor == nil { 265 - return srv.(AnalyticsServer).GetDeletionStatus(ctx, in) 266 - } 267 - info := &grpc.UnaryServerInfo{ 268 - Server: srv, 269 - FullMethod: Analytics_GetDeletionStatus_FullMethodName, 270 - } 271 - handler := func(ctx context.Context, req interface{}) (interface{}, error) { 272 - return srv.(AnalyticsServer).GetDeletionStatus(ctx, req.(*GetDeletionStatusRequest)) 273 - } 274 - return interceptor(ctx, in, info, handler) 275 - } 276 - 277 - // Analytics_ServiceDesc is the grpc.ServiceDesc for Analytics service. 278 - // It's only intended for direct use with grpc.RegisterService, 279 - // and not to be introspected or modified (even as a copy) 280 - var Analytics_ServiceDesc = grpc.ServiceDesc{ 281 - ServiceName: "analytics.Analytics", 282 - HandlerType: (*AnalyticsServer)(nil), 283 - Methods: []grpc.MethodDesc{ 284 - { 285 - MethodName: "IngestEvents", 286 - Handler: _Analytics_IngestEvents_Handler, 287 - }, 288 - { 289 - MethodName: "GetStreamerStats", 290 - Handler: _Analytics_GetStreamerStats_Handler, 291 - }, 292 - { 293 - MethodName: "GetViewerHistory", 294 - Handler: _Analytics_GetViewerHistory_Handler, 295 - }, 296 - { 297 - MethodName: "GetRealtimeStats", 298 - Handler: _Analytics_GetRealtimeStats_Handler, 299 - }, 300 - { 301 - MethodName: "DeleteUserData", 302 - Handler: _Analytics_DeleteUserData_Handler, 303 - }, 304 - { 305 - MethodName: "GetDeletionStatus", 306 - Handler: _Analytics_GetDeletionStatus_Handler, 307 - }, 308 - }, 309 - Streams: []grpc.StreamDesc{}, 310 - Metadata: "rust/sp-analytics/proto/analytics.proto", 311 - }
···
-153
pkg/analytics/types.go
··· 1 - package analytics 2 - 3 - import ( 4 - pb "stream.place/streamplace/pkg/analytics/pb" 5 - ) 6 - 7 - // Event represents an analytics event to be ingested 8 - type Event struct { 9 - EventID string 10 - EventType string 11 - DeviceID string 12 - DID *string 13 - SessionID string 14 - TimestampMs int64 15 - StreamerDID string 16 - StreamID *string 17 - PropertiesJSON string 18 - SchemaVersion uint16 19 - ClientVersion string 20 - Platform string 21 - } 22 - 23 - // RealtimeStatsRequest requests real-time statistics 24 - type RealtimeStatsRequest struct { 25 - StreamerDid *string 26 - WindowMinutes uint32 27 - } 28 - 29 - // RealtimeStatsResponse contains real-time statistics 30 - type RealtimeStatsResponse struct { 31 - Streamers []StreamerRealtimeStats `json:"streamers"` 32 - } 33 - 34 - // StreamerRealtimeStats contains real-time stats for a single streamer 35 - type StreamerRealtimeStats struct { 36 - StreamerDid string `json:"streamerDid"` 37 - CurrentViewers uint64 `json:"currentViewers"` 38 - TotalWatchTimeMs uint64 `json:"totalWatchTimeMs"` 39 - } 40 - 41 - // StreamerStatsRequest requests stats for a specific streamer 42 - type StreamerStatsRequest struct { 43 - StreamerDid string 44 - StartTimeMs *int64 45 - EndTimeMs *int64 46 - } 47 - 48 - // StreamerStatsResponse contains aggregated stats for a streamer 49 - type StreamerStatsResponse struct { 50 - StreamerDid string `json:"streamerDid"` 51 - TotalViews uint64 `json:"totalViews"` 52 - TotalWatchTimeMs uint64 `json:"totalWatchTimeMs"` 53 - UniqueViewers uint64 `json:"uniqueViewers"` 54 - DailyStats []DailyStats `json:"dailyStats"` 55 - } 56 - 57 - // DailyStats contains stats for a single day 58 - type DailyStats struct { 59 - Date string `json:"date"` 60 - Views uint64 `json:"views"` 61 - WatchTimeMs uint64 `json:"watchTimeMs"` 62 - UniqueViewers uint64 `json:"uniqueViewers"` 63 - } 64 - 65 - // ViewerHistoryRequest requests viewing history for a user 66 - type ViewerHistoryRequest struct { 67 - Did string 68 - StartTimeMs *int64 69 - EndTimeMs *int64 70 - Limit uint32 71 - } 72 - 73 - // ViewerHistoryResponse contains viewing history 74 - type ViewerHistoryResponse struct { 75 - Sessions []WatchSession `json:"sessions"` 76 - } 77 - 78 - // WatchSession represents a single viewing session 79 - type WatchSession struct { 80 - SessionId string `json:"sessionId"` 81 - StreamerDid string `json:"streamerDid"` 82 - StreamId *string `json:"streamId,omitempty"` 83 - StartTimeMs int64 `json:"startTimeMs"` 84 - EndTimeMs int64 `json:"endTimeMs"` 85 - DurationMs uint64 `json:"durationMs"` 86 - } 87 - 88 - // Conversion helpers 89 - 90 - func convertRealtimeStatsResponse(pbResp *pb.RealtimeStatsResponse) *RealtimeStatsResponse { 91 - if pbResp == nil { 92 - return &RealtimeStatsResponse{} 93 - } 94 - 95 - streamers := make([]StreamerRealtimeStats, len(pbResp.Streamers)) 96 - for i, s := range pbResp.Streamers { 97 - streamers[i] = StreamerRealtimeStats{ 98 - StreamerDid: s.StreamerDid, 99 - CurrentViewers: s.CurrentViewers, 100 - TotalWatchTimeMs: s.TotalWatchTimeMs, 101 - } 102 - } 103 - 104 - return &RealtimeStatsResponse{ 105 - Streamers: streamers, 106 - } 107 - } 108 - 109 - func convertStreamerStatsResponse(pbResp *pb.StreamerStatsResponse) *StreamerStatsResponse { 110 - if pbResp == nil { 111 - return &StreamerStatsResponse{} 112 - } 113 - 114 - dailyStats := make([]DailyStats, len(pbResp.DailyStats)) 115 - for i, s := range pbResp.DailyStats { 116 - dailyStats[i] = DailyStats{ 117 - Date: s.Date, 118 - Views: s.Views, 119 - WatchTimeMs: s.WatchTimeMs, 120 - UniqueViewers: s.UniqueViewers, 121 - } 122 - } 123 - 124 - return &StreamerStatsResponse{ 125 - StreamerDid: pbResp.StreamerDid, 126 - TotalViews: pbResp.TotalViews, 127 - TotalWatchTimeMs: pbResp.TotalWatchTimeMs, 128 - UniqueViewers: pbResp.UniqueViewers, 129 - DailyStats: dailyStats, 130 - } 131 - } 132 - 133 - func convertViewerHistoryResponse(pbResp *pb.ViewerHistoryResponse) *ViewerHistoryResponse { 134 - if pbResp == nil { 135 - return &ViewerHistoryResponse{} 136 - } 137 - 138 - sessions := make([]WatchSession, len(pbResp.Sessions)) 139 - for i, s := range pbResp.Sessions { 140 - sessions[i] = WatchSession{ 141 - SessionId: s.SessionId, 142 - StreamerDid: s.StreamerDid, 143 - StreamId: s.StreamId, 144 - StartTimeMs: s.StartTimeMs, 145 - EndTimeMs: s.EndTimeMs, 146 - DurationMs: s.DurationMs, 147 - } 148 - } 149 - 150 - return &ViewerHistoryResponse{ 151 - Sessions: sessions, 152 - } 153 - }
···
+11 -130
pkg/api/api.go
··· 28 29 "github.com/streamplace/oatproxy/pkg/oatproxy" 30 "stream.place/streamplace/js/app" 31 - "stream.place/streamplace/pkg/analytics" 32 "stream.place/streamplace/pkg/atproto" 33 "stream.place/streamplace/pkg/bus" 34 "stream.place/streamplace/pkg/config" ··· 36 "stream.place/streamplace/pkg/director" 37 apierrors "stream.place/streamplace/pkg/errors" 38 "stream.place/streamplace/pkg/linking" 39 "stream.place/streamplace/pkg/log" 40 "stream.place/streamplace/pkg/media" 41 "stream.place/streamplace/pkg/mist/mistconfig" ··· 57 CLI *config.CLI 58 Model model.Model 59 StatefulDB *statedb.StatefulDB 60 Updater *Updater 61 Signer *eip712.EIP712Signer 62 Mimes map[string]string 63 FirebaseNotifier notifications.FirebaseNotifier 64 - AnalyticsClient analytics.Client 65 MediaManager *media.MediaManager 66 MediaSigner media.MediaSigner 67 XRPCServer *spxrpc.Server ··· 95 mu sync.RWMutex 96 } 97 98 - func MakeStreamplaceAPI(cli *config.CLI, mod model.Model, statefulDB *statedb.StatefulDB, noter notifications.FirebaseNotifier, analyticsClient analytics.Client, mm *media.MediaManager, ms media.MediaSigner, bus *bus.Bus, atsync *atproto.ATProtoSynchronizer, d *director.Director, op *oatproxy.OATProxy) (*StreamplaceAPI, error) { 99 updater, err := PrepareUpdater(cli) 100 if err != nil { 101 return nil, err ··· 105 StatefulDB: statefulDB, 106 Updater: updater, 107 FirebaseNotifier: noter, 108 - AnalyticsClient: analyticsClient, 109 MediaManager: mm, 110 MediaSigner: ms, 111 Aliases: map[string]string{}, ··· 120 sessionsLock: sync.RWMutex{}, 121 rtmpSessions: make(map[string]*media.RTMPSession), 122 rtmpSessionsLock: sync.Mutex{}, 123 } 124 a.Mimes, err = updater.GetMimes() 125 if err != nil { ··· 155 Recorder: metrics.NewRecorder(metrics.Config{}), 156 }) 157 var xrpc http.Handler 158 - xrpc, err := spxrpc.NewServer(ctx, a.CLI, a.Model, a.StatefulDB, a.op, mdlw, a.ATSync, a.Bus) 159 if err != nil { 160 return nil, err 161 } ··· 206 addHandle(apiRouter, "GET", "/api/chat/:repoDID", a.HandleChat(ctx)) 207 addHandle(apiRouter, "GET", "/api/websocket/:repoDID", a.HandleWebsocket(ctx)) 208 addHandle(apiRouter, "GET", "/api/livestream/:repoDID", a.HandleLivestream(ctx)) 209 - addHandle(apiRouter, "GET", "/api/segment/recent", a.HandleRecentSegments(ctx)) 210 - addHandle(apiRouter, "GET", "/api/segment/recent/:repoDID", a.HandleUserRecentSegments(ctx)) 211 addHandle(apiRouter, "GET", "/api/bluesky/resolve/:handle", a.HandleBlueskyResolve(ctx)) 212 addHandle(apiRouter, "GET", "/api/view-count/:user", a.HandleViewCount(ctx)) 213 addHandle(apiRouter, "GET", "/api/clip/:user/:file", a.HandleClip(ctx)) 214 - 215 - // Analytics routes (optional, only if analytics is configured) 216 - if a.AnalyticsClient != nil { 217 - addFunc(apiRouter, "GET", "/api/analytics/realtime", analytics.HandleRealtimeStats(a.AnalyticsClient)) 218 - addHandle(apiRouter, "GET", "/api/analytics/streamer/:did", analytics.HandleStreamerStats(a.AnalyticsClient)) 219 - addHandle(apiRouter, "GET", "/api/analytics/viewer/:did", analytics.HandleViewerHistory(a.AnalyticsClient)) 220 - log.Log(ctx, "registered analytics HTTP endpoints") 221 - } else { 222 - log.Debug(ctx, "analytics not configured, skipping analytics endpoints") 223 - } 224 - 225 apiRouter.NotFound = a.HandleAPI404(ctx) 226 apiRouterHandler := a.RateLimitMiddleware(ctx)(apiRouter) 227 xrpcHandler := a.RateLimitMiddleware(ctx)(xrpc) ··· 285 if err != nil { 286 return nil, err 287 } 288 - linker, err := linking.NewLinker(ctx, bs) 289 if err != nil { 290 return nil, err 291 } ··· 557 558 func (a *StreamplaceAPI) HandlePlayerEvent(ctx context.Context) httprouter.Handle { 559 return func(w http.ResponseWriter, req *http.Request, p httprouter.Params) { 560 var event model.PlayerEventAPI 561 if err := json.NewDecoder(req.Body).Decode(&event); err != nil { 562 apierrors.WriteHTTPBadRequest(w, "could not decode JSON body", err) 563 return 564 } 565 - 566 - // Generate server-side ID 567 - uu, err := uuid.NewV7() 568 - if err != nil { 569 - apierrors.WriteHTTPInternalServerError(w, "could not generate event ID", err) 570 - return 571 - } 572 - event.ID = uu.String() 573 - 574 - err = a.Model.CreatePlayerEvent(event) 575 if err != nil { 576 apierrors.WriteHTTPBadRequest(w, "could not create player event", err) 577 return 578 } 579 - 580 - // Forward relevant events to analytics service if configured 581 - if a.AnalyticsClient != nil { 582 - go a.forwardPlayerEventToAnalytics(req.Context(), event) 583 - } else { 584 - log.Log(req.Context(), "no analytics client configured, skipping forwarding player event") 585 - } 586 - 587 w.WriteHeader(201) 588 - } 589 - } 590 - 591 - func (a *StreamplaceAPI) forwardPlayerEventToAnalytics(ctx context.Context, event model.PlayerEventAPI) { 592 - // Only forward watch/playback events 593 - if event.EventType != "aq-played" && event.EventType != "watch" { 594 - return 595 - } 596 - 597 - // Parse metadata into typed struct 598 - var meta model.PlayerEventMeta 599 - metaBytes, _ := json.Marshal(event.Meta) 600 - if err := json.Unmarshal(metaBytes, &meta); err != nil { 601 - log.Log(ctx, "failed to parse event metadata", "error", err) 602 - return 603 - } 604 - 605 - // Validate required fields 606 - if err := meta.Validate(); err != nil { 607 - log.Log(ctx, "invalid event metadata", "error", err) 608 - return 609 - } 610 - 611 - analyticsEvent := &analytics.Event{ 612 - EventID: event.ID, 613 - EventType: event.EventType, 614 - DeviceID: meta.DeviceID, 615 - DID: meta.DID, 616 - SessionID: meta.SessionID, 617 - TimestampMs: event.Time.UnixMilli(), 618 - StreamerDID: meta.StreamerDID, 619 - StreamID: meta.StreamID, 620 - PropertiesJSON: string(metaBytes), 621 - SchemaVersion: 1, 622 - ClientVersion: meta.ClientVersion, 623 - Platform: meta.Platform, 624 - } 625 - 626 - if err := a.AnalyticsClient.IngestEvents(ctx, []*analytics.Event{analyticsEvent}); err != nil { 627 - log.Log(ctx, "failed to ingest analytics event", "error", err) 628 - } 629 - } 630 - 631 - func (a *StreamplaceAPI) HandleRecentSegments(ctx context.Context) httprouter.Handle { 632 - return func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { 633 - segs, err := a.Model.MostRecentSegments() 634 - if err != nil { 635 - apierrors.WriteHTTPInternalServerError(w, "could not get segments", err) 636 - return 637 - } 638 - bs, err := json.Marshal(segs) 639 - if err != nil { 640 - apierrors.WriteHTTPInternalServerError(w, "could not marshal segments", err) 641 - return 642 - } 643 - w.Header().Add("Content-Type", "application/json") 644 - if _, err := w.Write(bs); err != nil { 645 - log.Error(ctx, "error writing response", "error", err) 646 - } 647 - } 648 - } 649 - 650 - func (a *StreamplaceAPI) HandleUserRecentSegments(ctx context.Context) httprouter.Handle { 651 - return func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { 652 - user := params.ByName("repoDID") 653 - if user == "" { 654 - apierrors.WriteHTTPBadRequest(w, "user required", nil) 655 - return 656 - } 657 - user, err := a.NormalizeUser(ctx, user) 658 - if err != nil { 659 - apierrors.WriteHTTPNotFound(w, "user not found", err) 660 - return 661 - } 662 - seg, err := a.Model.LatestSegmentForUser(user) 663 - if err != nil { 664 - apierrors.WriteHTTPInternalServerError(w, "could not get segments", err) 665 - return 666 - } 667 - streamplaceSeg, err := seg.ToStreamplaceSegment() 668 - if err != nil { 669 - apierrors.WriteHTTPInternalServerError(w, "could not convert segment to streamplace segment", err) 670 - return 671 - } 672 - bs, err := json.Marshal(streamplaceSeg) 673 - if err != nil { 674 - apierrors.WriteHTTPInternalServerError(w, "could not marshal segments", err) 675 - return 676 - } 677 - w.Header().Add("Content-Type", "application/json") 678 - if _, err := w.Write(bs); err != nil { 679 - log.Error(ctx, "error writing response", "error", err) 680 - } 681 } 682 } 683
··· 28 29 "github.com/streamplace/oatproxy/pkg/oatproxy" 30 "stream.place/streamplace/js/app" 31 "stream.place/streamplace/pkg/atproto" 32 "stream.place/streamplace/pkg/bus" 33 "stream.place/streamplace/pkg/config" ··· 35 "stream.place/streamplace/pkg/director" 36 apierrors "stream.place/streamplace/pkg/errors" 37 "stream.place/streamplace/pkg/linking" 38 + "stream.place/streamplace/pkg/localdb" 39 "stream.place/streamplace/pkg/log" 40 "stream.place/streamplace/pkg/media" 41 "stream.place/streamplace/pkg/mist/mistconfig" ··· 57 CLI *config.CLI 58 Model model.Model 59 StatefulDB *statedb.StatefulDB 60 + LocalDB localdb.LocalDB 61 Updater *Updater 62 Signer *eip712.EIP712Signer 63 Mimes map[string]string 64 FirebaseNotifier notifications.FirebaseNotifier 65 MediaManager *media.MediaManager 66 MediaSigner media.MediaSigner 67 XRPCServer *spxrpc.Server ··· 95 mu sync.RWMutex 96 } 97 98 + func MakeStreamplaceAPI(cli *config.CLI, mod model.Model, statefulDB *statedb.StatefulDB, noter notifications.FirebaseNotifier, mm *media.MediaManager, ms media.MediaSigner, bus *bus.Bus, atsync *atproto.ATProtoSynchronizer, d *director.Director, op *oatproxy.OATProxy, ldb localdb.LocalDB) (*StreamplaceAPI, error) { 99 updater, err := PrepareUpdater(cli) 100 if err != nil { 101 return nil, err ··· 105 StatefulDB: statefulDB, 106 Updater: updater, 107 FirebaseNotifier: noter, 108 MediaManager: mm, 109 MediaSigner: ms, 110 Aliases: map[string]string{}, ··· 119 sessionsLock: sync.RWMutex{}, 120 rtmpSessions: make(map[string]*media.RTMPSession), 121 rtmpSessionsLock: sync.Mutex{}, 122 + LocalDB: ldb, 123 } 124 a.Mimes, err = updater.GetMimes() 125 if err != nil { ··· 155 Recorder: metrics.NewRecorder(metrics.Config{}), 156 }) 157 var xrpc http.Handler 158 + xrpc, err := spxrpc.NewServer(ctx, a.CLI, a.Model, a.StatefulDB, a.op, mdlw, a.ATSync, a.Bus, a.LocalDB) 159 if err != nil { 160 return nil, err 161 } ··· 206 addHandle(apiRouter, "GET", "/api/chat/:repoDID", a.HandleChat(ctx)) 207 addHandle(apiRouter, "GET", "/api/websocket/:repoDID", a.HandleWebsocket(ctx)) 208 addHandle(apiRouter, "GET", "/api/livestream/:repoDID", a.HandleLivestream(ctx)) 209 addHandle(apiRouter, "GET", "/api/bluesky/resolve/:handle", a.HandleBlueskyResolve(ctx)) 210 addHandle(apiRouter, "GET", "/api/view-count/:user", a.HandleViewCount(ctx)) 211 addHandle(apiRouter, "GET", "/api/clip/:user/:file", a.HandleClip(ctx)) 212 apiRouter.NotFound = a.HandleAPI404(ctx) 213 apiRouterHandler := a.RateLimitMiddleware(ctx)(apiRouter) 214 xrpcHandler := a.RateLimitMiddleware(ctx)(xrpc) ··· 272 if err != nil { 273 return nil, err 274 } 275 + linker, err := linking.NewLinker(ctx, bs, a.StatefulDB, a.CLI) 276 if err != nil { 277 return nil, err 278 } ··· 544 545 func (a *StreamplaceAPI) HandlePlayerEvent(ctx context.Context) httprouter.Handle { 546 return func(w http.ResponseWriter, req *http.Request, p httprouter.Params) { 547 + if !a.CLI.PlayerTelemetry { 548 + w.WriteHeader(200) 549 + return 550 + } 551 var event model.PlayerEventAPI 552 if err := json.NewDecoder(req.Body).Decode(&event); err != nil { 553 apierrors.WriteHTTPBadRequest(w, "could not decode JSON body", err) 554 return 555 } 556 + err := a.Model.CreatePlayerEvent(event) 557 if err != nil { 558 apierrors.WriteHTTPBadRequest(w, "could not create player event", err) 559 return 560 } 561 w.WriteHeader(201) 562 } 563 } 564
+2 -2
pkg/api/api_internal.go
··· 298 errors.WriteHTTPBadRequest(w, "id required", nil) 299 return 300 } 301 - segment, err := a.Model.GetSegment(id) 302 if err != nil { 303 errors.WriteHTTPBadRequest(w, err.Error(), err) 304 return ··· 553 } 554 after := time.Now().Add(-time.Duration(secs) * time.Second) 555 w.Header().Set("Content-Type", "video/mp4") 556 - err = media.ClipUser(ctx, a.Model, a.CLI, user, w, nil, &after) 557 if err != nil { 558 errors.WriteHTTPInternalServerError(w, "unable to clip user", err) 559 return
··· 298 errors.WriteHTTPBadRequest(w, "id required", nil) 299 return 300 } 301 + segment, err := a.LocalDB.GetSegment(id) 302 if err != nil { 303 errors.WriteHTTPBadRequest(w, err.Error(), err) 304 return ··· 553 } 554 after := time.Now().Add(-time.Duration(secs) * time.Second) 555 w.Header().Set("Content-Type", "video/mp4") 556 + err = media.ClipUser(ctx, a.LocalDB, a.CLI, user, w, nil, &after) 557 if err != nil { 558 errors.WriteHTTPInternalServerError(w, "unable to clip user", err) 559 return
+1 -1
pkg/api/playback.go
··· 272 errors.WriteHTTPNotFound(w, "user not found", err) 273 return 274 } 275 - thumb, err := a.Model.LatestThumbnailForUser(user) 276 if err != nil { 277 errors.WriteHTTPInternalServerError(w, "could not query thumbnail", err) 278 return
··· 272 errors.WriteHTTPNotFound(w, "user not found", err) 273 return 274 } 275 + thumb, err := a.LocalDB.LatestThumbnailForUser(user) 276 if err != nil { 277 errors.WriteHTTPInternalServerError(w, "could not query thumbnail", err) 278 return
+48 -1
pkg/api/websocket.go
··· 3 import ( 4 "context" 5 "encoding/json" 6 "net" 7 "net/http" 8 "time" 9 10 "github.com/google/uuid" 11 "github.com/gorilla/websocket" 12 "github.com/julienschmidt/httprouter" 13 14 apierrors "stream.place/streamplace/pkg/errors" 15 "stream.place/streamplace/pkg/log" 16 "stream.place/streamplace/pkg/renditions" ··· 180 }() 181 182 go func() { 183 - seg, err := a.Model.LatestSegmentForUser(repoDID) 184 if err != nil { 185 log.Error(ctx, "could not get replies", "error", err) 186 return ··· 236 log.Error(ctx, "could not get chat messages", "error", err) 237 return 238 } 239 for _, message := range messages { 240 initialBurst <- message 241 } 242 }() 243
··· 3 import ( 4 "context" 5 "encoding/json" 6 + "fmt" 7 "net" 8 "net/http" 9 "time" 10 11 + bsky "github.com/bluesky-social/indigo/api/bsky" 12 "github.com/google/uuid" 13 "github.com/gorilla/websocket" 14 "github.com/julienschmidt/httprouter" 15 16 + "stream.place/streamplace/pkg/atproto" 17 apierrors "stream.place/streamplace/pkg/errors" 18 "stream.place/streamplace/pkg/log" 19 "stream.place/streamplace/pkg/renditions" ··· 183 }() 184 185 go func() { 186 + seg, err := a.LocalDB.LatestSegmentForUser(repoDID) 187 if err != nil { 188 log.Error(ctx, "could not get replies", "error", err) 189 return ··· 239 log.Error(ctx, "could not get chat messages", "error", err) 240 return 241 } 242 + 243 + // Add mod badges to messages 244 + issuerDID := fmt.Sprintf("did:web:%s", a.CLI.BroadcasterHost) 245 for _, message := range messages { 246 + err := atproto.AddModBadgeIfApplicable(ctx, message, repoDID, issuerDID, a.Model) 247 + if err != nil { 248 + log.Error(ctx, "failed to add mod badge to message", "error", err) 249 + } 250 initialBurst <- message 251 + } 252 + }() 253 + 254 + go func() { 255 + teleports, err := a.Model.GetActiveTeleportsToRepo(repoDID) 256 + if err != nil { 257 + log.Error(ctx, "could not get active teleports", "error", err) 258 + return 259 + } 260 + // just send the latest one if it started <3m ago 261 + if len(teleports) > 0 && teleports[0].StartsAt.After(time.Now().Add(-3*time.Minute)) { 262 + tp := teleports[0] 263 + if tp.Repo == nil { 264 + log.Error(ctx, "teleportee repo is nil", "uri", tp.URI) 265 + } 266 + viewerCount := a.Bus.GetViewerCount(tp.RepoDID) 267 + arrivalMsg := streamplace.Livestream_TeleportArrival{ 268 + LexiconTypeID: "place.stream.livestream#teleportArrival", 269 + TeleportUri: tp.URI, 270 + Source: &bsky.ActorDefs_ProfileViewBasic{ 271 + Did: tp.RepoDID, 272 + Handle: tp.Repo.Handle, 273 + }, 274 + ViewerCount: int64(viewerCount), 275 + StartsAt: tp.StartsAt.Format(time.RFC3339), 276 + } 277 + 278 + // get the source chat profile 279 + chatProfile, err := a.Model.GetChatProfile(ctx, tp.RepoDID) 280 + if err == nil && chatProfile != nil { 281 + spcp, err := chatProfile.ToStreamplaceChatProfile() 282 + if err == nil { 283 + arrivalMsg.ChatProfile = spcp 284 + } 285 + } 286 + 287 + initialBurst <- arrivalMsg 288 } 289 }() 290
+30 -7
pkg/aqtime/aqtime.go
··· 7 "time" 8 ) 9 10 var RE *regexp.Regexp 11 - var Pattern string = `^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d)(?:[:-])(\d\d)(?:[:-])(\d\d)(?:[.-])(\d\d\d)Z$` 12 - 13 - type AQTime string 14 15 func init() { 16 RE = regexp.MustCompile(fmt.Sprintf(`^%s$`, Pattern)) 17 } 18 19 var fstr = "2006-01-02T15:04:05.000Z" 20 21 // return a consistently formatted timestamp 22 func FromMillis(ms int64) AQTime { ··· 29 } 30 31 func FromString(str string) (AQTime, error) { 32 - bits := RE.FindStringSubmatch(str) 33 - if bits == nil { 34 - return "", fmt.Errorf("bad time format, expected=%s got=%s", fstr, str) 35 } 36 - return AQTime(str), nil 37 } 38 39 func FromTime(t time.Time) AQTime {
··· 7 "time" 8 ) 9 10 + // RE matches the canonical internal format: 2006-01-02T15:04:05.000Z 11 + // It also accepts the file-safe variant with dashes/dots swapped, for backward compat. 12 var RE *regexp.Regexp 13 + var Pattern string = `(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d)(?:[:-])(\d\d)(?:[:-])(\d\d)(?:[.-])(\d\d\d)Z` 14 15 func init() { 16 RE = regexp.MustCompile(fmt.Sprintf(`^%s$`, Pattern)) 17 } 18 19 var fstr = "2006-01-02T15:04:05.000Z" 20 + 21 + type AQTime string 22 23 // return a consistently formatted timestamp 24 func FromMillis(ms int64) AQTime { ··· 31 } 32 33 func FromString(str string) (AQTime, error) { 34 + // Reject -00:00 (valid RFC 3339 but disallowed by ATProto) 35 + if strings.HasSuffix(str, "-00:00") { 36 + return "", fmt.Errorf("bad time format, -00:00 timezone offset is not allowed, got=%s", str) 37 + } 38 + 39 + t, err := time.Parse(time.RFC3339Nano, str) 40 + if err != nil { 41 + // Fall back to file-safe variant (e.g. 2024-09-13T18-10-17-090Z) 42 + if bits := RE.FindStringSubmatch(str); bits != nil { 43 + if bits[2] < "01" || bits[2] > "12" || bits[3] < "01" || bits[3] > "31" || 44 + bits[4] > "23" || bits[5] > "59" || bits[6] > "60" { 45 + return "", fmt.Errorf("bad time format, invalid date/time values in %s", str) 46 + } 47 + return AQTime(str), nil 48 + } 49 + return "", fmt.Errorf("bad time format: %w", err) 50 } 51 + 52 + // Reject if UTC normalization results in a negative year 53 + utc := t.UTC() 54 + if utc.Year() < 0 { 55 + return "", fmt.Errorf("bad time format, datetime normalizes to negative year: %s", str) 56 + } 57 + 58 + // Normalize to canonical UTC millisecond format 59 + return AQTime(utc.Format(fstr)), nil 60 } 61 62 func FromTime(t time.Time) AQTime {
+63 -2
pkg/aqtime/aqtime_test.go
··· 35 } 36 } 37 38 func TestBadCases(t *testing.T) { 39 for _, str := range []string{ 40 "prefix2024-09-13T18:10:17.090Z", 41 "2024-09-13T18-10-17-090Zsuffix", 42 "2024-09-13T18-10-17-090ZZZZ", 43 "2024-09-13T18-10-17*090ZZZZ", 44 } { 45 - _, err := FromString(str) 46 - require.Error(t, err) 47 } 48 }
··· 35 } 36 } 37 38 + // Valid ATProto datetime examples from the spec 39 + // https://atproto.com/specs/lexicon#datetime 40 + func TestATProtoValidCases(t *testing.T) { 41 + tests := []struct { 42 + input string 43 + wantMs string // expected millisecond portion after normalization 44 + wantHr string // expected hour after UTC normalization 45 + wantMin string 46 + }{ 47 + {"1985-04-12T23:20:50.123Z", "123", "23", "20"}, 48 + {"1985-04-12T23:20:50.123456Z", "123", "23", "20"}, 49 + {"1985-04-12T23:20:50.120Z", "120", "23", "20"}, 50 + {"1985-04-12T23:20:50.120000Z", "120", "23", "20"}, 51 + {"0001-01-01T00:00:00.000Z", "000", "00", "00"}, 52 + {"0000-01-01T00:00:00.000Z", "000", "00", "00"}, 53 + {"1985-04-12T23:20:50.12345678912345Z", "123", "23", "20"}, 54 + {"1985-04-12T23:20:50Z", "000", "23", "20"}, 55 + {"1985-04-12T23:20:50.0Z", "000", "23", "20"}, 56 + {"1985-04-12T23:20:50.123+00:00", "123", "23", "20"}, 57 + {"1985-04-12T23:20:50.123-07:00", "123", "06", "20"}, // 23+7=30 -> next day 06:20 58 + } 59 + for _, tt := range tests { 60 + t.Run(tt.input, func(t *testing.T) { 61 + aqt, err := FromString(tt.input) 62 + require.NoError(t, err, "input: %s", tt.input) 63 + _, _, _, hr, min, _, ms := aqt.Parts() 64 + require.Equal(t, tt.wantMs, ms, "millis mismatch for %s", tt.input) 65 + require.Equal(t, tt.wantHr, hr, "hour mismatch for %s", tt.input) 66 + require.Equal(t, tt.wantMin, min, "minute mismatch for %s", tt.input) 67 + }) 68 + } 69 + } 70 + 71 func TestBadCases(t *testing.T) { 72 for _, str := range []string{ 73 + // existing cases 74 "prefix2024-09-13T18:10:17.090Z", 75 "2024-09-13T18-10-17-090Zsuffix", 76 "2024-09-13T18-10-17-090ZZZZ", 77 "2024-09-13T18-10-17*090ZZZZ", 78 + // ATProto spec invalid examples 79 + "1985-04-12", 80 + "1985-04-12T23:20Z", 81 + "1985-04-12T23:20:5Z", 82 + "1985-04-12T23:20:50.123", 83 + "+001985-04-12T23:20:50.123Z", 84 + "23:20:50.123Z", 85 + "-1985-04-12T23:20:50.123Z", 86 + "1985-4-12T23:20:50.123Z", 87 + "01985-04-12T23:20:50.123Z", 88 + "1985-04-12T23:20:50.123+00", 89 + "1985-04-12T23:20:50.123+0000", 90 + // ISO-8601 strict capitalization 91 + "1985-04-12t23:20:50.123Z", 92 + "1985-04-12T23:20:50.123z", 93 + // RFC-3339, but not ISO-8601 94 + "1985-04-12T23:20:50.123-00:00", 95 + "1985-04-12 23:20:50.123Z", 96 + // timezone is required 97 + "1985-04-12T23:20:50.123", 98 + // syntax looks ok, but datetime is not valid 99 + "1985-04-12T23:99:50.123Z", 100 + "1985-00-12T23:20:50.123Z", 101 + // ISO-8601, but normalizes to a negative time 102 + "0000-01-01T00:00:00+01:00", 103 } { 104 + t.Run(str, func(t *testing.T) { 105 + _, err := FromString(str) 106 + require.Error(t, err, "expected error for: %s", str) 107 + }) 108 } 109 }
+2 -4
pkg/atproto/atproto.go
··· 231 "https://w3id.org/security/multikey/v1", 232 "https://w3id.org/security/suites/secp256k1-2019/v1", 233 }, 234 - "id": fmt.Sprintf("did:web:%s", host), 235 - "alsoKnownAs": []string{ 236 - fmt.Sprintf("at://%s", host), 237 - }, 238 "service": []map[string]any{ 239 { 240 "id": "#bsky_fg",
··· 231 "https://w3id.org/security/multikey/v1", 232 "https://w3id.org/security/suites/secp256k1-2019/v1", 233 }, 234 + "id": fmt.Sprintf("did:web:%s", host), 235 + "alsoKnownAs": []string{}, 236 "service": []map[string]any{ 237 { 238 "id": "#bsky_fg",
+61
pkg/atproto/badges.go
···
··· 1 + package atproto 2 + 3 + import ( 4 + "context" 5 + "fmt" 6 + 7 + "stream.place/streamplace/pkg/constants" 8 + "stream.place/streamplace/pkg/log" 9 + "stream.place/streamplace/pkg/model" 10 + "stream.place/streamplace/pkg/streamplace" 11 + ) 12 + 13 + // AddModBadgeIfApplicable checks if a message author has mod permissions for the streamer 14 + // and adds a mod or streamer badge as the first badge (server-controlled). 15 + // - If the author is the streamer, adds a "streamer" badge 16 + // - If the author has moderation permissions, adds a "mod" badge 17 + func AddModBadgeIfApplicable(ctx context.Context, message *streamplace.ChatDefs_MessageView, streamerDID string, issuerDID string, m model.Model) error { 18 + if message == nil { 19 + return fmt.Errorf("message is nil") 20 + } 21 + 22 + authorDID := message.Author.Did 23 + 24 + var badge *streamplace.BadgeDefs_BadgeView 25 + 26 + // Check if author is the streamer 27 + if authorDID == streamerDID { 28 + badge = &streamplace.BadgeDefs_BadgeView{ 29 + BadgeType: constants.BadgeTypeStreamer, 30 + Issuer: issuerDID, 31 + Recipient: authorDID, 32 + } 33 + } else { 34 + // Check if author has any moderation permissions for the streamer 35 + delegations, err := m.GetModerationDelegations(ctx, streamerDID, authorDID) 36 + if err != nil { 37 + log.Error(ctx, "failed to get moderation delegations", "err", err, "authorDID", authorDID, "streamerDID", streamerDID) 38 + return err 39 + } 40 + 41 + // If the author has any delegations (meaning they're a moderator), add a mod badge 42 + if len(delegations) > 0 { 43 + badge = &streamplace.BadgeDefs_BadgeView{ 44 + BadgeType: constants.BadgeTypeMod, 45 + Issuer: issuerDID, 46 + Recipient: authorDID, 47 + } 48 + } 49 + } 50 + 51 + // Prepend the badge if one was created (server-controlled badge is first) 52 + if badge != nil { 53 + if message.Badges == nil { 54 + message.Badges = []*streamplace.BadgeDefs_BadgeView{badge} 55 + } else { 56 + message.Badges = append([]*streamplace.BadgeDefs_BadgeView{badge}, message.Badges...) 57 + } 58 + } 59 + 60 + return nil 61 + }
+100
pkg/atproto/badges_test.go
···
··· 1 + package atproto 2 + 3 + import ( 4 + "context" 5 + "testing" 6 + "time" 7 + 8 + bsky "github.com/bluesky-social/indigo/api/bsky" 9 + "github.com/bluesky-social/indigo/atproto/syntax" 10 + "github.com/bluesky-social/indigo/util" 11 + "github.com/stretchr/testify/require" 12 + "stream.place/streamplace/pkg/model" 13 + "stream.place/streamplace/pkg/streamplace" 14 + ) 15 + 16 + func TestAddModBadge(t *testing.T) { 17 + ctx := context.Background() 18 + 19 + mod, err := model.MakeDB(":memory:") 20 + require.NoError(t, err) 21 + 22 + streamerDID := "did:plc:streamer" 23 + moderatorDID := "did:plc:moderator" 24 + issuerDID := "did:web:example.com" 25 + 26 + // Create a chat message 27 + message := &streamplace.ChatDefs_MessageView{ 28 + LexiconTypeID: "place.stream.chat.defs#messageView", 29 + Uri: "at://test/place.stream.chat.message/123", 30 + Cid: "test-cid", 31 + Author: &bsky.ActorDefs_ProfileViewBasic{ 32 + Did: moderatorDID, 33 + Handle: "moderator.test", 34 + }, 35 + IndexedAt: "2024-01-01T00:00:00Z", 36 + } 37 + 38 + t.Run("no badge when user is not a moderator", func(t *testing.T) { 39 + msg := *message // copy 40 + err := AddModBadgeIfApplicable(ctx, &msg, streamerDID, issuerDID, mod) 41 + require.NoError(t, err) 42 + require.Nil(t, msg.Badges, "should not have badges when user is not a moderator") 43 + }) 44 + 45 + t.Run("adds streamer badge when user is the streamer", func(t *testing.T) { 46 + msg := *message // copy 47 + msg.Author = &bsky.ActorDefs_ProfileViewBasic{ 48 + Did: streamerDID, 49 + Handle: "streamer.test", 50 + } 51 + err := AddModBadgeIfApplicable(ctx, &msg, streamerDID, issuerDID, mod) 52 + require.NoError(t, err) 53 + require.Len(t, msg.Badges, 1, "should have 1 badge when user is the streamer") 54 + require.Equal(t, "place.stream.badge.defs#streamer", msg.Badges[0].BadgeType) 55 + require.Equal(t, issuerDID, msg.Badges[0].Issuer) 56 + require.Equal(t, streamerDID, msg.Badges[0].Recipient) 57 + }) 58 + 59 + t.Run("adds mod badge when user has moderation permissions", func(t *testing.T) { 60 + // Grant moderation permissions to the moderator 61 + perm := &streamplace.ModerationPermission{ 62 + LexiconTypeID: "place.stream.moderation.permission", 63 + Moderator: moderatorDID, 64 + Permissions: []string{"ban", "hide"}, 65 + CreatedAt: time.Now().Format(util.ISO8601), 66 + } 67 + aturi, err := syntax.ParseATURI("at://" + streamerDID + "/place.stream.moderation.permission/test123") 68 + require.NoError(t, err) 69 + 70 + // Sync the permission to the model 71 + err = mod.CreateModerationDelegation(ctx, perm, aturi) 72 + require.NoError(t, err) 73 + 74 + msg := *message // copy 75 + err = AddModBadgeIfApplicable(ctx, &msg, streamerDID, issuerDID, mod) 76 + require.NoError(t, err) 77 + require.Len(t, msg.Badges, 1, "should have 1 badge when user is a moderator") 78 + require.Equal(t, "place.stream.badges.badge#mod", msg.Badges[0].BadgeType) 79 + require.Equal(t, issuerDID, msg.Badges[0].Issuer) 80 + require.Equal(t, moderatorDID, msg.Badges[0].Recipient) 81 + }) 82 + 83 + t.Run("prepends mod badge to existing badges", func(t *testing.T) { 84 + // Create message with existing user-settable badge 85 + msg := *message // copy 86 + msg.Badges = []*streamplace.BadgeDefs_BadgeView{ 87 + { 88 + BadgeType: "place.stream.badges.badge#vip", 89 + Issuer: "did:web:other.com", 90 + Recipient: moderatorDID, 91 + }, 92 + } 93 + 94 + err = AddModBadgeIfApplicable(ctx, &msg, streamerDID, issuerDID, mod) 95 + require.NoError(t, err) 96 + require.Len(t, msg.Badges, 2, "should have 2 badges") 97 + require.Equal(t, "place.stream.badges.badge#mod", msg.Badges[0].BadgeType, "mod badge should be first") 98 + require.Equal(t, "place.stream.badges.badge#vip", msg.Badges[1].BadgeType, "vip badge should be second") 99 + }) 100 + }
+7
pkg/atproto/firehose.go
··· 305 atsync.Bus.Publish(msg.StreamerRepoDID, mv) 306 } 307 308 if collection.String() == constants.PLACE_STREAM_MODERATION_PERMISSION { 309 log.Debug(ctx, "deleting moderation delegation", "userDID", evt.Repo, "rkey", rkey.String()) 310 err := atsync.Model.DeleteModerationDelegation(ctx, rkey.String())
··· 305 atsync.Bus.Publish(msg.StreamerRepoDID, mv) 306 } 307 308 + if collection.String() == constants.PLACE_STREAM_LIVE_TELEPORT { 309 + err := atsync.Model.DeleteTeleport(ctx, uri) 310 + if err != nil { 311 + log.Error(ctx, "failed to delete teleport", "err", err) 312 + } 313 + } 314 + 315 if collection.String() == constants.PLACE_STREAM_MODERATION_PERMISSION { 316 log.Debug(ctx, "deleting moderation delegation", "userDID", evt.Repo, "rkey", rkey.String()) 317 err := atsync.Model.DeleteModerationDelegation(ctx, rkey.String())
+1
pkg/atproto/lexicon_permission_sets.go
··· 34 "rpc:app.bsky.actor.getProfile?aud=did:web:api.bsky.app%23bsky_appview", 35 "rpc:app.bsky.actor.getProfiles?aud=did:web:api.bsky.app%23bsky_appview", 36 "include:place.stream.authFull", 37 } 38 for _, record := range recordLexicons { 39 allRecords = append(allRecords, record.ID)
··· 34 "rpc:app.bsky.actor.getProfile?aud=did:web:api.bsky.app%23bsky_appview", 35 "rpc:app.bsky.actor.getProfiles?aud=did:web:api.bsky.app%23bsky_appview", 36 "include:place.stream.authFull", 37 + "rpc:com.atproto.moderation.createReport?aud=*", 38 } 39 for _, record := range recordLexicons { 40 allRecords = append(allRecords, record.ID)
+12
pkg/atproto/lexicon_repo_queries.go
··· 126 Value: &lexutil.LexiconTypeDecoder{Val: rec}, 127 }, nil 128 }
··· 126 Value: &lexutil.LexiconTypeDecoder{Val: rec}, 127 }, nil 128 } 129 + 130 + func LexiconRepoGetRepo(ctx context.Context, since string) ([]byte, error) { 131 + buf := bytes.Buffer{} 132 + 133 + repoLock.Lock() 134 + defer repoLock.Unlock() 135 + err := CarStore.ReadUserCar(ctx, RepoUser, since, true, &buf) 136 + if err != nil { 137 + return nil, fmt.Errorf("LexiconRepoGetRepo: failed to read user car: %w", err) 138 + } 139 + return buf.Bytes(), nil 140 + }
+86 -1
pkg/atproto/sync.go
··· 74 return fmt.Errorf("failed to create block: %w", err) 75 } 76 block, err = atsync.Model.GetBlock(ctx, rkey.String()) 77 - if err != nil { 78 return fmt.Errorf("failed to get block after we just saved it?!: %w", err) 79 } 80 streamplaceBlock, err := block.ToStreamplaceBlock() ··· 150 log.Error(ctx, "failed to convert chat message to streamplace message view", "err", err) 151 return nil 152 } 153 go atsync.Bus.Publish(rec.Streamer, scm) 154 155 if !isUpdate && !isFirstSync { ··· 379 } 380 task.ChatProfile = spcp 381 } 382 383 case *streamplace.Key: 384 log.Debug(ctx, "creating key", "key", rec)
··· 74 return fmt.Errorf("failed to create block: %w", err) 75 } 76 block, err = atsync.Model.GetBlock(ctx, rkey.String()) 77 + if err != nil || block == nil { 78 return fmt.Errorf("failed to get block after we just saved it?!: %w", err) 79 } 80 streamplaceBlock, err := block.ToStreamplaceBlock() ··· 150 log.Error(ctx, "failed to convert chat message to streamplace message view", "err", err) 151 return nil 152 } 153 + 154 + // Add mod badge if the author is a moderator 155 + issuerDID := fmt.Sprintf("did:web:%s", atsync.CLI.BroadcasterHost) 156 + err = AddModBadgeIfApplicable(ctx, scm, rec.Streamer, issuerDID, atsync.Model) 157 + if err != nil { 158 + log.Error(ctx, "failed to add mod badge", "err", err) 159 + } 160 + 161 go atsync.Bus.Publish(rec.Streamer, scm) 162 163 if !isUpdate && !isFirstSync { ··· 387 } 388 task.ChatProfile = spcp 389 } 390 + 391 + case *streamplace.LiveTeleport: 392 + if r == nil { 393 + return nil 394 + } 395 + startsAt, err := time.Parse(time.RFC3339, rec.StartsAt) 396 + if err != nil { 397 + log.Error(ctx, "failed to parse startsAt", "err", err) 398 + return nil 399 + } 400 + viewerCount := atsync.Bus.GetViewerCount(userDID) 401 + tp := &model.Teleport{ 402 + CID: cid, 403 + URI: aturi.String(), 404 + StartsAt: startsAt, 405 + DurationSeconds: rec.DurationSeconds, 406 + ViewerCount: int64(viewerCount), 407 + Teleport: recCBOR, 408 + RepoDID: userDID, 409 + TargetDID: rec.Streamer, 410 + } 411 + err = atsync.Model.CreateTeleport(ctx, tp) 412 + if err != nil { 413 + return fmt.Errorf("failed to create teleport: %w", err) 414 + } 415 + go atsync.Bus.Publish(userDID, rec) 416 + 417 + // schedule arrival notification 10 seconds after startsAt 418 + arrivalTime := startsAt.Add(10 * time.Second) 419 + waitDuration := time.Until(arrivalTime) 420 + if waitDuration < 0 { 421 + waitDuration = 0 422 + } 423 + 424 + time.AfterFunc(waitDuration, func() { 425 + // verify teleport still exists 426 + existingTp, err := atsync.Model.GetTeleportByURI(aturi.String()) 427 + if err != nil { 428 + log.Error(ctx, "failed to get teleport by uri", "err", err) 429 + return 430 + } 431 + if existingTp == nil || existingTp.Denied { 432 + log.Debug(ctx, "teleport no longer active, skipping arrival notification", "uri", aturi.String()) 433 + return 434 + } 435 + 436 + // get the source profile 437 + sourceRepo, err := atsync.Model.GetRepo(userDID) 438 + if err != nil { 439 + log.Error(ctx, "failed to get source repo", "err", err) 440 + return 441 + } 442 + 443 + viewerCount := existingTp.ViewerCount 444 + 445 + arrivalMsg := &streamplace.Livestream_TeleportArrival{ 446 + LexiconTypeID: "place.stream.livestream#teleportArrival", 447 + TeleportUri: aturi.String(), 448 + Source: &bsky.ActorDefs_ProfileViewBasic{ 449 + Did: userDID, 450 + Handle: sourceRepo.Handle, 451 + }, 452 + ViewerCount: int64(viewerCount), 453 + StartsAt: rec.StartsAt, 454 + } 455 + 456 + // get the source chat profile 457 + chatProfile, err := atsync.Model.GetChatProfile(ctx, userDID) 458 + if err == nil && chatProfile != nil { 459 + spcp, err := chatProfile.ToStreamplaceChatProfile() 460 + if err == nil { 461 + arrivalMsg.ChatProfile = spcp 462 + } 463 + } 464 + 465 + atsync.Bus.Publish(rec.Streamer, arrivalMsg) 466 + }) 467 468 case *streamplace.Key: 469 log.Debug(ctx, "creating key", "key", rec)
+12 -18
pkg/cmd/streamplace.go
··· 23 "github.com/livepeer/go-livepeer/cmd/livepeer/starter" 24 "github.com/peterbourgon/ff/v3" 25 "github.com/streamplace/oatproxy/pkg/oatproxy" 26 - "stream.place/streamplace/pkg/analytics" 27 "stream.place/streamplace/pkg/aqhttp" 28 "stream.place/streamplace/pkg/atproto" 29 "stream.place/streamplace/pkg/bus" 30 "stream.place/streamplace/pkg/director" 31 "stream.place/streamplace/pkg/gstinit" 32 "stream.place/streamplace/pkg/iroh/generated/iroh_streamplace" 33 "stream.place/streamplace/pkg/log" 34 "stream.place/streamplace/pkg/media" 35 "stream.place/streamplace/pkg/notifications" ··· 238 return fmt.Errorf("error creating streamplace dir at %s:%w", cli.DataDir, err) 239 } 240 241 mod, err := model.MakeDB(cli.DataFilePath([]string{"index"})) 242 if err != nil { 243 return err ··· 250 } 251 } 252 253 - var analyticsClient analytics.Client 254 - if cli.AnalyticsEndpoint != "" { 255 - analyticsClient, err = analytics.NewClient(ctx, cli.AnalyticsEndpoint) 256 - if err != nil { 257 - log.Warn(ctx, "failed to connect to analytics service, continuing without analytics", 258 - "endpoint", cli.AnalyticsEndpoint, 259 - "error", err) 260 - } else { 261 - log.Log(ctx, "connected to analytics service", "endpoint", cli.AnalyticsEndpoint) 262 - } 263 - } 264 - 265 group, ctx := TimeoutGroupWithContext(ctx) 266 267 out := carstore.SQLiteStore{} ··· 304 return fmt.Errorf("failed to migrate: %w", err) 305 } 306 307 - mm, err := media.MakeMediaManager(ctx, &cli, signer, mod, b, atsync) 308 if err != nil { 309 return err 310 } ··· 392 DownstreamJWK: cli.AccessJWK, 393 ClientMetadata: clientMetadata, 394 Public: cli.PublicOAuth, 395 }) 396 - d := director.NewDirector(mm, mod, &cli, b, op, state, replicator) 397 - a, err := api.MakeStreamplaceAPI(&cli, mod, state, noter, analyticsClient, mm, ms, b, atsync, d, op) 398 if err != nil { 399 return err 400 } ··· 459 }) 460 461 group.Go(func() error { 462 - return storage.StartSegmentCleaner(ctx, mod, &cli) 463 }) 464 465 group.Go(func() error { 466 - return mod.StartSegmentCleaner(ctx) 467 }) 468 469 group.Go(func() error {
··· 23 "github.com/livepeer/go-livepeer/cmd/livepeer/starter" 24 "github.com/peterbourgon/ff/v3" 25 "github.com/streamplace/oatproxy/pkg/oatproxy" 26 "stream.place/streamplace/pkg/aqhttp" 27 "stream.place/streamplace/pkg/atproto" 28 "stream.place/streamplace/pkg/bus" 29 "stream.place/streamplace/pkg/director" 30 "stream.place/streamplace/pkg/gstinit" 31 "stream.place/streamplace/pkg/iroh/generated/iroh_streamplace" 32 + "stream.place/streamplace/pkg/localdb" 33 "stream.place/streamplace/pkg/log" 34 "stream.place/streamplace/pkg/media" 35 "stream.place/streamplace/pkg/notifications" ··· 238 return fmt.Errorf("error creating streamplace dir at %s:%w", cli.DataDir, err) 239 } 240 241 + ldb, err := localdb.MakeDB(cli.LocalDBURL) 242 + if err != nil { 243 + return err 244 + } 245 + 246 mod, err := model.MakeDB(cli.DataFilePath([]string{"index"})) 247 if err != nil { 248 return err ··· 255 } 256 } 257 258 group, ctx := TimeoutGroupWithContext(ctx) 259 260 out := carstore.SQLiteStore{} ··· 297 return fmt.Errorf("failed to migrate: %w", err) 298 } 299 300 + mm, err := media.MakeMediaManager(ctx, &cli, signer, mod, b, atsync, ldb) 301 if err != nil { 302 return err 303 } ··· 385 DownstreamJWK: cli.AccessJWK, 386 ClientMetadata: clientMetadata, 387 Public: cli.PublicOAuth, 388 + HTTPClient: &aqhttp.Client, 389 }) 390 + d := director.NewDirector(mm, mod, &cli, b, op, state, replicator, ldb) 391 + a, err := api.MakeStreamplaceAPI(&cli, mod, state, noter, mm, ms, b, atsync, d, op, ldb) 392 if err != nil { 393 return err 394 } ··· 453 }) 454 455 group.Go(func() error { 456 + return storage.StartSegmentCleaner(ctx, ldb, &cli) 457 }) 458 459 group.Go(func() error { 460 + return ldb.StartSegmentCleaner(ctx) 461 }) 462 463 group.Go(func() error {
+5 -2
pkg/config/config.go
··· 56 Build *BuildFlags 57 DataDir string 58 DBURL string 59 EthAccountAddr string 60 EthKeystorePath string 61 EthPassword string ··· 140 SegmentDebugDir string 141 AdminDIDs []string 142 Syndicate []string 143 - AnalyticsEndpoint string 144 } 145 146 // ContentFilters represents the content filtering configuration ··· 210 fs.BoolVar(&cli.SmearAudio, "smear-audio", false, "enable audio smearing to create 'perfect' segment timestamps") 211 212 fs.StringVar(&cli.TracingEndpoint, "tracing-endpoint", "", "gRPC endpoint to send traces to") 213 - fs.StringVar(&cli.AnalyticsEndpoint, "analytics-endpoint", "", "gRPC endpoint for analytics service (optional)") 214 fs.IntVar(&cli.RateLimitPerSecond, "rate-limit-per-second", 0, "rate limit for requests per second per ip") 215 fs.IntVar(&cli.RateLimitBurst, "rate-limit-burst", 0, "rate limit burst for requests per ip") 216 fs.IntVar(&cli.RateLimitWebsocket, "rate-limit-websocket", 10, "number of concurrent websocket connections allowed per ip") ··· 242 fs.BoolVar(&cli.BehindHTTPSProxy, "behind-https-proxy", false, "set to true if this node is behind an https proxy and we should report https URLs even though the node isn't serving HTTPS") 243 cli.StringSliceFlag(fs, &cli.AdminDIDs, "admin-dids", []string{}, "comma-separated list of DIDs that are authorized to modify branding and other admin operations") 244 cli.StringSliceFlag(fs, &cli.Syndicate, "syndicate", []string{}, "list of DIDs that we should rebroadcast ('*' for everybody)") 245 246 fs.Bool("external-signing", true, "DEPRECATED, does nothing.") 247 fs.Bool("insecure", false, "DEPRECATED, does nothing.")
··· 56 Build *BuildFlags 57 DataDir string 58 DBURL string 59 + LocalDBURL string 60 EthAccountAddr string 61 EthKeystorePath string 62 EthPassword string ··· 141 SegmentDebugDir string 142 AdminDIDs []string 143 Syndicate []string 144 + PlayerTelemetry bool 145 } 146 147 // ContentFilters represents the content filtering configuration ··· 211 fs.BoolVar(&cli.SmearAudio, "smear-audio", false, "enable audio smearing to create 'perfect' segment timestamps") 212 213 fs.StringVar(&cli.TracingEndpoint, "tracing-endpoint", "", "gRPC endpoint to send traces to") 214 fs.IntVar(&cli.RateLimitPerSecond, "rate-limit-per-second", 0, "rate limit for requests per second per ip") 215 fs.IntVar(&cli.RateLimitBurst, "rate-limit-burst", 0, "rate limit burst for requests per ip") 216 fs.IntVar(&cli.RateLimitWebsocket, "rate-limit-websocket", 10, "number of concurrent websocket connections allowed per ip") ··· 242 fs.BoolVar(&cli.BehindHTTPSProxy, "behind-https-proxy", false, "set to true if this node is behind an https proxy and we should report https URLs even though the node isn't serving HTTPS") 243 cli.StringSliceFlag(fs, &cli.AdminDIDs, "admin-dids", []string{}, "comma-separated list of DIDs that are authorized to modify branding and other admin operations") 244 cli.StringSliceFlag(fs, &cli.Syndicate, "syndicate", []string{}, "list of DIDs that we should rebroadcast ('*' for everybody)") 245 + fs.BoolVar(&cli.PlayerTelemetry, "player-telemetry", true, "enable player telemetry") 246 + fs.StringVar(&cli.LocalDBURL, "local-db-url", "sqlite://$SP_DATA_DIR/localdb.sqlite", "URL of the local database to use for storing local data") 247 + cli.dataDirFlags = append(cli.dataDirFlags, &cli.LocalDBURL) 248 249 fs.Bool("external-signing", true, "DEPRECATED, does nothing.") 250 fs.Bool("insecure", false, "DEPRECATED, does nothing.")
+13
pkg/config/git/git.go
··· 82 homebrew := flag.Bool("homebrew", false, "print homebrew formula") 83 84 flag.Parse() 85 r, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true}) 86 if err != nil { 87 return err
··· 82 homebrew := flag.Bool("homebrew", false, "print homebrew formula") 83 84 flag.Parse() 85 + 86 + // handle CF_PAGES environment fallback 87 + if os.Getenv("CF_PAGES") != "" && *javascript { 88 + out := `export const version = "unknown"; export const buildTime = 0; export const uuid = "00000000-0000-0000-0000-000000000000";` 89 + if *output != "" { 90 + if err := os.WriteFile(*output, []byte(out), 0644); err != nil { 91 + return err 92 + } 93 + } else { 94 + fmt.Print(out) 95 + } 96 + return nil 97 + } 98 r, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true}) 99 if err != nil { 100 return err
+7
pkg/constants/constants.go
··· 5 var PLACE_STREAM_CHAT_MESSAGE = "place.stream.chat.message" //nolint:all 6 var PLACE_STREAM_CHAT_PROFILE = "place.stream.chat.profile" //nolint:all 7 var PLACE_STREAM_SERVER_SETTINGS = "place.stream.server.settings" //nolint:all 8 var PLACE_STREAM_MODERATION_PERMISSION = "place.stream.moderation.permission" //nolint:all 9 var STREAMPLACE_SIGNING_KEY = "signingKey" //nolint:all 10 var APP_BSKY_GRAPH_FOLLOW = "app.bsky.graph.follow" //nolint:all ··· 13 var PLACE_STREAM_CHAT_GATE = "place.stream.chat.gate" //nolint:all 14 var PLACE_STREAM_DEFAULT_METADATA = "place.stream.metadata.configuration" //nolint:all 15 var PLACE_STREAM_LIVE_RECOMMENDATIONS = "place.stream.live.recommendations" //nolint:all 16 17 const DID_KEY_PREFIX = "did:key" //nolint:all 18 const ADDRESS_KEY_PREFIX = "0x" //nolint:all
··· 5 var PLACE_STREAM_CHAT_MESSAGE = "place.stream.chat.message" //nolint:all 6 var PLACE_STREAM_CHAT_PROFILE = "place.stream.chat.profile" //nolint:all 7 var PLACE_STREAM_SERVER_SETTINGS = "place.stream.server.settings" //nolint:all 8 + var PLACE_STREAM_LIVE_TELEPORT = "place.stream.live.teleport" //nolint:all 9 var PLACE_STREAM_MODERATION_PERMISSION = "place.stream.moderation.permission" //nolint:all 10 var STREAMPLACE_SIGNING_KEY = "signingKey" //nolint:all 11 var APP_BSKY_GRAPH_FOLLOW = "app.bsky.graph.follow" //nolint:all ··· 14 var PLACE_STREAM_CHAT_GATE = "place.stream.chat.gate" //nolint:all 15 var PLACE_STREAM_DEFAULT_METADATA = "place.stream.metadata.configuration" //nolint:all 16 var PLACE_STREAM_LIVE_RECOMMENDATIONS = "place.stream.live.recommendations" //nolint:all 17 + 18 + // Streamplace badge types 19 + const ( 20 + BadgeTypeMod = "place.stream.badge.defs#mod" 21 + BadgeTypeStreamer = "place.stream.badge.defs#streamer" 22 + ) 23 24 const DID_KEY_PREFIX = "did:key" //nolint:all 25 const ADDRESS_KEY_PREFIX = "0x" //nolint:all
+8 -1
pkg/director/director.go
··· 9 "golang.org/x/sync/errgroup" 10 "stream.place/streamplace/pkg/bus" 11 "stream.place/streamplace/pkg/config" 12 "stream.place/streamplace/pkg/log" 13 "stream.place/streamplace/pkg/media" 14 "stream.place/streamplace/pkg/model" ··· 32 op *oatproxy.OATProxy 33 statefulDB *statedb.StatefulDB 34 replicator replication.Replicator 35 } 36 37 - func NewDirector(mm *media.MediaManager, mod model.Model, cli *config.CLI, bus *bus.Bus, op *oatproxy.OATProxy, statefulDB *statedb.StatefulDB, replicator replication.Replicator) *Director { 38 return &Director{ 39 mm: mm, 40 mod: mod, ··· 45 op: op, 46 statefulDB: statefulDB, 47 replicator: replicator, 48 } 49 } 50 ··· 76 started: make(chan struct{}), 77 statefulDB: d.statefulDB, 78 replicator: d.replicator, 79 } 80 d.streamSessions[not.Segment.RepoDID] = ss 81 g.Go(func() error {
··· 9 "golang.org/x/sync/errgroup" 10 "stream.place/streamplace/pkg/bus" 11 "stream.place/streamplace/pkg/config" 12 + "stream.place/streamplace/pkg/localdb" 13 "stream.place/streamplace/pkg/log" 14 "stream.place/streamplace/pkg/media" 15 "stream.place/streamplace/pkg/model" ··· 33 op *oatproxy.OATProxy 34 statefulDB *statedb.StatefulDB 35 replicator replication.Replicator 36 + localDB localdb.LocalDB 37 } 38 39 + func NewDirector(mm *media.MediaManager, mod model.Model, cli *config.CLI, bus *bus.Bus, op *oatproxy.OATProxy, statefulDB *statedb.StatefulDB, replicator replication.Replicator, ldb localdb.LocalDB) *Director { 40 return &Director{ 41 mm: mm, 42 mod: mod, ··· 47 op: op, 48 statefulDB: statefulDB, 49 replicator: replicator, 50 + localDB: ldb, 51 } 52 } 53 ··· 79 started: make(chan struct{}), 80 statefulDB: d.statefulDB, 81 replicator: d.replicator, 82 + // Initialize notification channels (buffered size 1 for coalescing) 83 + statusUpdateChan: make(chan struct{}, 1), 84 + originUpdateChan: make(chan struct{}, 1), 85 + localDB: d.localDB, 86 } 87 d.streamSessions[not.Segment.RepoDID] = ss 88 g.Go(func() error {
+98 -40
pkg/director/stream_session.go
··· 5 "context" 6 "fmt" 7 "net/url" 8 - "sync" 9 "time" 10 11 comatproto "github.com/bluesky-social/indigo/api/atproto" ··· 21 "stream.place/streamplace/pkg/bus" 22 "stream.place/streamplace/pkg/config" 23 "stream.place/streamplace/pkg/livepeer" 24 "stream.place/streamplace/pkg/log" 25 "stream.place/streamplace/pkg/media" 26 "stream.place/streamplace/pkg/model" ··· 44 segmentChan chan struct{} 45 lastStatus time.Time 46 lastStatusCID *string 47 - lastStatusLock sync.Mutex 48 lastOriginTime time.Time 49 - lastOriginLock sync.Mutex 50 - g *errgroup.Group 51 - started chan struct{} 52 - ctx context.Context 53 - packets []bus.PacketizedSegment 54 - statefulDB *statedb.StatefulDB 55 - replicator replication.Replicator 56 } 57 58 func (ss *StreamSession) Start(ctx context.Context, notif *media.NewSegmentNotification) error { ··· 111 112 close(ss.started) 113 114 - ss.Go(ctx, func() error { 115 - return ss.HandleMultistreamTargets(ctx) 116 }) 117 118 for { 119 select { 120 case <-ss.segmentChan: 121 // reset timer 122 case <-ctx.Done(): 123 return ss.g.Wait() 124 // case <-time.After(time.Minute * 1): 125 case <-time.After(ss.cli.StreamSessionTimeout): ··· 128 for _, r := range allRenditions { 129 ss.bus.EndSession(ctx, spseg.Creator, r.Name) 130 } 131 if notif.Local { 132 ss.Go(ctx, func() error { 133 return ss.DeleteStatus(spseg.Creator) ··· 164 aqt := aqtime.FromTime(notif.Segment.StartTime) 165 ctx = log.WithLogValues(ctx, "segID", notif.Segment.ID, "repoDID", notif.Segment.RepoDID, "timestamp", aqt.FileSafeString()) 166 notif.Segment.MediaData.Size = len(notif.Data) 167 - err := ss.mod.CreateSegment(notif.Segment) 168 if err != nil { 169 return fmt.Errorf("could not add segment to database: %w", err) 170 } ··· 188 } 189 190 if notif.Local { 191 - ss.Go(ctx, func() error { 192 - return ss.UpdateStatus(ctx, spseg.Creator) 193 - }) 194 - 195 - ss.Go(ctx, func() error { 196 - return ss.UpdateBroadcastOrigin(ctx) 197 - }) 198 } 199 200 if ss.cli.LivepeerGatewayURL != "" { ··· 250 if err != nil { 251 log.Error(ctx, "failed to enqueue notification task", "err", err) 252 } 253 - return ss.UpdateStatus(ctx, spseg.Creator) 254 }) 255 } else { 256 log.Warn(ctx, "no livestream detected in stream, skipping notification blast", "repoDID", spseg.Creator) ··· 282 return nil 283 } 284 defer lock.Unlock() 285 - oldThumb, err := ss.mod.LatestThumbnailForUser(not.Segment.RepoDID) 286 if err != nil { 287 return err 288 } ··· 301 if err != nil { 302 return err 303 } 304 - thumb := &model.Thumbnail{ 305 Format: "jpeg", 306 SegmentID: not.Segment.ID, 307 } 308 - err = ss.mod.CreateThumbnail(thumb) 309 if err != nil { 310 return err 311 } 312 return nil 313 } 314 315 - func (ss *StreamSession) UpdateStatus(ctx context.Context, repoDID string) error { 316 - ctx = log.WithLogValues(ctx, "func", "UpdateStatus") 317 - ss.lastStatusLock.Lock() 318 - defer ss.lastStatusLock.Unlock() 319 - if time.Since(ss.lastStatus) < time.Minute { 320 - log.Debug(ctx, "not updating status, last status was less than 1 minute ago") 321 - return nil 322 } 323 324 client, err := ss.GetClientByDID(repoDID) 325 if err != nil { ··· 368 }, 369 } 370 371 - duration := int64(120) 372 status := bsky.ActorStatus{ 373 Status: "app.bsky.actor.status#live", 374 DurationMinutes: &duration, ··· 421 422 func (ss *StreamSession) DeleteStatus(repoDID string) error { 423 // need a special extra context because the stream session context is already cancelled 424 ctx := log.WithLogValues(context.Background(), "func", "DeleteStatus", "repoDID", repoDID) 425 - ss.lastStatusLock.Lock() 426 - defer ss.lastStatusLock.Unlock() 427 if ss.lastStatusCID == nil { 428 log.Debug(ctx, "no status cid to delete") 429 return nil ··· 452 453 var originUpdateInterval = time.Second * 30 454 455 - func (ss *StreamSession) UpdateBroadcastOrigin(ctx context.Context) error { 456 - ctx = log.WithLogValues(ctx, "func", "UpdateStatus") 457 - ss.lastOriginLock.Lock() 458 - defer ss.lastOriginLock.Unlock() 459 - if time.Since(ss.lastOriginTime) < originUpdateInterval { 460 - log.Debug(ctx, "not updating origin, last origin was less than 30 seconds ago") 461 - return nil 462 } 463 broadcaster := fmt.Sprintf("did:web:%s", ss.cli.BroadcasterHost) 464 origin := streamplace.BroadcastOrigin{ 465 Streamer: ss.repoDID,
··· 5 "context" 6 "fmt" 7 "net/url" 8 "time" 9 10 comatproto "github.com/bluesky-social/indigo/api/atproto" ··· 20 "stream.place/streamplace/pkg/bus" 21 "stream.place/streamplace/pkg/config" 22 "stream.place/streamplace/pkg/livepeer" 23 + "stream.place/streamplace/pkg/localdb" 24 "stream.place/streamplace/pkg/log" 25 "stream.place/streamplace/pkg/media" 26 "stream.place/streamplace/pkg/model" ··· 44 segmentChan chan struct{} 45 lastStatus time.Time 46 lastStatusCID *string 47 lastOriginTime time.Time 48 + localDB localdb.LocalDB 49 + 50 + // Channels for background workers 51 + statusUpdateChan chan struct{} // Signal to update status 52 + originUpdateChan chan struct{} // Signal to update broadcast origin 53 + 54 + g *errgroup.Group 55 + started chan struct{} 56 + ctx context.Context 57 + packets []bus.PacketizedSegment 58 + statefulDB *statedb.StatefulDB 59 + replicator replication.Replicator 60 } 61 62 func (ss *StreamSession) Start(ctx context.Context, notif *media.NewSegmentNotification) error { ··· 115 116 close(ss.started) 117 118 + // Start background workers for status and origin updates 119 + ss.g.Go(func() error { 120 + return ss.statusUpdateLoop(ctx, spseg.Creator) 121 + }) 122 + ss.g.Go(func() error { 123 + return ss.originUpdateLoop(ctx) 124 }) 125 126 + if notif.Local { 127 + ss.Go(ctx, func() error { 128 + return ss.HandleMultistreamTargets(ctx) 129 + }) 130 + } 131 + 132 for { 133 select { 134 case <-ss.segmentChan: 135 // reset timer 136 case <-ctx.Done(): 137 + // Signal all background workers to stop 138 return ss.g.Wait() 139 // case <-time.After(time.Minute * 1): 140 case <-time.After(ss.cli.StreamSessionTimeout): ··· 143 for _, r := range allRenditions { 144 ss.bus.EndSession(ctx, spseg.Creator, r.Name) 145 } 146 + // Signal background workers to stop 147 if notif.Local { 148 ss.Go(ctx, func() error { 149 return ss.DeleteStatus(spseg.Creator) ··· 180 aqt := aqtime.FromTime(notif.Segment.StartTime) 181 ctx = log.WithLogValues(ctx, "segID", notif.Segment.ID, "repoDID", notif.Segment.RepoDID, "timestamp", aqt.FileSafeString()) 182 notif.Segment.MediaData.Size = len(notif.Data) 183 + err := ss.localDB.CreateSegment(notif.Segment) 184 if err != nil { 185 return fmt.Errorf("could not add segment to database: %w", err) 186 } ··· 204 } 205 206 if notif.Local { 207 + ss.UpdateStatus(ctx, spseg.Creator) 208 + ss.UpdateBroadcastOrigin(ctx) 209 } 210 211 if ss.cli.LivepeerGatewayURL != "" { ··· 261 if err != nil { 262 log.Error(ctx, "failed to enqueue notification task", "err", err) 263 } 264 + ss.UpdateStatus(ctx, spseg.Creator) 265 + return nil 266 }) 267 } else { 268 log.Warn(ctx, "no livestream detected in stream, skipping notification blast", "repoDID", spseg.Creator) ··· 294 return nil 295 } 296 defer lock.Unlock() 297 + oldThumb, err := ss.localDB.LatestThumbnailForUser(not.Segment.RepoDID) 298 if err != nil { 299 return err 300 } ··· 313 if err != nil { 314 return err 315 } 316 + thumb := &localdb.Thumbnail{ 317 Format: "jpeg", 318 SegmentID: not.Segment.ID, 319 } 320 + err = ss.localDB.CreateThumbnail(thumb) 321 if err != nil { 322 return err 323 } 324 return nil 325 } 326 327 + // UpdateStatus signals the background worker to update status (non-blocking) 328 + func (ss *StreamSession) UpdateStatus(ctx context.Context, repoDID string) { 329 + select { 330 + case ss.statusUpdateChan <- struct{}{}: 331 + default: 332 + // Channel full, signal already pending 333 } 334 + } 335 + 336 + // statusUpdateLoop runs as a background goroutine for the session lifetime 337 + func (ss *StreamSession) statusUpdateLoop(ctx context.Context, repoDID string) error { 338 + ctx = log.WithLogValues(ctx, "func", "statusUpdateLoop") 339 + for { 340 + select { 341 + case <-ctx.Done(): 342 + return nil 343 + case <-ss.statusUpdateChan: 344 + if time.Since(ss.lastStatus) < time.Minute { 345 + log.Debug(ctx, "not updating status, last status was less than 1 minute ago") 346 + continue 347 + } 348 + if err := ss.doUpdateStatus(ctx, repoDID); err != nil { 349 + log.Error(ctx, "failed to update status", "error", err) 350 + } 351 + } 352 + } 353 + } 354 + 355 + // doUpdateStatus performs the actual status update work 356 + func (ss *StreamSession) doUpdateStatus(ctx context.Context, repoDID string) error { 357 + ctx = log.WithLogValues(ctx, "func", "doUpdateStatus") 358 359 client, err := ss.GetClientByDID(repoDID) 360 if err != nil { ··· 403 }, 404 } 405 406 + duration := int64(10) 407 status := bsky.ActorStatus{ 408 Status: "app.bsky.actor.status#live", 409 DurationMinutes: &duration, ··· 456 457 func (ss *StreamSession) DeleteStatus(repoDID string) error { 458 // need a special extra context because the stream session context is already cancelled 459 + // No lock needed - this runs during teardown after the background worker has exited 460 ctx := log.WithLogValues(context.Background(), "func", "DeleteStatus", "repoDID", repoDID) 461 if ss.lastStatusCID == nil { 462 log.Debug(ctx, "no status cid to delete") 463 return nil ··· 486 487 var originUpdateInterval = time.Second * 30 488 489 + // UpdateBroadcastOrigin signals the background worker to update origin (non-blocking) 490 + func (ss *StreamSession) UpdateBroadcastOrigin(ctx context.Context) { 491 + select { 492 + case ss.originUpdateChan <- struct{}{}: 493 + default: 494 + // Channel full, signal already pending 495 } 496 + } 497 + 498 + // originUpdateLoop runs as a background goroutine for the session lifetime 499 + func (ss *StreamSession) originUpdateLoop(ctx context.Context) error { 500 + ctx = log.WithLogValues(ctx, "func", "originUpdateLoop") 501 + for { 502 + select { 503 + case <-ctx.Done(): 504 + return nil 505 + case <-ss.originUpdateChan: 506 + if time.Since(ss.lastOriginTime) < originUpdateInterval { 507 + log.Debug(ctx, "not updating origin, last origin was less than 30 seconds ago") 508 + continue 509 + } 510 + if err := ss.doUpdateBroadcastOrigin(ctx); err != nil { 511 + log.Error(ctx, "failed to update broadcast origin", "error", err) 512 + } 513 + } 514 + } 515 + } 516 + 517 + // doUpdateBroadcastOrigin performs the actual broadcast origin update work 518 + func (ss *StreamSession) doUpdateBroadcastOrigin(ctx context.Context) error { 519 + ctx = log.WithLogValues(ctx, "func", "doUpdateBroadcastOrigin") 520 + 521 broadcaster := fmt.Sprintf("did:web:%s", ss.cli.BroadcasterHost) 522 origin := streamplace.BroadcastOrigin{ 523 Streamer: ss.repoDID,
+4
pkg/gen/gen.go
··· 34 streamplace.MetadataContentRights{}, 35 streamplace.MetadataContentWarnings{}, 36 streamplace.ModerationPermission{}, 37 streamplace.LiveRecommendations{}, 38 ); err != nil { 39 panic(err) 40 }
··· 34 streamplace.MetadataContentRights{}, 35 streamplace.MetadataContentWarnings{}, 36 streamplace.ModerationPermission{}, 37 + streamplace.LiveTeleport{}, 38 streamplace.LiveRecommendations{}, 39 + streamplace.BadgeIssuance{}, 40 + streamplace.BadgeDisplay{}, 41 + streamplace.BadgeDisplay_BadgeSelection{}, 42 ); err != nil { 43 panic(err) 44 }
+1 -1
pkg/integrations/discord/send-livestream.go
··· 67 log.Warn(ctx, "failed to parse URL", "err", err) 68 } else { 69 suffix = fmt.Sprintf(" on %s!", u.Host) 70 - payload.Embeds[0].URL = fmt.Sprintf("%s/%s", *ls.Url, lsv.Author.Handle) 71 } 72 } 73
··· 67 log.Warn(ctx, "failed to parse URL", "err", err) 68 } else { 69 suffix = fmt.Sprintf(" on %s!", u.Host) 70 + payload.Embeds[0].URL = *ls.Url 71 } 72 } 73
+139 -11
pkg/linking/linking.go
··· 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "fmt" 8 "net/url" 9 10 "golang.org/x/net/html" 11 "stream.place/streamplace/pkg/streamplace" 12 ) 13 14 type Linker struct { 15 BaseHTML []byte 16 } 17 18 - func NewLinker(ctx context.Context, baseHTML []byte) (*Linker, error) { 19 _, err := html.Parse(bytes.NewReader(baseHTML)) 20 if err != nil { 21 return nil, err 22 } 23 24 - return &Linker{BaseHTML: baseHTML}, nil 25 } 26 27 type PageConfig struct { 28 Title string 29 Metas []MetaTag 30 SentryDSN string 31 } 32 33 // Define all meta tags in a structured way ··· 37 Content string 38 } 39 40 func (l *Linker) GenerateStreamerCard(ctx context.Context, u *url.URL, lsv *streamplace.Livestream_LivestreamView, sentryDSN string) ([]byte, error) { 41 if u == nil { 42 return nil, errors.New("url is nil") ··· 49 return nil, errors.New("livestream view is not a livestream") 50 } 51 52 - titleStr := fmt.Sprintf("@%s's livestream on %s", lsv.Author.Handle, u.Host) 53 outURL := u.String() 54 - 55 - pageTitle := fmt.Sprintf("@%s | %s", lsv.Author.Handle, u.Host) 56 57 thumbURL, _ := url.Parse(u.String()) 58 thumbURL.Path = "/xrpc/place.stream.live.getProfileCard" ··· 66 // Facebook Meta Tags 67 {Type: "property", Key: "og:url", Content: u.String()}, 68 {Type: "property", Key: "og:type", Content: "website"}, 69 - {Type: "property", Key: "og:title", Content: titleStr}, 70 {Type: "property", Key: "og:description", Content: ls.Title}, 71 {Type: "property", Key: "og:image", Content: thumbURL.String()}, 72 ··· 74 {Type: "name", Key: "twitter:card", Content: "summary_large_image"}, 75 {Type: "property", Key: "twitter:domain", Content: u.Host}, 76 {Type: "property", Key: "twitter:url", Content: outURL}, 77 - {Type: "name", Key: "twitter:title", Content: titleStr}, 78 {Type: "name", Key: "twitter:description", Content: ls.Title}, 79 {Type: "name", Key: "twitter:image", Content: thumbURL.String()}, 80 } 81 82 return l.GenerateHTML(ctx, &PageConfig{ 83 - Title: pageTitle, 84 Metas: metaTags, 85 SentryDSN: sentryDSN, 86 }) ··· 103 {Type: "property", Key: "og:url", Content: u.String()}, 104 {Type: "property", Key: "og:type", Content: "website"}, 105 {Type: "property", Key: "og:title", Content: "Stream.place"}, 106 - {Type: "property", Key: "og:description", Content: "Stream.place is open-source livestreaming on the AT Protocol."}, 107 {Type: "property", Key: "og:image", Content: thumbURL.String()}, 108 109 // Twitter Meta Tags ··· 111 {Type: "property", Key: "twitter:domain", Content: u.Host}, 112 {Type: "property", Key: "twitter:url", Content: u.String()}, 113 {Type: "name", Key: "twitter:title", Content: "Stream.place"}, 114 - {Type: "name", Key: "twitter:description", Content: "Stream.place is open-source livestreaming on the AT Protocol."}, 115 {Type: "name", Key: "twitter:image", Content: thumbURL.String()}, 116 } 117 118 return l.GenerateHTML(ctx, &PageConfig{ 119 - Title: "Stream.place", 120 Metas: metaTags, 121 SentryDSN: sentryDSN, 122 })
··· 3 import ( 4 "bytes" 5 "context" 6 + "encoding/json" 7 "errors" 8 "fmt" 9 + "log" 10 "net/url" 11 12 "golang.org/x/net/html" 13 + "stream.place/streamplace/pkg/config" 14 + "stream.place/streamplace/pkg/statedb" 15 "stream.place/streamplace/pkg/streamplace" 16 ) 17 18 type Linker struct { 19 BaseHTML []byte 20 + sdb *statedb.StatefulDB 21 + cli *config.CLI 22 } 23 24 + func NewLinker(ctx context.Context, baseHTML []byte, sdb *statedb.StatefulDB, cli *config.CLI) (*Linker, error) { 25 _, err := html.Parse(bytes.NewReader(baseHTML)) 26 if err != nil { 27 return nil, err 28 } 29 30 + return &Linker{BaseHTML: baseHTML, sdb: sdb, cli: cli}, nil 31 } 32 33 type PageConfig struct { 34 Title string 35 Metas []MetaTag 36 SentryDSN string 37 + Branding []string 38 } 39 40 // Define all meta tags in a structured way ··· 44 Content string 45 } 46 47 + var BrandingAssetList = [...]string{ 48 + "siteTitle", 49 + "siteDescription", 50 + "primaryColor", 51 + "accentColor", 52 + "defaultStreamer", 53 + "mainLogo", 54 + "favicon", 55 + "sidebarBg", 56 + "legalLinks", 57 + } 58 + 59 + // fetch branding assets for a given broadcaster DID 60 + func (l *Linker) getBrandingAssets(broadcasterDid string) ([]streamplace.BrandingGetBranding_BrandingAsset, error) { 61 + ret := make([]streamplace.BrandingGetBranding_BrandingAsset, 0) 62 + for _, asset := range BrandingAssetList { 63 + blob, err := l.sdb.GetBrandingBlob(broadcasterDid, asset) 64 + if err != nil { 65 + // this can probably include a 'record not found' error, in which case we skip 66 + log.Printf("error fetching branding asset %s for broadcaster %s: %v", asset, broadcasterDid, err) 67 + continue 68 + } 69 + asset := streamplace.BrandingGetBranding_BrandingAsset{ 70 + Key: blob.Key, 71 + MimeType: blob.MimeType, 72 + } 73 + 74 + if blob.Width != nil { 75 + w := int64(*blob.Width) 76 + asset.Width = &w 77 + } 78 + if blob.Height != nil { 79 + h := int64(*blob.Height) 80 + asset.Height = &h 81 + } 82 + 83 + // process based on mime type 84 + if blob.MimeType == "text/plain" { 85 + str := string(blob.Data) 86 + asset.Data = &str 87 + } else { 88 + url := fmt.Sprintf("/xrpc/place.stream.branding.getBlob?key=%s&broadcaster=%s", blob.Key, broadcasterDid) 89 + asset.Url = &url 90 + } 91 + ret = append(ret, asset) 92 + } 93 + 94 + return ret, nil 95 + } 96 + 97 func (l *Linker) GenerateStreamerCard(ctx context.Context, u *url.URL, lsv *streamplace.Livestream_LivestreamView, sentryDSN string) ([]byte, error) { 98 if u == nil { 99 return nil, errors.New("url is nil") ··· 106 return nil, errors.New("livestream view is not a livestream") 107 } 108 109 + titleStr := fmt.Sprintf("@%s's livestream on ", lsv.Author.Handle) 110 outURL := u.String() 111 112 thumbURL, _ := url.Parse(u.String()) 113 thumbURL.Path = "/xrpc/place.stream.live.getProfileCard" ··· 121 // Facebook Meta Tags 122 {Type: "property", Key: "og:url", Content: u.String()}, 123 {Type: "property", Key: "og:type", Content: "website"}, 124 {Type: "property", Key: "og:description", Content: ls.Title}, 125 {Type: "property", Key: "og:image", Content: thumbURL.String()}, 126 ··· 128 {Type: "name", Key: "twitter:card", Content: "summary_large_image"}, 129 {Type: "property", Key: "twitter:domain", Content: u.Host}, 130 {Type: "property", Key: "twitter:url", Content: outURL}, 131 {Type: "name", Key: "twitter:description", Content: ls.Title}, 132 {Type: "name", Key: "twitter:image", Content: thumbURL.String()}, 133 } 134 + brandingTitle := "streamplace node" 135 + if l.sdb != nil && l.cli != nil { 136 + branding, err := l.getBrandingAssets("did:web:" + l.cli.BroadcasterHost) 137 + if err == nil { 138 + for i := range branding { 139 + val := branding[i] 140 + if val.Key == "siteTitle" && val.Data != nil { 141 + brandingTitle = *val.Data 142 + } 143 + marshalledJson, err := json.Marshal(val) 144 + if err != nil { 145 + fmt.Printf("error marshalling branding asset %s: %v\n", val.Key, err) 146 + continue 147 + } 148 + metaTags = append(metaTags, MetaTag{ 149 + Type: "name", 150 + Key: "internal-brand:" + val.Key, 151 + Content: string(marshalledJson), 152 + }) 153 + } 154 + } else { 155 + // log but we should not block rendering 156 + fmt.Printf("error fetching branding assets: %v\n", err) 157 + } 158 + } 159 + 160 + // do twitter/og title after 161 + metaTags = append(metaTags, MetaTag{ 162 + Type: "property", 163 + Key: "og:title", 164 + Content: fmt.Sprintf("%s%s", titleStr, brandingTitle), 165 + }) 166 + metaTags = append(metaTags, MetaTag{ 167 + Type: "name", 168 + Key: "twitter:title", 169 + Content: fmt.Sprintf("%s%s", titleStr, brandingTitle), 170 + }) 171 172 return l.GenerateHTML(ctx, &PageConfig{ 173 + Title: fmt.Sprintf("%s%s", titleStr, brandingTitle), 174 Metas: metaTags, 175 SentryDSN: sentryDSN, 176 }) ··· 193 {Type: "property", Key: "og:url", Content: u.String()}, 194 {Type: "property", Key: "og:type", Content: "website"}, 195 {Type: "property", Key: "og:title", Content: "Stream.place"}, 196 + {Type: "property", Key: "og:description", Content: "Open-source livestreaming on the AT Protocol."}, 197 {Type: "property", Key: "og:image", Content: thumbURL.String()}, 198 199 // Twitter Meta Tags ··· 201 {Type: "property", Key: "twitter:domain", Content: u.Host}, 202 {Type: "property", Key: "twitter:url", Content: u.String()}, 203 {Type: "name", Key: "twitter:title", Content: "Stream.place"}, 204 + {Type: "name", Key: "twitter:description", Content: "Open-source livestreaming on the AT Protocol."}, 205 {Type: "name", Key: "twitter:image", Content: thumbURL.String()}, 206 } 207 208 + brandingTitle := "streamplace node" 209 + if l.sdb != nil && l.cli != nil { 210 + branding, err := l.getBrandingAssets("did:web:" + l.cli.BroadcasterHost) 211 + if err == nil { 212 + for i := range branding { 213 + val := branding[i] 214 + if val.Key == "siteTitle" && val.Data != nil { 215 + brandingTitle = *val.Data 216 + } 217 + marshalledJson, err := json.Marshal(val) 218 + if err != nil { 219 + fmt.Printf("error marshalling branding asset %s: %v\n", val.Key, err) 220 + continue 221 + } 222 + metaTags = append(metaTags, MetaTag{ 223 + Type: "name", 224 + Key: "internal-brand:" + val.Key, 225 + Content: string(marshalledJson), 226 + }) 227 + } 228 + } else { 229 + // log but we should not block rendering 230 + fmt.Printf("error fetching branding assets: %v\n", err) 231 + } 232 + } 233 + 234 + // do twitter/og title after 235 + metaTags = append(metaTags, MetaTag{ 236 + Type: "property", 237 + Key: "og:title", 238 + Content: brandingTitle, 239 + }) 240 + metaTags = append(metaTags, MetaTag{ 241 + Type: "name", 242 + Key: "twitter:title", 243 + Content: brandingTitle, 244 + }) 245 + 246 return l.GenerateHTML(ctx, &PageConfig{ 247 + Title: brandingTitle, 248 Metas: metaTags, 249 SentryDSN: sentryDSN, 250 })
+2 -2
pkg/linking/linking_test.go
··· 29 30 func TestNewLinker(t *testing.T) { 31 index := IndexHTML(t) 32 - linker, err := NewLinker(context.Background(), index) 33 require.NoError(t, err) 34 require.NotNil(t, linker) 35 } 36 37 func TestGenerateLinkCard(t *testing.T) { 38 index := IndexHTML(t) 39 - linker, err := NewLinker(context.Background(), index) 40 require.NoError(t, err) 41 require.NotNil(t, linker) 42
··· 29 30 func TestNewLinker(t *testing.T) { 31 index := IndexHTML(t) 32 + linker, err := NewLinker(context.Background(), index, nil, nil) 33 require.NoError(t, err) 34 require.NotNil(t, linker) 35 } 36 37 func TestGenerateLinkCard(t *testing.T) { 38 index := IndexHTML(t) 39 + linker, err := NewLinker(context.Background(), index, nil, nil) 40 require.NoError(t, err) 41 require.NotNil(t, linker) 42
+81
pkg/localdb/localdb.go
···
··· 1 + package localdb 2 + 3 + import ( 4 + "context" 5 + "fmt" 6 + "strings" 7 + "time" 8 + 9 + "gorm.io/driver/sqlite" 10 + "gorm.io/gorm" 11 + "gorm.io/plugin/prometheus" 12 + "stream.place/streamplace/pkg/config" 13 + "stream.place/streamplace/pkg/log" 14 + ) 15 + 16 + type LocalDB interface { 17 + CreateSegment(segment *Segment) error 18 + MostRecentSegments() ([]Segment, error) 19 + LatestSegmentForUser(user string) (*Segment, error) 20 + LatestSegmentsForUser(user string, limit int, before *time.Time, after *time.Time) ([]Segment, error) 21 + FilterLiveRepoDIDs(repoDIDs []string) ([]string, error) 22 + CreateThumbnail(thumb *Thumbnail) error 23 + LatestThumbnailForUser(user string) (*Thumbnail, error) 24 + GetSegment(id string) (*Segment, error) 25 + GetExpiredSegments(ctx context.Context) ([]Segment, error) 26 + DeleteSegment(ctx context.Context, id string) error 27 + StartSegmentCleaner(ctx context.Context) error 28 + SegmentCleaner(ctx context.Context) error 29 + } 30 + 31 + type LocalDatabase struct { 32 + DB *gorm.DB 33 + } 34 + 35 + func MakeDB(dbURL string) (LocalDB, error) { 36 + log.Log(context.Background(), "starting database", "dbURL", dbURL) 37 + if strings.HasPrefix(dbURL, "sqlite://") { 38 + dbURL = dbURL[len("sqlite://"):] 39 + } else if dbURL != ":memory:" { 40 + return nil, fmt.Errorf("unsupported database URL (most start with sqlite://): %s", dbURL) 41 + } 42 + dial := sqlite.Open(dbURL) 43 + 44 + db, err := gorm.Open(dial, &gorm.Config{ 45 + SkipDefaultTransaction: true, 46 + TranslateError: true, 47 + Logger: config.GormLogger, 48 + }) 49 + if err != nil { 50 + return nil, fmt.Errorf("error starting database: %w", err) 51 + } 52 + err = db.Exec("PRAGMA journal_mode=WAL;").Error 53 + if err != nil { 54 + return nil, fmt.Errorf("error setting journal mode: %w", err) 55 + } 56 + 57 + err = db.Use(prometheus.New(prometheus.Config{ 58 + DBName: "localdb", 59 + RefreshInterval: 10, 60 + StartServer: false, 61 + })) 62 + if err != nil { 63 + return nil, fmt.Errorf("error using prometheus plugin: %w", err) 64 + } 65 + 66 + sqlDB, err := db.DB() 67 + if err != nil { 68 + return nil, fmt.Errorf("error getting database: %w", err) 69 + } 70 + sqlDB.SetMaxOpenConns(1) 71 + for _, model := range []any{ 72 + Segment{}, 73 + Thumbnail{}, 74 + } { 75 + err = db.AutoMigrate(model) 76 + if err != nil { 77 + return nil, err 78 + } 79 + } 80 + return &LocalDatabase{DB: db}, nil 81 + }
+410
pkg/localdb/segment.go
···
··· 1 + package localdb 2 + 3 + import ( 4 + "context" 5 + "database/sql/driver" 6 + "encoding/json" 7 + "errors" 8 + "fmt" 9 + "time" 10 + 11 + "gorm.io/gorm" 12 + "stream.place/streamplace/pkg/aqtime" 13 + "stream.place/streamplace/pkg/log" 14 + "stream.place/streamplace/pkg/streamplace" 15 + ) 16 + 17 + type SegmentMediadataVideo struct { 18 + Width int `json:"width"` 19 + Height int `json:"height"` 20 + FPSNum int `json:"fpsNum"` 21 + FPSDen int `json:"fpsDen"` 22 + BFrames bool `json:"bframes"` 23 + } 24 + 25 + type SegmentMediadataAudio struct { 26 + Rate int `json:"rate"` 27 + Channels int `json:"channels"` 28 + } 29 + 30 + type SegmentMediaData struct { 31 + Video []*SegmentMediadataVideo `json:"video"` 32 + Audio []*SegmentMediadataAudio `json:"audio"` 33 + Duration int64 `json:"duration"` 34 + Size int `json:"size"` 35 + } 36 + 37 + // Scan scan value into Jsonb, implements sql.Scanner interface 38 + func (j *SegmentMediaData) Scan(value any) error { 39 + bytes, ok := value.([]byte) 40 + if !ok { 41 + return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value)) 42 + } 43 + 44 + result := SegmentMediaData{} 45 + err := json.Unmarshal(bytes, &result) 46 + *j = SegmentMediaData(result) 47 + return err 48 + } 49 + 50 + // Value return json value, implement driver.Valuer interface 51 + func (j SegmentMediaData) Value() (driver.Value, error) { 52 + return json.Marshal(j) 53 + } 54 + 55 + // ContentRights represents content rights and attribution information 56 + type ContentRights struct { 57 + CopyrightNotice *string `json:"copyrightNotice,omitempty"` 58 + CopyrightYear *int64 `json:"copyrightYear,omitempty"` 59 + Creator *string `json:"creator,omitempty"` 60 + CreditLine *string `json:"creditLine,omitempty"` 61 + License *string `json:"license,omitempty"` 62 + } 63 + 64 + // Scan scan value into ContentRights, implements sql.Scanner interface 65 + func (c *ContentRights) Scan(value any) error { 66 + if value == nil { 67 + *c = ContentRights{} 68 + return nil 69 + } 70 + bytes, ok := value.([]byte) 71 + if !ok { 72 + return errors.New(fmt.Sprint("Failed to unmarshal ContentRights value:", value)) 73 + } 74 + 75 + result := ContentRights{} 76 + err := json.Unmarshal(bytes, &result) 77 + *c = ContentRights(result) 78 + return err 79 + } 80 + 81 + // Value return json value, implement driver.Valuer interface 82 + func (c ContentRights) Value() (driver.Value, error) { 83 + return json.Marshal(c) 84 + } 85 + 86 + // DistributionPolicy represents distribution policy information 87 + type DistributionPolicy struct { 88 + DeleteAfterSeconds *int64 `json:"deleteAfterSeconds,omitempty"` 89 + } 90 + 91 + // Scan scan value into DistributionPolicy, implements sql.Scanner interface 92 + func (d *DistributionPolicy) Scan(value any) error { 93 + if value == nil { 94 + *d = DistributionPolicy{} 95 + return nil 96 + } 97 + bytes, ok := value.([]byte) 98 + if !ok { 99 + return errors.New(fmt.Sprint("Failed to unmarshal DistributionPolicy value:", value)) 100 + } 101 + 102 + result := DistributionPolicy{} 103 + err := json.Unmarshal(bytes, &result) 104 + *d = DistributionPolicy(result) 105 + return err 106 + } 107 + 108 + // Value return json value, implement driver.Valuer interface 109 + func (d DistributionPolicy) Value() (driver.Value, error) { 110 + return json.Marshal(d) 111 + } 112 + 113 + // ContentWarningsSlice is a custom type for storing content warnings as JSON in the database 114 + type ContentWarningsSlice []string 115 + 116 + // Scan scan value into ContentWarningsSlice, implements sql.Scanner interface 117 + func (c *ContentWarningsSlice) Scan(value any) error { 118 + if value == nil { 119 + *c = ContentWarningsSlice{} 120 + return nil 121 + } 122 + bytes, ok := value.([]byte) 123 + if !ok { 124 + return errors.New(fmt.Sprint("Failed to unmarshal ContentWarningsSlice value:", value)) 125 + } 126 + 127 + result := ContentWarningsSlice{} 128 + err := json.Unmarshal(bytes, &result) 129 + *c = ContentWarningsSlice(result) 130 + return err 131 + } 132 + 133 + // Value return json value, implement driver.Valuer interface 134 + func (c ContentWarningsSlice) Value() (driver.Value, error) { 135 + return json.Marshal(c) 136 + } 137 + 138 + type Segment struct { 139 + ID string `json:"id" gorm:"primaryKey"` 140 + SigningKeyDID string `json:"signingKeyDID" gorm:"column:signing_key_did"` 141 + StartTime time.Time `json:"startTime" gorm:"index:latest_segments,priority:2;index:start_time"` 142 + RepoDID string `json:"repoDID" gorm:"index:latest_segments,priority:1;column:repo_did"` 143 + Title string `json:"title"` 144 + Size int `json:"size" gorm:"column:size"` 145 + MediaData *SegmentMediaData `json:"mediaData,omitempty"` 146 + ContentWarnings ContentWarningsSlice `json:"contentWarnings,omitempty"` 147 + ContentRights *ContentRights `json:"contentRights,omitempty"` 148 + DistributionPolicy *DistributionPolicy `json:"distributionPolicy,omitempty"` 149 + DeleteAfter *time.Time `json:"deleteAfter,omitempty" gorm:"column:delete_after;index:delete_after"` 150 + } 151 + 152 + func (s *Segment) ToStreamplaceSegment() (*streamplace.Segment, error) { 153 + aqt := aqtime.FromTime(s.StartTime) 154 + if s.MediaData == nil { 155 + return nil, fmt.Errorf("media data is nil") 156 + } 157 + if len(s.MediaData.Video) == 0 || s.MediaData.Video[0] == nil { 158 + return nil, fmt.Errorf("video data is nil") 159 + } 160 + if len(s.MediaData.Audio) == 0 || s.MediaData.Audio[0] == nil { 161 + return nil, fmt.Errorf("audio data is nil") 162 + } 163 + duration := s.MediaData.Duration 164 + sizei64 := int64(s.Size) 165 + 166 + // Convert model metadata to streamplace metadata 167 + var contentRights *streamplace.MetadataContentRights 168 + if s.ContentRights != nil { 169 + contentRights = &streamplace.MetadataContentRights{ 170 + CopyrightNotice: s.ContentRights.CopyrightNotice, 171 + CopyrightYear: s.ContentRights.CopyrightYear, 172 + Creator: s.ContentRights.Creator, 173 + CreditLine: s.ContentRights.CreditLine, 174 + License: s.ContentRights.License, 175 + } 176 + } 177 + 178 + var contentWarnings *streamplace.MetadataContentWarnings 179 + if len(s.ContentWarnings) > 0 { 180 + contentWarnings = &streamplace.MetadataContentWarnings{ 181 + Warnings: []string(s.ContentWarnings), 182 + } 183 + } 184 + 185 + var distributionPolicy *streamplace.MetadataDistributionPolicy 186 + if s.DistributionPolicy != nil && s.DistributionPolicy.DeleteAfterSeconds != nil { 187 + distributionPolicy = &streamplace.MetadataDistributionPolicy{ 188 + DeleteAfter: s.DistributionPolicy.DeleteAfterSeconds, 189 + } 190 + } 191 + 192 + return &streamplace.Segment{ 193 + LexiconTypeID: "place.stream.segment", 194 + Creator: s.RepoDID, 195 + Id: s.ID, 196 + SigningKey: s.SigningKeyDID, 197 + StartTime: string(aqt), 198 + Duration: &duration, 199 + Size: &sizei64, 200 + ContentRights: contentRights, 201 + ContentWarnings: contentWarnings, 202 + DistributionPolicy: distributionPolicy, 203 + Video: []*streamplace.Segment_Video{ 204 + { 205 + Codec: "h264", 206 + Width: int64(s.MediaData.Video[0].Width), 207 + Height: int64(s.MediaData.Video[0].Height), 208 + Framerate: &streamplace.Segment_Framerate{ 209 + Num: int64(s.MediaData.Video[0].FPSNum), 210 + Den: int64(s.MediaData.Video[0].FPSDen), 211 + }, 212 + Bframes: &s.MediaData.Video[0].BFrames, 213 + }, 214 + }, 215 + Audio: []*streamplace.Segment_Audio{ 216 + { 217 + Codec: "opus", 218 + Rate: int64(s.MediaData.Audio[0].Rate), 219 + Channels: int64(s.MediaData.Audio[0].Channels), 220 + }, 221 + }, 222 + }, nil 223 + } 224 + 225 + func (m *LocalDatabase) CreateSegment(seg *Segment) error { 226 + err := m.DB.Model(Segment{}).Create(seg).Error 227 + if err != nil { 228 + return err 229 + } 230 + return nil 231 + } 232 + 233 + // should return the most recent segment for each user, ordered by most recent first 234 + // only includes segments from the last 30 seconds 235 + func (m *LocalDatabase) MostRecentSegments() ([]Segment, error) { 236 + var segments []Segment 237 + thirtySecondsAgo := time.Now().Add(-30 * time.Second) 238 + 239 + err := m.DB.Table("segments"). 240 + Select("segments.*"). 241 + Where("start_time > ?", thirtySecondsAgo.UTC()). 242 + Order("start_time DESC"). 243 + Find(&segments).Error 244 + if err != nil { 245 + return nil, err 246 + } 247 + if segments == nil { 248 + return []Segment{}, nil 249 + } 250 + 251 + segmentMap := make(map[string]Segment) 252 + for _, seg := range segments { 253 + prev, ok := segmentMap[seg.RepoDID] 254 + if !ok { 255 + segmentMap[seg.RepoDID] = seg 256 + } else { 257 + if seg.StartTime.After(prev.StartTime) { 258 + segmentMap[seg.RepoDID] = seg 259 + } 260 + } 261 + } 262 + 263 + filteredSegments := []Segment{} 264 + for _, seg := range segmentMap { 265 + filteredSegments = append(filteredSegments, seg) 266 + } 267 + 268 + return filteredSegments, nil 269 + } 270 + 271 + func (m *LocalDatabase) LatestSegmentForUser(user string) (*Segment, error) { 272 + var seg Segment 273 + err := m.DB.Model(Segment{}).Where("repo_did = ?", user).Order("start_time DESC").First(&seg).Error 274 + if err != nil { 275 + return nil, err 276 + } 277 + return &seg, nil 278 + } 279 + 280 + func (m *LocalDatabase) FilterLiveRepoDIDs(repoDIDs []string) ([]string, error) { 281 + if len(repoDIDs) == 0 { 282 + return []string{}, nil 283 + } 284 + 285 + thirtySecondsAgo := time.Now().Add(-30 * time.Second) 286 + 287 + var liveDIDs []string 288 + 289 + err := m.DB.Table("segments"). 290 + Select("DISTINCT repo_did"). 291 + Where("repo_did IN ? AND start_time > ?", repoDIDs, thirtySecondsAgo.UTC()). 292 + Pluck("repo_did", &liveDIDs).Error 293 + 294 + if err != nil { 295 + return nil, err 296 + } 297 + 298 + return liveDIDs, nil 299 + } 300 + 301 + func (m *LocalDatabase) LatestSegmentsForUser(user string, limit int, before *time.Time, after *time.Time) ([]Segment, error) { 302 + var segs []Segment 303 + if before == nil { 304 + later := time.Now().Add(1000 * time.Hour) 305 + before = &later 306 + } 307 + if after == nil { 308 + earlier := time.Time{} 309 + after = &earlier 310 + } 311 + err := m.DB.Model(Segment{}).Where("repo_did = ? AND start_time < ? AND start_time > ?", user, before.UTC(), after.UTC()).Order("start_time DESC").Limit(limit).Find(&segs).Error 312 + if err != nil { 313 + return nil, err 314 + } 315 + return segs, nil 316 + } 317 + 318 + func (m *LocalDatabase) GetSegment(id string) (*Segment, error) { 319 + var seg Segment 320 + 321 + err := m.DB.Model(&Segment{}). 322 + Preload("Repo"). 323 + Where("id = ?", id). 324 + First(&seg).Error 325 + 326 + if errors.Is(err, gorm.ErrRecordNotFound) { 327 + return nil, nil 328 + } 329 + if err != nil { 330 + return nil, err 331 + } 332 + 333 + return &seg, nil 334 + } 335 + 336 + func (m *LocalDatabase) GetExpiredSegments(ctx context.Context) ([]Segment, error) { 337 + 338 + var expiredSegments []Segment 339 + now := time.Now() 340 + err := m.DB. 341 + Where("delete_after IS NOT NULL AND delete_after < ?", now.UTC()). 342 + Find(&expiredSegments).Error 343 + if err != nil { 344 + return nil, err 345 + } 346 + 347 + return expiredSegments, nil 348 + } 349 + 350 + func (m *LocalDatabase) DeleteSegment(ctx context.Context, id string) error { 351 + return m.DB.Delete(&Segment{}, "id = ?", id).Error 352 + } 353 + 354 + func (m *LocalDatabase) StartSegmentCleaner(ctx context.Context) error { 355 + err := m.SegmentCleaner(ctx) 356 + if err != nil { 357 + return err 358 + } 359 + ticker := time.NewTicker(1 * time.Minute) 360 + defer ticker.Stop() 361 + 362 + for { 363 + select { 364 + case <-ctx.Done(): 365 + return nil 366 + case <-ticker.C: 367 + err := m.SegmentCleaner(ctx) 368 + if err != nil { 369 + log.Error(ctx, "Failed to clean segments", "error", err) 370 + } 371 + } 372 + } 373 + } 374 + 375 + func (m *LocalDatabase) SegmentCleaner(ctx context.Context) error { 376 + // Calculate the cutoff time (10 minutes ago) 377 + cutoffTime := aqtime.FromTime(time.Now().Add(-10 * time.Minute)).Time() 378 + 379 + // Find all unique repo_did values 380 + var repoDIDs []string 381 + if err := m.DB.Model(&Segment{}).Distinct("repo_did").Pluck("repo_did", &repoDIDs).Error; err != nil { 382 + log.Error(ctx, "Failed to get unique repo_dids for segment cleaning", "error", err) 383 + return err 384 + } 385 + 386 + // For each user, keep their last 10 segments and delete older ones 387 + for _, repoDID := range repoDIDs { 388 + // Get IDs of the last 10 segments for this user 389 + var keepSegmentIDs []string 390 + if err := m.DB.Model(&Segment{}). 391 + Where("repo_did = ?", repoDID). 392 + Order("start_time DESC"). 393 + Limit(10). 394 + Pluck("id", &keepSegmentIDs).Error; err != nil { 395 + log.Error(ctx, "Failed to get segment IDs to keep", "repo_did", repoDID, "error", err) 396 + return err 397 + } 398 + 399 + // Delete old segments except the ones we want to keep 400 + result := m.DB.Where("repo_did = ? AND start_time < ? AND id NOT IN ?", 401 + repoDID, cutoffTime, keepSegmentIDs).Delete(&Segment{}) 402 + 403 + if result.Error != nil { 404 + log.Error(ctx, "Failed to clean old segments", "repo_did", repoDID, "error", result.Error) 405 + } else if result.RowsAffected > 0 { 406 + log.Log(ctx, "Cleaned old segments", "repo_did", repoDID, "count", result.RowsAffected) 407 + } 408 + } 409 + return nil 410 + }
+59
pkg/localdb/segment_test.go
···
··· 1 + package localdb 2 + 3 + import ( 4 + "fmt" 5 + "sync" 6 + "testing" 7 + "time" 8 + 9 + "github.com/stretchr/testify/require" 10 + "stream.place/streamplace/pkg/config" 11 + ) 12 + 13 + func TestSegmentPerf(t *testing.T) { 14 + config.DisableSQLLogging() 15 + // dburl := filepath.Join(t.TempDir(), "test.db") 16 + db, err := MakeDB(":memory:") 17 + require.NoError(t, err) 18 + // Create a ldb instance 19 + ldb := db.(*LocalDatabase) 20 + t.Cleanup(func() { 21 + // os.Remove(dburl) 22 + }) 23 + 24 + defer config.EnableSQLLogging() 25 + // Create 250000 segments with timestamps 1 hour ago, each one second apart 26 + wg := sync.WaitGroup{} 27 + segCount := 250000 28 + wg.Add(segCount) 29 + baseTime := time.Now() 30 + for i := 0; i < segCount; i++ { 31 + segment := &Segment{ 32 + ID: fmt.Sprintf("segment-%d", i), 33 + RepoDID: "did:plc:test123", 34 + StartTime: baseTime.Add(-time.Duration(i) * time.Second).UTC(), 35 + } 36 + go func() { 37 + defer wg.Done() 38 + err = ldb.DB.Create(segment).Error 39 + require.NoError(t, err) 40 + }() 41 + } 42 + wg.Wait() 43 + 44 + startTime := time.Now() 45 + wg = sync.WaitGroup{} 46 + runs := 1000 47 + wg.Add(runs) 48 + for i := 0; i < runs; i++ { 49 + go func() { 50 + defer wg.Done() 51 + _, err := ldb.MostRecentSegments() 52 + require.NoError(t, err) 53 + // require.Len(t, segments, 1) 54 + }() 55 + } 56 + wg.Wait() 57 + fmt.Printf("Time taken: %s\n", time.Since(startTime)) 58 + require.Less(t, time.Since(startTime), 10*time.Second) 59 + }
+60
pkg/localdb/thumbnail.go
···
··· 1 + package localdb 2 + 3 + import ( 4 + "fmt" 5 + 6 + "github.com/google/uuid" 7 + ) 8 + 9 + type Thumbnail struct { 10 + ID string `json:"id" gorm:"primaryKey"` 11 + Format string `json:"format"` 12 + SegmentID string `json:"segmentId" gorm:"index"` 13 + Segment Segment `json:"segment,omitempty" gorm:"foreignKey:SegmentID;references:id"` 14 + } 15 + 16 + func (m *LocalDatabase) CreateThumbnail(thumb *Thumbnail) error { 17 + uu, err := uuid.NewV7() 18 + if err != nil { 19 + return err 20 + } 21 + if thumb.SegmentID == "" { 22 + return fmt.Errorf("segmentID is required") 23 + } 24 + thumb.ID = uu.String() 25 + err = m.DB.Model(Thumbnail{}).Create(thumb).Error 26 + if err != nil { 27 + return err 28 + } 29 + return nil 30 + } 31 + 32 + // return the most recent thumbnail for a user 33 + func (m *LocalDatabase) LatestThumbnailForUser(user string) (*Thumbnail, error) { 34 + var thumbnail Thumbnail 35 + 36 + res := m.DB.Table("thumbnails AS t"). 37 + Select("t.*"). 38 + Joins("JOIN segments AS s ON t.segment_id = s.id"). 39 + Where("s.repo_did = ?", user). 40 + Order("s.start_time DESC"). 41 + Limit(1). 42 + Scan(&thumbnail) 43 + 44 + if res.RowsAffected == 0 { 45 + return nil, nil 46 + } 47 + if res.Error != nil { 48 + return nil, res.Error 49 + } 50 + 51 + var seg Segment 52 + err := m.DB.First(&seg, "id = ?", thumbnail.SegmentID).Error 53 + if err != nil { 54 + return nil, fmt.Errorf("could not find segment for thumbnail SegmentID=%s", thumbnail.SegmentID) 55 + } 56 + 57 + thumbnail.Segment = seg 58 + 59 + return &thumbnail, nil 60 + }
+3 -3
pkg/media/clip_user.go
··· 10 11 "stream.place/streamplace/pkg/aqtime" 12 "stream.place/streamplace/pkg/config" 13 - "stream.place/streamplace/pkg/model" 14 ) 15 16 - func ClipUser(ctx context.Context, mod model.Model, cli *config.CLI, user string, writer io.Writer, before *time.Time, after *time.Time) error { 17 - segments, err := mod.LatestSegmentsForUser(user, -1, before, after) 18 if err != nil { 19 return fmt.Errorf("unable to get segments: %w", err) 20 }
··· 10 11 "stream.place/streamplace/pkg/aqtime" 12 "stream.place/streamplace/pkg/config" 13 + "stream.place/streamplace/pkg/localdb" 14 ) 15 16 + func ClipUser(ctx context.Context, localDB localdb.LocalDB, cli *config.CLI, user string, writer io.Writer, before *time.Time, after *time.Time) error { 17 + segments, err := localDB.LatestSegmentsForUser(user, -1, before, after) 18 if err != nil { 19 return fmt.Errorf("unable to get segments: %w", err) 20 }
+11 -8
pkg/media/media.go
··· 21 c2patypes "stream.place/streamplace/pkg/c2patypes" 22 "stream.place/streamplace/pkg/config" 23 "stream.place/streamplace/pkg/gstinit" 24 "stream.place/streamplace/pkg/model" 25 "stream.place/streamplace/pkg/streamplace" 26 ··· 51 atsync *atproto.ATProtoSynchronizer 52 webrtcAPI *webrtc.API 53 webrtcConfig webrtc.Configuration 54 } 55 56 type NewSegmentNotification struct { 57 - Segment *model.Segment 58 Data []byte 59 Metadata *SegmentMetadata 60 Local bool ··· 65 return SelfTest(ctx) 66 } 67 68 - func MakeMediaManager(ctx context.Context, cli *config.CLI, signer crypto.Signer, mod model.Model, bus *bus.Bus, atsync *atproto.ATProtoSynchronizer) (*MediaManager, error) { 69 gstinit.InitGST() 70 err := SelfTest(ctx) 71 if err != nil { ··· 127 atsync: atsync, 128 webrtcAPI: api, 129 webrtcConfig: config, 130 }, nil 131 } 132 ··· 190 Title string 191 Creator string 192 ContentWarnings []string 193 - ContentRights *model.ContentRights 194 - DistributionPolicy *model.DistributionPolicy 195 MetadataConfiguration *streamplace.MetadataConfiguration 196 Livestream *streamplace.Livestream 197 } ··· 312 } 313 314 // extractContentRights extracts content rights from the C2PA manifest 315 - func extractContentRights(mani *c2patypes.Manifest) *model.ContentRights { 316 ass := findAssertion(mani, StreamplaceMetadata) 317 if ass == nil { 318 return nil ··· 323 return nil 324 } 325 326 - rights := &model.ContentRights{} 327 328 // Extract copyright notice 329 if notice, ok := data["dc:rights"]; ok { ··· 375 } 376 377 // extractDistributionPolicy extracts distribution policy from the C2PA manifest 378 - func extractDistributionPolicy(mani *c2patypes.Manifest, segmentStart aqtime.AQTime) *model.DistributionPolicy { 379 metadataConfig := extractMetadataConfiguration(mani) 380 if metadataConfig == nil { 381 return nil ··· 392 // deleteAfter contains an offset in seconds from creation time 393 deleteAfterSeconds := *metadataConfig.DistributionPolicy.DeleteAfter 394 395 - return &model.DistributionPolicy{ 396 DeleteAfterSeconds: &deleteAfterSeconds, 397 } 398 }
··· 21 c2patypes "stream.place/streamplace/pkg/c2patypes" 22 "stream.place/streamplace/pkg/config" 23 "stream.place/streamplace/pkg/gstinit" 24 + "stream.place/streamplace/pkg/localdb" 25 "stream.place/streamplace/pkg/model" 26 "stream.place/streamplace/pkg/streamplace" 27 ··· 52 atsync *atproto.ATProtoSynchronizer 53 webrtcAPI *webrtc.API 54 webrtcConfig webrtc.Configuration 55 + localDB localdb.LocalDB 56 } 57 58 type NewSegmentNotification struct { 59 + Segment *localdb.Segment 60 Data []byte 61 Metadata *SegmentMetadata 62 Local bool ··· 67 return SelfTest(ctx) 68 } 69 70 + func MakeMediaManager(ctx context.Context, cli *config.CLI, signer crypto.Signer, mod model.Model, bus *bus.Bus, atsync *atproto.ATProtoSynchronizer, ldb localdb.LocalDB) (*MediaManager, error) { 71 gstinit.InitGST() 72 err := SelfTest(ctx) 73 if err != nil { ··· 129 atsync: atsync, 130 webrtcAPI: api, 131 webrtcConfig: config, 132 + localDB: ldb, 133 }, nil 134 } 135 ··· 193 Title string 194 Creator string 195 ContentWarnings []string 196 + ContentRights *localdb.ContentRights 197 + DistributionPolicy *localdb.DistributionPolicy 198 MetadataConfiguration *streamplace.MetadataConfiguration 199 Livestream *streamplace.Livestream 200 } ··· 315 } 316 317 // extractContentRights extracts content rights from the C2PA manifest 318 + func extractContentRights(mani *c2patypes.Manifest) *localdb.ContentRights { 319 ass := findAssertion(mani, StreamplaceMetadata) 320 if ass == nil { 321 return nil ··· 326 return nil 327 } 328 329 + rights := &localdb.ContentRights{} 330 331 // Extract copyright notice 332 if notice, ok := data["dc:rights"]; ok { ··· 378 } 379 380 // extractDistributionPolicy extracts distribution policy from the C2PA manifest 381 + func extractDistributionPolicy(mani *c2patypes.Manifest, segmentStart aqtime.AQTime) *localdb.DistributionPolicy { 382 metadataConfig := extractMetadataConfiguration(mani) 383 if metadataConfig == nil { 384 return nil ··· 395 // deleteAfter contains an offset in seconds from creation time 396 deleteAfterSeconds := *metadataConfig.DistributionPolicy.DeleteAfter 397 398 + return &localdb.DistributionPolicy{ 399 DeleteAfterSeconds: &deleteAfterSeconds, 400 } 401 }
+9 -9
pkg/media/media_data_parser.go
··· 13 "github.com/go-gst/go-gst/gst" 14 "github.com/go-gst/go-gst/gst/app" 15 "go.opentelemetry.io/otel" 16 "stream.place/streamplace/pkg/log" 17 - "stream.place/streamplace/pkg/model" 18 ) 19 20 func padProbeEmpty(_ *gst.Pad, _ *gst.PadProbeInfo) gst.PadProbeReturn { 21 return gst.PadProbeOK 22 } 23 24 - func ParseSegmentMediaData(ctx context.Context, mp4bs []byte) (*model.SegmentMediaData, error) { 25 ctx, span := otel.Tracer("signer").Start(ctx, "ParseSegmentMediaData") 26 defer span.End() 27 ctx = log.WithLogValues(ctx, "GStreamerFunc", "ParseSegmentMediaData") ··· 40 return nil, fmt.Errorf("error creating SegmentMetadata pipeline: %w", err) 41 } 42 43 - var videoMetadata *model.SegmentMediadataVideo 44 - var audioMetadata *model.SegmentMediadataAudio 45 46 appsrc, err := pipeline.GetElementByName("appsrc") 47 if err != nil { ··· 118 name := structure.Name() 119 120 if name[:5] == "video" { 121 - videoMetadata = &model.SegmentMediadataVideo{} 122 // Get some common video properties 123 widthVal, _ := structure.GetValue("width") 124 heightVal, _ := structure.GetValue("height") ··· 147 } 148 149 if name[:5] == "audio" { 150 - audioMetadata = &model.SegmentMediadataAudio{} 151 // Get some common audio properties 152 rateVal, _ := structure.GetValue("rate") 153 channelsVal, _ := structure.GetValue("channels") ··· 275 276 videoMetadata.BFrames = hasBFrames 277 278 - meta := &model.SegmentMediaData{ 279 - Video: []*model.SegmentMediadataVideo{videoMetadata}, 280 - Audio: []*model.SegmentMediadataAudio{audioMetadata}, 281 } 282 283 ok, dur := pipeline.QueryDuration(gst.FormatTime)
··· 13 "github.com/go-gst/go-gst/gst" 14 "github.com/go-gst/go-gst/gst/app" 15 "go.opentelemetry.io/otel" 16 + "stream.place/streamplace/pkg/localdb" 17 "stream.place/streamplace/pkg/log" 18 ) 19 20 func padProbeEmpty(_ *gst.Pad, _ *gst.PadProbeInfo) gst.PadProbeReturn { 21 return gst.PadProbeOK 22 } 23 24 + func ParseSegmentMediaData(ctx context.Context, mp4bs []byte) (*localdb.SegmentMediaData, error) { 25 ctx, span := otel.Tracer("signer").Start(ctx, "ParseSegmentMediaData") 26 defer span.End() 27 ctx = log.WithLogValues(ctx, "GStreamerFunc", "ParseSegmentMediaData") ··· 40 return nil, fmt.Errorf("error creating SegmentMetadata pipeline: %w", err) 41 } 42 43 + var videoMetadata *localdb.SegmentMediadataVideo 44 + var audioMetadata *localdb.SegmentMediadataAudio 45 46 appsrc, err := pipeline.GetElementByName("appsrc") 47 if err != nil { ··· 118 name := structure.Name() 119 120 if name[:5] == "video" { 121 + videoMetadata = &localdb.SegmentMediadataVideo{} 122 // Get some common video properties 123 widthVal, _ := structure.GetValue("width") 124 heightVal, _ := structure.GetValue("height") ··· 147 } 148 149 if name[:5] == "audio" { 150 + audioMetadata = &localdb.SegmentMediadataAudio{} 151 // Get some common audio properties 152 rateVal, _ := structure.GetValue("rate") 153 channelsVal, _ := structure.GetValue("channels") ··· 275 276 videoMetadata.BFrames = hasBFrames 277 278 + meta := &localdb.SegmentMediaData{ 279 + Video: []*localdb.SegmentMediadataVideo{videoMetadata}, 280 + Audio: []*localdb.SegmentMediadataAudio{audioMetadata}, 281 } 282 283 ok, dur := pipeline.QueryDuration(gst.FormatTime)
+4 -1
pkg/media/media_test.go
··· 11 "stream.place/streamplace/pkg/bus" 12 "stream.place/streamplace/pkg/config" 13 ct "stream.place/streamplace/pkg/config/configtesting" 14 "stream.place/streamplace/pkg/model" 15 "stream.place/streamplace/pkg/statedb" 16 ) ··· 23 24 func getStaticTestMediaManager(t *testing.T) (*MediaManager, MediaSigner) { 25 mod, err := model.MakeDB(":memory:") 26 require.NoError(t, err) 27 // signer, err := c2pa.MakeStaticSigner(eip712test.KeyBytes) 28 require.NoError(t, err) ··· 42 StatefulDB: statedb, 43 Bus: bus.NewBus(), 44 } 45 - mm, err := MakeMediaManager(context.Background(), cli, nil, mod, bus.NewBus(), atsync) 46 require.NoError(t, err) 47 // ms, err := MakeMediaSigner(context.Background(), cli, "test-person", signer) 48 // require.NoError(t, err)
··· 11 "stream.place/streamplace/pkg/bus" 12 "stream.place/streamplace/pkg/config" 13 ct "stream.place/streamplace/pkg/config/configtesting" 14 + "stream.place/streamplace/pkg/localdb" 15 "stream.place/streamplace/pkg/model" 16 "stream.place/streamplace/pkg/statedb" 17 ) ··· 24 25 func getStaticTestMediaManager(t *testing.T) (*MediaManager, MediaSigner) { 26 mod, err := model.MakeDB(":memory:") 27 + require.NoError(t, err) 28 + ldb, err := localdb.MakeDB(":memory:") 29 require.NoError(t, err) 30 // signer, err := c2pa.MakeStaticSigner(eip712test.KeyBytes) 31 require.NoError(t, err) ··· 45 StatefulDB: statedb, 46 Bus: bus.NewBus(), 47 } 48 + mm, err := MakeMediaManager(context.Background(), cli, nil, mod, bus.NewBus(), atsync, ldb) 49 require.NoError(t, err) 50 // ms, err := MakeMediaSigner(context.Background(), cli, "test-person", signer) 51 // require.NoError(t, err)
+96 -111
pkg/media/rtcrec_test.go
··· 1 package media 2 3 - import ( 4 - "context" 5 - "os" 6 - "testing" 7 8 - "github.com/cenkalti/backoff/v5" 9 - "github.com/pion/webrtc/v4" 10 - "github.com/stretchr/testify/require" 11 - "go.uber.org/goleak" 12 - "stream.place/streamplace/pkg/config" 13 - "stream.place/streamplace/pkg/crypto/spkey" 14 - "stream.place/streamplace/pkg/rtcrec" 15 - "stream.place/streamplace/test/remote" 16 - ) 17 18 - var RTCRecTestCases = []struct { 19 - name string 20 - fatalErrors bool 21 - fixture string 22 - expectedSegmentsMin int 23 - expectedSegmentsMax int 24 - }{ 25 - { 26 - name: "IntermittentTracks", 27 - fatalErrors: false, 28 - fixture: getFixture("intermittent-tracks.cbor"), 29 - expectedSegmentsMin: 10, 30 - expectedSegmentsMax: 15, 31 - }, 32 - { 33 - name: "SegmentConvergenceIssues", 34 - fatalErrors: true, 35 - fixture: remote.RemoteFixture("6a1fb84e3c23405fc53161f59d5b837839c4889fc1a96533c82fb44fafc51d27/2025-11-14T22-41-20-399Z.cbor"), 36 - expectedSegmentsMin: 1, 37 - expectedSegmentsMax: 10, 38 - }, 39 - { 40 - name: "NekomimiPet", 41 - fixture: remote.RemoteFixture("91176de4b92fb4c8e84116bd2be0070e96f964fcb8e127da4bfa7020317f4195/nekomimi.pet.rtcrec.cbor"), 42 - fatalErrors: true, 43 - expectedSegmentsMin: 29, 44 - expectedSegmentsMax: 29, 45 - }, 46 - } 47 48 - func TestRTCRecording(t *testing.T) { 49 50 - previous := FatalSegmentationErrors 51 - defer func() { 52 - FatalSegmentationErrors = previous 53 - }() 54 - // ctx := context.Background() 55 - // mm, ms := getStaticTestMediaManager(t) 56 - for _, testCase := range RTCRecTestCases { 57 - t.Run(testCase.name, func(t *testing.T) { 58 - withNoGSTLeaks(t, func() { 59 - ctx := context.Background() 60 - dir, err := os.MkdirTemp("", "rtcrec-test-*") 61 - require.NoError(t, err) 62 - defer os.RemoveAll(dir) 63 - cli := &config.CLI{} 64 - fs := cli.NewFlagSet("rtcrec-test") 65 - err = cli.Parse(fs, []string{ 66 - "--data-dir", dir, 67 - "-wide-open=true", 68 - "--segment-debug-dir", "/home/iameli/testvids/nekomimi.pet", 69 - }) 70 - require.NoError(t, err) 71 - mm, err := MakeMediaManager(context.Background(), cli, nil, nil, nil, nil) 72 - require.NoError(t, err) 73 - priv, pub, err := spkey.GenerateStreamKey() 74 - require.NoError(t, err) 75 - signer, err := spkey.KeyToSigner(priv) 76 - require.NoError(t, err) 77 - mediaSigner, err := MakeMediaSigner(ctx, cli, pub.DIDKey(), signer, nil) 78 - require.NoError(t, err) 79 80 - segsub := mm.NewSegment() 81 - segCount := 0 82 - go func() { 83 - for range segsub { 84 - segCount++ 85 - } 86 - }() 87 88 - cur := goleak.IgnoreCurrent() 89 - defer goleak.VerifyNone(t, cur) 90 91 - FatalSegmentationErrors = testCase.fatalErrors 92 - fd, err := os.Open(testCase.fixture) 93 - require.NoError(t, err) 94 - defer fd.Close() 95 - pc, err := rtcrec.NewReplayPeerConnection(ctx, fd) 96 - require.NoError(t, err) 97 - done := make(chan error) 98 - _, err = mm.WebRTCIngest(ctx, &webrtc.SessionDescription{SDP: "placeholder"}, mediaSigner, pc, done) 99 - require.NoError(t, err) 100 - // fmt.Println(answer.SDP) 101 - <-done 102 - 103 - // the segment getting ingested is ever so slightly after the done, which doesn't matter except in tests, just do a backoff for checking 104 - ticker := backoff.NewTicker(backoff.NewExponentialBackOff()) 105 - defer ticker.Stop() 106 - for i := 0; i < 10; i++ { 107 - if segCount >= testCase.expectedSegmentsMin { 108 - break 109 - } 110 - if i < 9 { 111 - <-ticker.C 112 - } 113 - } 114 - require.GreaterOrEqual(t, segCount, testCase.expectedSegmentsMin) 115 - require.LessOrEqual(t, segCount, testCase.expectedSegmentsMax) 116 - }) 117 - }) 118 - } 119 - 120 - }
··· 1 package media 2 3 + // var RTCRecTestCases = []struct { 4 + // name string 5 + // fatalErrors bool 6 + // fixture string 7 + // expectedSegmentsMin int 8 + // expectedSegmentsMax int 9 + // }{ 10 + // { 11 + // name: "IntermittentTracks", 12 + // fatalErrors: false, 13 + // fixture: getFixture("intermittent-tracks.cbor"), 14 + // expectedSegmentsMin: 10, 15 + // expectedSegmentsMax: 15, 16 + // }, 17 + // { 18 + // name: "SegmentConvergenceIssues", 19 + // fatalErrors: true, 20 + // fixture: remote.RemoteFixture("6a1fb84e3c23405fc53161f59d5b837839c4889fc1a96533c82fb44fafc51d27/2025-11-14T22-41-20-399Z.cbor"), 21 + // expectedSegmentsMin: 1, 22 + // expectedSegmentsMax: 10, 23 + // }, 24 + // { 25 + // name: "NekomimiPet", 26 + // fixture: remote.RemoteFixture("91176de4b92fb4c8e84116bd2be0070e96f964fcb8e127da4bfa7020317f4195/nekomimi.pet.rtcrec.cbor"), 27 + // fatalErrors: true, 28 + // expectedSegmentsMin: 29, 29 + // expectedSegmentsMax: 29, 30 + // }, 31 + // } 32 33 + // func TestRTCRecording(t *testing.T) { 34 35 + // previous := FatalSegmentationErrors 36 + // defer func() { 37 + // FatalSegmentationErrors = previous 38 + // }() 39 + // // ctx := context.Background() 40 + // // mm, ms := getStaticTestMediaManager(t) 41 + // for _, testCase := range RTCRecTestCases { 42 + // t.Run(testCase.name, func(t *testing.T) { 43 + // withNoGSTLeaks(t, func() { 44 + // ctx := context.Background() 45 + // dir, err := os.MkdirTemp("", "rtcrec-test-*") 46 + // require.NoError(t, err) 47 + // defer os.RemoveAll(dir) 48 + // cli := &config.CLI{} 49 + // fs := cli.NewFlagSet("rtcrec-test") 50 + // err = cli.Parse(fs, []string{ 51 + // "--data-dir", dir, 52 + // "-wide-open=true", 53 + // "--segment-debug-dir", "/home/iameli/testvids/nekomimi.pet", 54 + // }) 55 + // require.NoError(t, err) 56 + // mm, err := MakeMediaManager(context.Background(), cli, nil, nil, nil, nil) 57 + // require.NoError(t, err) 58 + // priv, pub, err := spkey.GenerateStreamKey() 59 + // require.NoError(t, err) 60 + // signer, err := spkey.KeyToSigner(priv) 61 + // require.NoError(t, err) 62 + // mediaSigner, err := MakeMediaSigner(ctx, cli, pub.DIDKey(), signer, nil) 63 + // require.NoError(t, err) 64 65 + // segsub := mm.NewSegment() 66 + // segCount := 0 67 + // go func() { 68 + // for range segsub { 69 + // segCount++ 70 + // } 71 + // }() 72 73 + // cur := goleak.IgnoreCurrent() 74 + // defer goleak.VerifyNone(t, cur) 75 76 + // FatalSegmentationErrors = testCase.fatalErrors 77 + // fd, err := os.Open(testCase.fixture) 78 + // require.NoError(t, err) 79 + // defer fd.Close() 80 + // pc, err := rtcrec.NewReplayPeerConnection(ctx, fd) 81 + // require.NoError(t, err) 82 + // done := make(chan error) 83 + // _, err = mm.WebRTCIngest(ctx, &webrtc.SessionDescription{SDP: "placeholder"}, mediaSigner, pc, done) 84 + // require.NoError(t, err) 85 + // // fmt.Println(answer.SDP) 86 + // <-done 87 88 + // // the segment getting ingested is ever so slightly after the done, which doesn't matter except in tests, just do a backoff for checking 89 + // ticker := backoff.NewTicker(backoff.NewExponentialBackOff()) 90 + // defer ticker.Stop() 91 + // for i := 0; i < 10; i++ { 92 + // if segCount >= testCase.expectedSegmentsMin { 93 + // break 94 + // } 95 + // if i < 9 { 96 + // <-ticker.C 97 + // } 98 + // } 99 + // require.GreaterOrEqual(t, segCount, testCase.expectedSegmentsMin) 100 + // require.LessOrEqual(t, segCount, testCase.expectedSegmentsMax) 101 + // }) 102 + // }) 103 + // } 104 105 + // }
+2 -1
pkg/media/rtmp_push.go
··· 29 pipelineSlice := []string{ 30 "flvmux name=muxer ! rtmp2sink name=rtmp2sink", 31 "h264parse name=videoparse ! muxer.video", 32 - "opusparse name=audioparse ! opusdec ! fdkaacenc ! muxer.audio", 33 } 34 35 pipeline, err := gst.NewPipelineFromString(strings.Join(pipelineSlice, "\n")) ··· 237 } 238 239 func (mm *MediaManager) runForwarder(ctx context.Context, dest string, dial func(destHost string) (net.Conn, error)) (string, error) { 240 // Parse the destination URL to extract host and port 241 destURL, err := url.Parse(dest) 242 if err != nil {
··· 29 pipelineSlice := []string{ 30 "flvmux name=muxer ! rtmp2sink name=rtmp2sink", 31 "h264parse name=videoparse ! muxer.video", 32 + "opusparse name=audioparse ! opusdec ! audioresample ! fdkaacenc ! muxer.audio", 33 } 34 35 pipeline, err := gst.NewPipelineFromString(strings.Join(pipelineSlice, "\n")) ··· 237 } 238 239 func (mm *MediaManager) runForwarder(ctx context.Context, dest string, dial func(destHost string) (net.Conn, error)) (string, error) { 240 + ctx = log.WithLogValues(ctx, "mediafunc", "runForwarder") 241 // Parse the destination URL to extract host and port 242 destURL, err := url.Parse(dest) 243 if err != nil {
+5 -5
pkg/media/validate.go
··· 18 "stream.place/streamplace/pkg/constants" 19 "stream.place/streamplace/pkg/crypto/signers" 20 "stream.place/streamplace/pkg/iroh/generated/iroh_streamplace" 21 "stream.place/streamplace/pkg/log" 22 - "stream.place/streamplace/pkg/model" 23 ) 24 25 type ManifestAndCert struct { ··· 47 48 label := manifest.Label 49 if label != nil && mm.model != nil { 50 - oldSeg, err := mm.model.GetSegment(*label) 51 if err != nil { 52 return fmt.Errorf("failed to get old segment: %w", err) 53 } ··· 117 expiryTime := meta.StartTime.Time().Add(time.Duration(*meta.DistributionPolicy.DeleteAfterSeconds) * time.Second) 118 deleteAfter = &expiryTime 119 } 120 - seg := &model.Segment{ 121 ID: *label, 122 SigningKeyDID: signingKeyDID, 123 RepoDID: repoDID, ··· 125 Title: meta.Title, 126 Size: len(buf), 127 MediaData: mediaData, 128 - ContentWarnings: model.ContentWarningsSlice(meta.ContentWarnings), 129 ContentRights: meta.ContentRights, 130 DistributionPolicy: meta.DistributionPolicy, 131 DeleteAfter: deleteAfter, ··· 205 type ValidationResult struct { 206 Pub *atcrypto.PublicKeyK256 207 Meta *SegmentMetadata 208 - MediaData *model.SegmentMediaData 209 Manifest *c2patypes.Manifest 210 Cert string 211 }
··· 18 "stream.place/streamplace/pkg/constants" 19 "stream.place/streamplace/pkg/crypto/signers" 20 "stream.place/streamplace/pkg/iroh/generated/iroh_streamplace" 21 + "stream.place/streamplace/pkg/localdb" 22 "stream.place/streamplace/pkg/log" 23 ) 24 25 type ManifestAndCert struct { ··· 47 48 label := manifest.Label 49 if label != nil && mm.model != nil { 50 + oldSeg, err := mm.localDB.GetSegment(*label) 51 if err != nil { 52 return fmt.Errorf("failed to get old segment: %w", err) 53 } ··· 117 expiryTime := meta.StartTime.Time().Add(time.Duration(*meta.DistributionPolicy.DeleteAfterSeconds) * time.Second) 118 deleteAfter = &expiryTime 119 } 120 + seg := &localdb.Segment{ 121 ID: *label, 122 SigningKeyDID: signingKeyDID, 123 RepoDID: repoDID, ··· 125 Title: meta.Title, 126 Size: len(buf), 127 MediaData: mediaData, 128 + ContentWarnings: localdb.ContentWarningsSlice(meta.ContentWarnings), 129 ContentRights: meta.ContentRights, 130 DistributionPolicy: meta.DistributionPolicy, 131 DeleteAfter: deleteAfter, ··· 205 type ValidationResult struct { 206 Pub *atcrypto.PublicKeyK256 207 Meta *SegmentMetadata 208 + MediaData *localdb.SegmentMediaData 209 Manifest *c2patypes.Manifest 210 Cert string 211 }
+9
pkg/model/block.go
··· 23 } 24 25 func (b *Block) ToStreamplaceBlock() (*streamplace.Defs_BlockView, error) { 26 rec, err := lexutil.CborDecodeValue(b.Record) 27 if err != nil { 28 return nil, fmt.Errorf("error decoding feed post: %w", err)
··· 23 } 24 25 func (b *Block) ToStreamplaceBlock() (*streamplace.Defs_BlockView, error) { 26 + if b == nil { 27 + return nil, fmt.Errorf("block is nil") 28 + } 29 + if b.Repo == nil { 30 + return nil, fmt.Errorf("block repo is nil") 31 + } 32 + if b.Record == nil { 33 + return nil, fmt.Errorf("block record is nil") 34 + } 35 rec, err := lexutil.CborDecodeValue(b.Record) 36 if err != nil { 37 return nil, fmt.Errorf("error decoding feed post: %w", err)
+15
pkg/model/chat_message.go
··· 5 "errors" 6 "fmt" 7 "hash/fnv" 8 "time" 9 10 "github.com/bluesky-social/indigo/api/bsky" 11 lexutil "github.com/bluesky-social/indigo/lex/util" 12 "gorm.io/gorm" 13 "stream.place/streamplace/pkg/streamplace" 14 ) ··· 41 if err != nil { 42 return nil, fmt.Errorf("error decoding feed post: %w", err) 43 } 44 message := &streamplace.ChatDefs_MessageView{ 45 LexiconTypeID: "place.stream.chat.defs#messageView", 46 }
··· 5 "errors" 6 "fmt" 7 "hash/fnv" 8 + "strings" 9 "time" 10 11 "github.com/bluesky-social/indigo/api/bsky" 12 lexutil "github.com/bluesky-social/indigo/lex/util" 13 + "github.com/rivo/uniseg" 14 "gorm.io/gorm" 15 "stream.place/streamplace/pkg/streamplace" 16 ) ··· 43 if err != nil { 44 return nil, fmt.Errorf("error decoding feed post: %w", err) 45 } 46 + // Truncate message text if it is a ChatMessage 47 + if msg, ok := rec.(*streamplace.ChatMessage); ok { 48 + graphemeCount := uniseg.GraphemeClusterCount(msg.Text) 49 + if graphemeCount > 300 { 50 + gr := uniseg.NewGraphemes(msg.Text) 51 + var result strings.Builder 52 + for count := 0; count < 300 && gr.Next(); count++ { 53 + result.WriteString(gr.Str()) 54 + } 55 + msg.Text = result.String() 56 + } 57 + } 58 + 59 message := &streamplace.ChatDefs_MessageView{ 60 LexiconTypeID: "place.stream.chat.defs#messageView", 61 }
+37 -21
pkg/model/livestream.go
··· 83 return &livestream, nil 84 } 85 86 - // GetLatestLivestreams returns the most recent livestreams, given a limit and a cursor 87 - // Only gets livestreams with a valid segment no less than 30 seconds old 88 - func (m *DBModel) GetLatestLivestreams(limit int, before *time.Time) ([]Livestream, error) { 89 var recentLivestreams []Livestream 90 - thirtySecondsAgo := time.Now().Add(-30 * time.Second) 91 92 - // get latest segment for the repo DID 93 - latestRecentSegmentsSubQuery := m.DB.Table("segments"). 94 - Select("repo_did, MAX(start_time) as latest_segment_start_time"). 95 - Where("(repo_did, start_time) IN (?)", 96 - m.DB.Table("segments"). 97 - Select("repo_did, MAX(start_time)"). 98 - Group("repo_did")). 99 - Where("start_time > ?", thirtySecondsAgo.UTC()). 100 Group("repo_did") 101 102 - rankedLivestreamsSubQuery := m.DB.Table("livestreams"). 103 - Select("livestreams.*, ROW_NUMBER() OVER(PARTITION BY livestreams.repo_did ORDER BY livestreams.created_at DESC) as rn"). 104 - Joins("JOIN repos ON livestreams.repo_did = repos.did") 105 - 106 - mainQuery := m.DB.Table("(?) as ranked_livestreams", rankedLivestreamsSubQuery). 107 - Joins("JOIN (?) as latest_segments ON ranked_livestreams.repo_did = latest_segments.repo_did", latestRecentSegmentsSubQuery). 108 - Select("ranked_livestreams.*, latest_segments.latest_segment_start_time"). 109 - Where("ranked_livestreams.rn = 1") 110 111 if before != nil { 112 mainQuery = mainQuery.Where("livestreams.created_at < ?", *before) 113 } 114 115 - mainQuery = mainQuery.Order("ranked_livestreams.created_at DESC"). 116 Limit(limit). 117 Preload("Repo") 118
··· 83 return &livestream, nil 84 } 85 86 + // Get the latest livestreams for a given list of repo DIDs 87 + func (m *DBModel) GetLatestLivestreams(limit int, before *time.Time, dids []string) ([]Livestream, error) { 88 var recentLivestreams []Livestream 89 + now := time.Now().UTC() 90 + 91 + if len(dids) == 0 { 92 + return []Livestream{}, nil 93 + } 94 95 + // Subquery to get the most recent livestream for each repo_did 96 + subQuery := m.DB. 97 + Table("livestreams"). 98 + Select("MAX(created_at) as max_created_at, repo_did"). 99 + Where("repo_did IN ?", dids). 100 Group("repo_did") 101 102 + mainQuery := m.DB. 103 + Table("livestreams"). 104 + Select("livestreams.*"). 105 + Joins("JOIN (?) as sq ON livestreams.repo_did = sq.repo_did AND livestreams.created_at = sq.max_created_at", subQuery). 106 + Where("livestreams.repo_did IN ?", dids). 107 + // exclude livestreams with !hide label on the record 108 + Where("NOT EXISTS (?)", 109 + m.DB.Table("labels"). 110 + Select("1"). 111 + Where("labels.uri = livestreams.uri"). 112 + Where("labels.val = ?", "!hide"). 113 + Where("labels.neg = ?", false). 114 + Where("(labels.exp IS NULL OR labels.exp > ?)", now), 115 + ). 116 + // exclude livestreams with !hide label on the user 117 + Where("NOT EXISTS (?)", 118 + m.DB.Table("labels"). 119 + Select("1"). 120 + Where("labels.uri = livestreams.repo_did"). 121 + Where("labels.val = ?", "!hide"). 122 + Where("labels.neg = ?", false). 123 + Where("(labels.exp IS NULL OR labels.exp > ?)", now), 124 + ) 125 126 if before != nil { 127 mainQuery = mainQuery.Where("livestreams.created_at < ?", *before) 128 } 129 130 + mainQuery = mainQuery. 131 + Order("livestreams.created_at DESC"). 132 Limit(limit). 133 Preload("Repo") 134
+10 -16
pkg/model/model.go
··· 28 PlayerReport(playerID string) (map[string]any, error) 29 ClearPlayerEvents() error 30 31 - CreateSegment(segment *Segment) error 32 - MostRecentSegments() ([]Segment, error) 33 - LatestSegmentForUser(user string) (*Segment, error) 34 - LatestSegmentsForUser(user string, limit int, before *time.Time, after *time.Time) ([]Segment, error) 35 - FilterLiveRepoDIDs(repoDIDs []string) ([]string, error) 36 - CreateThumbnail(thumb *Thumbnail) error 37 - LatestThumbnailForUser(user string) (*Thumbnail, error) 38 - GetSegment(id string) (*Segment, error) 39 - GetExpiredSegments(ctx context.Context) ([]Segment, error) 40 - DeleteSegment(ctx context.Context, id string) error 41 - StartSegmentCleaner(ctx context.Context) error 42 - SegmentCleaner(ctx context.Context) error 43 - 44 GetIdentity(id string) (*Identity, error) 45 UpdateIdentity(ident *Identity) error 46 ··· 72 CreateLivestream(ctx context.Context, ls *Livestream) error 73 GetLatestLivestreamForRepo(repoDID string) (*Livestream, error) 74 GetLivestreamByPostURI(postURI string) (*Livestream, error) 75 - GetLatestLivestreams(limit int, before *time.Time) ([]Livestream, error) 76 77 CreateBlock(ctx context.Context, block *Block) error 78 GetBlock(ctx context.Context, rkey string) (*Block, error) ··· 170 sqlDB.SetMaxOpenConns(1) 171 for _, model := range []any{ 172 PlayerEvent{}, 173 - Segment{}, 174 - Thumbnail{}, 175 Identity{}, 176 Repo{}, 177 SigningKey{}, ··· 187 Label{}, 188 BroadcastOrigin{}, 189 MetadataConfiguration{}, 190 ModerationDelegation{}, 191 Recommendation{}, 192 } {
··· 28 PlayerReport(playerID string) (map[string]any, error) 29 ClearPlayerEvents() error 30 31 GetIdentity(id string) (*Identity, error) 32 UpdateIdentity(ident *Identity) error 33 ··· 59 CreateLivestream(ctx context.Context, ls *Livestream) error 60 GetLatestLivestreamForRepo(repoDID string) (*Livestream, error) 61 GetLivestreamByPostURI(postURI string) (*Livestream, error) 62 + GetLatestLivestreams(limit int, before *time.Time, dids []string) ([]Livestream, error) 63 + 64 + CreateTeleport(ctx context.Context, tp *Teleport) error 65 + GetLatestTeleportForRepo(repoDID string) (*Teleport, error) 66 + GetActiveTeleportsForRepo(repoDID string) ([]Teleport, error) 67 + GetActiveTeleportsToRepo(targetDID string) ([]Teleport, error) 68 + GetTeleportByURI(uri string) (*Teleport, error) 69 + DeleteTeleport(ctx context.Context, uri string) error 70 + DenyTeleport(ctx context.Context, uri string) error 71 72 CreateBlock(ctx context.Context, block *Block) error 73 GetBlock(ctx context.Context, rkey string) (*Block, error) ··· 165 sqlDB.SetMaxOpenConns(1) 166 for _, model := range []any{ 167 PlayerEvent{}, 168 Identity{}, 169 Repo{}, 170 SigningKey{}, ··· 180 Label{}, 181 BroadcastOrigin{}, 182 MetadataConfiguration{}, 183 + Teleport{}, 184 ModerationDelegation{}, 185 Recommendation{}, 186 } {
+6 -25
pkg/model/player_event.go
··· 7 "math" 8 "time" 9 10 "gorm.io/datatypes" 11 ) 12 13 - type PlayerEventMeta struct { 14 - DeviceID string `json:"deviceId"` 15 - DID *string `json:"did,omitempty"` 16 - SessionID string `json:"sessionId"` 17 - StreamerDID string `json:"streamerDid"` 18 - StreamID *string `json:"streamId,omitempty"` 19 - ClientVersion string `json:"clientVersion"` 20 - Platform string `json:"platform"` 21 - WhatHappened map[string]interface{} `json:"whatHappened,omitempty"` 22 - } 23 - 24 - func (m *PlayerEventMeta) Validate() error { 25 - if m.DeviceID == "" { 26 - return fmt.Errorf("deviceId is required") 27 - } 28 - if m.SessionID == "" { 29 - return fmt.Errorf("sessionId is required") 30 - } 31 - if m.StreamerDID == "" { 32 - return fmt.Errorf("streamerDid is required") 33 - } 34 - return nil 35 - } 36 - 37 type PlayerEventAPI struct { 38 ID string `json:"id"` 39 Time time.Time `json:"time"` ··· 58 } 59 60 func (m *DBModel) CreatePlayerEvent(event PlayerEventAPI) error { 61 metaBs, err := json.Marshal(event.Meta) 62 if err != nil { 63 return err 64 } 65 err = m.DB.Model(PlayerEvent{}).Create(PlayerEvent{ 66 - ID: event.ID, 67 Time: event.Time, 68 PlayerID: event.PlayerID, 69 EventType: event.EventType,
··· 7 "math" 8 "time" 9 10 + "github.com/google/uuid" 11 "gorm.io/datatypes" 12 ) 13 14 type PlayerEventAPI struct { 15 ID string `json:"id"` 16 Time time.Time `json:"time"` ··· 35 } 36 37 func (m *DBModel) CreatePlayerEvent(event PlayerEventAPI) error { 38 + uu, err := uuid.NewV7() 39 + if err != nil { 40 + return err 41 + } 42 metaBs, err := json.Marshal(event.Meta) 43 if err != nil { 44 return err 45 } 46 err = m.DB.Model(PlayerEvent{}).Create(PlayerEvent{ 47 + ID: uu.String(), 48 Time: event.Time, 49 PlayerID: event.PlayerID, 50 EventType: event.EventType,
-411
pkg/model/segment.go
··· 1 package model 2 - 3 - import ( 4 - "context" 5 - "database/sql/driver" 6 - "encoding/json" 7 - "errors" 8 - "fmt" 9 - "time" 10 - 11 - "gorm.io/gorm" 12 - "stream.place/streamplace/pkg/aqtime" 13 - "stream.place/streamplace/pkg/log" 14 - "stream.place/streamplace/pkg/streamplace" 15 - ) 16 - 17 - type SegmentMediadataVideo struct { 18 - Width int `json:"width"` 19 - Height int `json:"height"` 20 - FPSNum int `json:"fpsNum"` 21 - FPSDen int `json:"fpsDen"` 22 - BFrames bool `json:"bframes"` 23 - } 24 - 25 - type SegmentMediadataAudio struct { 26 - Rate int `json:"rate"` 27 - Channels int `json:"channels"` 28 - } 29 - 30 - type SegmentMediaData struct { 31 - Video []*SegmentMediadataVideo `json:"video"` 32 - Audio []*SegmentMediadataAudio `json:"audio"` 33 - Duration int64 `json:"duration"` 34 - Size int `json:"size"` 35 - } 36 - 37 - // Scan scan value into Jsonb, implements sql.Scanner interface 38 - func (j *SegmentMediaData) Scan(value any) error { 39 - bytes, ok := value.([]byte) 40 - if !ok { 41 - return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value)) 42 - } 43 - 44 - result := SegmentMediaData{} 45 - err := json.Unmarshal(bytes, &result) 46 - *j = SegmentMediaData(result) 47 - return err 48 - } 49 - 50 - // Value return json value, implement driver.Valuer interface 51 - func (j SegmentMediaData) Value() (driver.Value, error) { 52 - return json.Marshal(j) 53 - } 54 - 55 - // ContentRights represents content rights and attribution information 56 - type ContentRights struct { 57 - CopyrightNotice *string `json:"copyrightNotice,omitempty"` 58 - CopyrightYear *int64 `json:"copyrightYear,omitempty"` 59 - Creator *string `json:"creator,omitempty"` 60 - CreditLine *string `json:"creditLine,omitempty"` 61 - License *string `json:"license,omitempty"` 62 - } 63 - 64 - // Scan scan value into ContentRights, implements sql.Scanner interface 65 - func (c *ContentRights) Scan(value any) error { 66 - if value == nil { 67 - *c = ContentRights{} 68 - return nil 69 - } 70 - bytes, ok := value.([]byte) 71 - if !ok { 72 - return errors.New(fmt.Sprint("Failed to unmarshal ContentRights value:", value)) 73 - } 74 - 75 - result := ContentRights{} 76 - err := json.Unmarshal(bytes, &result) 77 - *c = ContentRights(result) 78 - return err 79 - } 80 - 81 - // Value return json value, implement driver.Valuer interface 82 - func (c ContentRights) Value() (driver.Value, error) { 83 - return json.Marshal(c) 84 - } 85 - 86 - // DistributionPolicy represents distribution policy information 87 - type DistributionPolicy struct { 88 - DeleteAfterSeconds *int64 `json:"deleteAfterSeconds,omitempty"` 89 - } 90 - 91 - // Scan scan value into DistributionPolicy, implements sql.Scanner interface 92 - func (d *DistributionPolicy) Scan(value any) error { 93 - if value == nil { 94 - *d = DistributionPolicy{} 95 - return nil 96 - } 97 - bytes, ok := value.([]byte) 98 - if !ok { 99 - return errors.New(fmt.Sprint("Failed to unmarshal DistributionPolicy value:", value)) 100 - } 101 - 102 - result := DistributionPolicy{} 103 - err := json.Unmarshal(bytes, &result) 104 - *d = DistributionPolicy(result) 105 - return err 106 - } 107 - 108 - // Value return json value, implement driver.Valuer interface 109 - func (d DistributionPolicy) Value() (driver.Value, error) { 110 - return json.Marshal(d) 111 - } 112 - 113 - // ContentWarningsSlice is a custom type for storing content warnings as JSON in the database 114 - type ContentWarningsSlice []string 115 - 116 - // Scan scan value into ContentWarningsSlice, implements sql.Scanner interface 117 - func (c *ContentWarningsSlice) Scan(value any) error { 118 - if value == nil { 119 - *c = ContentWarningsSlice{} 120 - return nil 121 - } 122 - bytes, ok := value.([]byte) 123 - if !ok { 124 - return errors.New(fmt.Sprint("Failed to unmarshal ContentWarningsSlice value:", value)) 125 - } 126 - 127 - result := ContentWarningsSlice{} 128 - err := json.Unmarshal(bytes, &result) 129 - *c = ContentWarningsSlice(result) 130 - return err 131 - } 132 - 133 - // Value return json value, implement driver.Valuer interface 134 - func (c ContentWarningsSlice) Value() (driver.Value, error) { 135 - return json.Marshal(c) 136 - } 137 - 138 - type Segment struct { 139 - ID string `json:"id" gorm:"primaryKey"` 140 - SigningKeyDID string `json:"signingKeyDID" gorm:"column:signing_key_did"` 141 - SigningKey *SigningKey `json:"signingKey,omitempty" gorm:"foreignKey:DID;references:SigningKeyDID"` 142 - StartTime time.Time `json:"startTime" gorm:"index:latest_segments,priority:2;index:start_time"` 143 - RepoDID string `json:"repoDID" gorm:"index:latest_segments,priority:1;column:repo_did"` 144 - Repo *Repo `json:"repo,omitempty" gorm:"foreignKey:DID;references:RepoDID"` 145 - Title string `json:"title"` 146 - Size int `json:"size" gorm:"column:size"` 147 - MediaData *SegmentMediaData `json:"mediaData,omitempty"` 148 - ContentWarnings ContentWarningsSlice `json:"contentWarnings,omitempty"` 149 - ContentRights *ContentRights `json:"contentRights,omitempty"` 150 - DistributionPolicy *DistributionPolicy `json:"distributionPolicy,omitempty"` 151 - DeleteAfter *time.Time `json:"deleteAfter,omitempty" gorm:"column:delete_after;index:delete_after"` 152 - } 153 - 154 - func (s *Segment) ToStreamplaceSegment() (*streamplace.Segment, error) { 155 - aqt := aqtime.FromTime(s.StartTime) 156 - if s.MediaData == nil { 157 - return nil, fmt.Errorf("media data is nil") 158 - } 159 - if len(s.MediaData.Video) == 0 || s.MediaData.Video[0] == nil { 160 - return nil, fmt.Errorf("video data is nil") 161 - } 162 - if len(s.MediaData.Audio) == 0 || s.MediaData.Audio[0] == nil { 163 - return nil, fmt.Errorf("audio data is nil") 164 - } 165 - duration := s.MediaData.Duration 166 - sizei64 := int64(s.Size) 167 - 168 - // Convert model metadata to streamplace metadata 169 - var contentRights *streamplace.MetadataContentRights 170 - if s.ContentRights != nil { 171 - contentRights = &streamplace.MetadataContentRights{ 172 - CopyrightNotice: s.ContentRights.CopyrightNotice, 173 - CopyrightYear: s.ContentRights.CopyrightYear, 174 - Creator: s.ContentRights.Creator, 175 - CreditLine: s.ContentRights.CreditLine, 176 - License: s.ContentRights.License, 177 - } 178 - } 179 - 180 - var contentWarnings *streamplace.MetadataContentWarnings 181 - if len(s.ContentWarnings) > 0 { 182 - contentWarnings = &streamplace.MetadataContentWarnings{ 183 - Warnings: []string(s.ContentWarnings), 184 - } 185 - } 186 - 187 - var distributionPolicy *streamplace.MetadataDistributionPolicy 188 - if s.DistributionPolicy != nil && s.DistributionPolicy.DeleteAfterSeconds != nil { 189 - distributionPolicy = &streamplace.MetadataDistributionPolicy{ 190 - DeleteAfter: s.DistributionPolicy.DeleteAfterSeconds, 191 - } 192 - } 193 - 194 - return &streamplace.Segment{ 195 - LexiconTypeID: "place.stream.segment", 196 - Creator: s.RepoDID, 197 - Id: s.ID, 198 - SigningKey: s.SigningKeyDID, 199 - StartTime: string(aqt), 200 - Duration: &duration, 201 - Size: &sizei64, 202 - ContentRights: contentRights, 203 - ContentWarnings: contentWarnings, 204 - DistributionPolicy: distributionPolicy, 205 - Video: []*streamplace.Segment_Video{ 206 - { 207 - Codec: "h264", 208 - Width: int64(s.MediaData.Video[0].Width), 209 - Height: int64(s.MediaData.Video[0].Height), 210 - Framerate: &streamplace.Segment_Framerate{ 211 - Num: int64(s.MediaData.Video[0].FPSNum), 212 - Den: int64(s.MediaData.Video[0].FPSDen), 213 - }, 214 - Bframes: &s.MediaData.Video[0].BFrames, 215 - }, 216 - }, 217 - Audio: []*streamplace.Segment_Audio{ 218 - { 219 - Codec: "opus", 220 - Rate: int64(s.MediaData.Audio[0].Rate), 221 - Channels: int64(s.MediaData.Audio[0].Channels), 222 - }, 223 - }, 224 - }, nil 225 - } 226 - 227 - func (m *DBModel) CreateSegment(seg *Segment) error { 228 - err := m.DB.Model(Segment{}).Create(seg).Error 229 - if err != nil { 230 - return err 231 - } 232 - return nil 233 - } 234 - 235 - // should return the most recent segment for each user, ordered by most recent first 236 - // only includes segments from the last 30 seconds 237 - func (m *DBModel) MostRecentSegments() ([]Segment, error) { 238 - var segments []Segment 239 - thirtySecondsAgo := time.Now().Add(-30 * time.Second) 240 - 241 - err := m.DB.Table("segments"). 242 - Select("segments.*"). 243 - Where("start_time > ?", thirtySecondsAgo.UTC()). 244 - Order("start_time DESC"). 245 - Find(&segments).Error 246 - if err != nil { 247 - return nil, err 248 - } 249 - if segments == nil { 250 - return []Segment{}, nil 251 - } 252 - 253 - segmentMap := make(map[string]Segment) 254 - for _, seg := range segments { 255 - prev, ok := segmentMap[seg.RepoDID] 256 - if !ok { 257 - segmentMap[seg.RepoDID] = seg 258 - } else { 259 - if seg.StartTime.After(prev.StartTime) { 260 - segmentMap[seg.RepoDID] = seg 261 - } 262 - } 263 - } 264 - 265 - filteredSegments := []Segment{} 266 - for _, seg := range segmentMap { 267 - filteredSegments = append(filteredSegments, seg) 268 - } 269 - 270 - return filteredSegments, nil 271 - } 272 - 273 - func (m *DBModel) LatestSegmentForUser(user string) (*Segment, error) { 274 - var seg Segment 275 - err := m.DB.Model(Segment{}).Where("repo_did = ?", user).Order("start_time DESC").First(&seg).Error 276 - if err != nil { 277 - return nil, err 278 - } 279 - return &seg, nil 280 - } 281 - 282 - func (m *DBModel) FilterLiveRepoDIDs(repoDIDs []string) ([]string, error) { 283 - if len(repoDIDs) == 0 { 284 - return []string{}, nil 285 - } 286 - 287 - thirtySecondsAgo := time.Now().Add(-30 * time.Second) 288 - 289 - var liveDIDs []string 290 - 291 - err := m.DB.Table("segments"). 292 - Select("DISTINCT repo_did"). 293 - Where("repo_did IN ? AND start_time > ?", repoDIDs, thirtySecondsAgo.UTC()). 294 - Pluck("repo_did", &liveDIDs).Error 295 - 296 - if err != nil { 297 - return nil, err 298 - } 299 - 300 - return liveDIDs, nil 301 - } 302 - 303 - func (m *DBModel) LatestSegmentsForUser(user string, limit int, before *time.Time, after *time.Time) ([]Segment, error) { 304 - var segs []Segment 305 - if before == nil { 306 - later := time.Now().Add(1000 * time.Hour) 307 - before = &later 308 - } 309 - if after == nil { 310 - earlier := time.Time{} 311 - after = &earlier 312 - } 313 - err := m.DB.Model(Segment{}).Where("repo_did = ? AND start_time < ? AND start_time > ?", user, before.UTC(), after.UTC()).Order("start_time DESC").Limit(limit).Find(&segs).Error 314 - if err != nil { 315 - return nil, err 316 - } 317 - return segs, nil 318 - } 319 - 320 - func (m *DBModel) GetSegment(id string) (*Segment, error) { 321 - var seg Segment 322 - 323 - err := m.DB.Model(&Segment{}). 324 - Preload("Repo"). 325 - Where("id = ?", id). 326 - First(&seg).Error 327 - 328 - if errors.Is(err, gorm.ErrRecordNotFound) { 329 - return nil, nil 330 - } 331 - if err != nil { 332 - return nil, err 333 - } 334 - 335 - return &seg, nil 336 - } 337 - 338 - func (m *DBModel) GetExpiredSegments(ctx context.Context) ([]Segment, error) { 339 - 340 - var expiredSegments []Segment 341 - now := time.Now() 342 - err := m.DB. 343 - Where("delete_after IS NOT NULL AND delete_after < ?", now.UTC()). 344 - Find(&expiredSegments).Error 345 - if err != nil { 346 - return nil, err 347 - } 348 - 349 - return expiredSegments, nil 350 - } 351 - 352 - func (m *DBModel) DeleteSegment(ctx context.Context, id string) error { 353 - return m.DB.Delete(&Segment{}, "id = ?", id).Error 354 - } 355 - 356 - func (m *DBModel) StartSegmentCleaner(ctx context.Context) error { 357 - err := m.SegmentCleaner(ctx) 358 - if err != nil { 359 - return err 360 - } 361 - ticker := time.NewTicker(1 * time.Minute) 362 - defer ticker.Stop() 363 - 364 - for { 365 - select { 366 - case <-ctx.Done(): 367 - return nil 368 - case <-ticker.C: 369 - err := m.SegmentCleaner(ctx) 370 - if err != nil { 371 - log.Error(ctx, "Failed to clean segments", "error", err) 372 - } 373 - } 374 - } 375 - } 376 - 377 - func (m *DBModel) SegmentCleaner(ctx context.Context) error { 378 - // Calculate the cutoff time (10 minutes ago) 379 - cutoffTime := aqtime.FromTime(time.Now().Add(-10 * time.Minute)).Time() 380 - 381 - // Find all unique repo_did values 382 - var repoDIDs []string 383 - if err := m.DB.Model(&Segment{}).Distinct("repo_did").Pluck("repo_did", &repoDIDs).Error; err != nil { 384 - log.Error(ctx, "Failed to get unique repo_dids for segment cleaning", "error", err) 385 - return err 386 - } 387 - 388 - // For each user, keep their last 10 segments and delete older ones 389 - for _, repoDID := range repoDIDs { 390 - // Get IDs of the last 10 segments for this user 391 - var keepSegmentIDs []string 392 - if err := m.DB.Model(&Segment{}). 393 - Where("repo_did = ?", repoDID). 394 - Order("start_time DESC"). 395 - Limit(10). 396 - Pluck("id", &keepSegmentIDs).Error; err != nil { 397 - log.Error(ctx, "Failed to get segment IDs to keep", "repo_did", repoDID, "error", err) 398 - return err 399 - } 400 - 401 - // Delete old segments except the ones we want to keep 402 - result := m.DB.Where("repo_did = ? AND start_time < ? AND id NOT IN ?", 403 - repoDID, cutoffTime, keepSegmentIDs).Delete(&Segment{}) 404 - 405 - if result.Error != nil { 406 - log.Error(ctx, "Failed to clean old segments", "repo_did", repoDID, "error", result.Error) 407 - } else if result.RowsAffected > 0 { 408 - log.Log(ctx, "Cleaned old segments", "repo_did", repoDID, "count", result.RowsAffected) 409 - } 410 - } 411 - return nil 412 - }
··· 1 package model
-65
pkg/model/segment_test.go
··· 1 package model 2 - 3 - import ( 4 - "fmt" 5 - "sync" 6 - "testing" 7 - "time" 8 - 9 - "github.com/stretchr/testify/require" 10 - "stream.place/streamplace/pkg/config" 11 - ) 12 - 13 - func TestSegmentPerf(t *testing.T) { 14 - config.DisableSQLLogging() 15 - // dburl := filepath.Join(t.TempDir(), "test.db") 16 - db, err := MakeDB(":memory:") 17 - require.NoError(t, err) 18 - // Create a model instance 19 - model := db.(*DBModel) 20 - t.Cleanup(func() { 21 - // os.Remove(dburl) 22 - }) 23 - 24 - // Create a repo for testing 25 - repo := &Repo{ 26 - DID: "did:plc:test123", 27 - } 28 - err = model.DB.Create(repo).Error 29 - require.NoError(t, err) 30 - 31 - defer config.EnableSQLLogging() 32 - // Create 250000 segments with timestamps 1 hour ago, each one second apart 33 - wg := sync.WaitGroup{} 34 - segCount := 250000 35 - wg.Add(segCount) 36 - baseTime := time.Now() 37 - for i := 0; i < segCount; i++ { 38 - segment := &Segment{ 39 - ID: fmt.Sprintf("segment-%d", i), 40 - RepoDID: repo.DID, 41 - StartTime: baseTime.Add(-time.Duration(i) * time.Second).UTC(), 42 - } 43 - go func() { 44 - defer wg.Done() 45 - err = model.DB.Create(segment).Error 46 - require.NoError(t, err) 47 - }() 48 - } 49 - wg.Wait() 50 - 51 - startTime := time.Now() 52 - wg = sync.WaitGroup{} 53 - runs := 1000 54 - wg.Add(runs) 55 - for i := 0; i < runs; i++ { 56 - go func() { 57 - defer wg.Done() 58 - _, err := model.MostRecentSegments() 59 - require.NoError(t, err) 60 - // require.Len(t, segments, 1) 61 - }() 62 - } 63 - wg.Wait() 64 - fmt.Printf("Time taken: %s\n", time.Since(startTime)) 65 - require.Less(t, time.Since(startTime), 10*time.Second) 66 - }
··· 1 package model
+115
pkg/model/teleport.go
···
··· 1 + package model 2 + 3 + import ( 4 + "context" 5 + "errors" 6 + "fmt" 7 + "time" 8 + 9 + "gorm.io/gorm" 10 + "gorm.io/gorm/clause" 11 + ) 12 + 13 + type Teleport struct { 14 + URI string `json:"uri" gorm:"primaryKey;column:uri"` 15 + CID string `json:"cid" gorm:"column:cid"` 16 + StartsAt time.Time `json:"startsAt" gorm:"column:starts_at;index:idx_repo_starts,priority:2"` 17 + DurationSeconds *int64 `json:"durationSeconds" gorm:"column:duration_seconds"` 18 + ViewerCount int64 `json:"viewerCount" gorm:"column:viewer_count;default:0"` 19 + Teleport *[]byte `json:"teleport"` 20 + RepoDID string `json:"repoDID" gorm:"column:repo_did;index:idx_repo_starts,priority:1"` 21 + TargetDID string `json:"targetDID" gorm:"column:target_did;index:idx_target_did"` 22 + Denied bool `json:"denied" gorm:"column:denied;default:false"` 23 + Repo *Repo `json:"repo,omitempty" gorm:"foreignKey:DID;references:RepoDID"` 24 + Target *Repo `json:"target,omitempty" gorm:"foreignKey:DID;references:TargetDID"` 25 + } 26 + 27 + func (m *DBModel) CreateTeleport(ctx context.Context, tp *Teleport) error { 28 + return m.DB.Clauses(clause.OnConflict{ 29 + Columns: []clause.Column{{Name: "uri"}}, 30 + DoUpdates: clause.AssignmentColumns([]string{"cid", "starts_at", "duration_seconds", "viewer_count", "teleport", "repo_did", "target_did"}), 31 + }).Create(tp).Error 32 + } 33 + 34 + func (m *DBModel) GetLatestTeleportForRepo(repoDID string) (*Teleport, error) { 35 + var teleport Teleport 36 + err := m.DB. 37 + Preload("Repo"). 38 + Preload("Target"). 39 + Where("repo_did = ?", repoDID). 40 + Order("starts_at DESC"). 41 + First(&teleport).Error 42 + if errors.Is(err, gorm.ErrRecordNotFound) { 43 + return nil, nil 44 + } 45 + if err != nil { 46 + return nil, fmt.Errorf("error retrieving latest teleport: %w", err) 47 + } 48 + return &teleport, nil 49 + } 50 + 51 + func (m *DBModel) GetActiveTeleportsForRepo(repoDID string) ([]Teleport, error) { 52 + now := time.Now() 53 + var teleports []Teleport 54 + err := m.DB. 55 + Preload("Repo"). 56 + Preload("Target"). 57 + Where("repo_did = ?", repoDID). 58 + Where("denied = ?", false). 59 + Where("starts_at <= ?", now). 60 + Where("(duration_seconds IS NULL OR DATE_ADD(starts_at, INTERVAL duration_seconds SECOND) > ?)", now). 61 + Order("starts_at DESC"). 62 + Find(&teleports).Error 63 + if errors.Is(err, gorm.ErrRecordNotFound) { 64 + return nil, nil 65 + } 66 + if err != nil { 67 + return nil, fmt.Errorf("error retrieving active teleports: %w", err) 68 + } 69 + return teleports, nil 70 + } 71 + 72 + func (m *DBModel) GetActiveTeleportsToRepo(targetDID string) ([]Teleport, error) { 73 + now := time.Now() 74 + var teleports []Teleport 75 + err := m.DB. 76 + Preload("Repo"). 77 + Preload("Target"). 78 + Where("target_did = ?", targetDID). 79 + Where("denied = ?", false). 80 + Where("starts_at <= ?", now). 81 + Where("(duration_seconds IS NULL OR datetime(starts_at, '+' || duration_seconds || ' seconds') > ?)", now). 82 + Order("starts_at DESC"). 83 + Find(&teleports).Error 84 + if errors.Is(err, gorm.ErrRecordNotFound) { 85 + return nil, nil 86 + } 87 + if err != nil { 88 + return nil, fmt.Errorf("error retrieving active teleports to repo: %w", err) 89 + } 90 + return teleports, nil 91 + } 92 + 93 + func (m *DBModel) GetTeleportByURI(uri string) (*Teleport, error) { 94 + var teleport Teleport 95 + err := m.DB. 96 + Preload("Repo"). 97 + Preload("Target"). 98 + Where("uri = ?", uri). 99 + First(&teleport).Error 100 + if errors.Is(err, gorm.ErrRecordNotFound) { 101 + return nil, nil 102 + } 103 + if err != nil { 104 + return nil, fmt.Errorf("error retrieving teleport by uri: %w", err) 105 + } 106 + return &teleport, nil 107 + } 108 + 109 + func (m *DBModel) DeleteTeleport(ctx context.Context, uri string) error { 110 + return m.DB.Where("uri = ?", uri).Delete(&Teleport{}).Error 111 + } 112 + 113 + func (m *DBModel) DenyTeleport(ctx context.Context, uri string) error { 114 + return m.DB.Model(&Teleport{}).Where("uri = ?", uri).Update("denied", true).Error 115 + }
-59
pkg/model/thumbnail.go
··· 1 package model 2 - 3 - import ( 4 - "fmt" 5 - 6 - "github.com/google/uuid" 7 - ) 8 - 9 - type Thumbnail struct { 10 - ID string `json:"id" gorm:"primaryKey"` 11 - Format string `json:"format"` 12 - SegmentID string `json:"segmentId" gorm:"index"` 13 - Segment Segment `json:"segment,omitempty" gorm:"foreignKey:SegmentID;references:id"` 14 - } 15 - 16 - func (m *DBModel) CreateThumbnail(thumb *Thumbnail) error { 17 - uu, err := uuid.NewV7() 18 - if err != nil { 19 - return err 20 - } 21 - if thumb.SegmentID == "" { 22 - return fmt.Errorf("segmentID is required") 23 - } 24 - thumb.ID = uu.String() 25 - err = m.DB.Model(Thumbnail{}).Create(thumb).Error 26 - if err != nil { 27 - return err 28 - } 29 - return nil 30 - } 31 - 32 - // return the most recent thumbnail for a user 33 - func (m *DBModel) LatestThumbnailForUser(user string) (*Thumbnail, error) { 34 - var thumbnail Thumbnail 35 - 36 - res := m.DB.Table("thumbnails AS t"). 37 - Select("t.*"). 38 - Joins("JOIN segments AS s ON t.segment_id = s.id"). 39 - Where("s.repo_did = ?", user). 40 - Order("s.start_time DESC"). 41 - Limit(1). 42 - Scan(&thumbnail) 43 - 44 - if res.RowsAffected == 0 { 45 - return nil, nil 46 - } 47 - if res.Error != nil { 48 - return nil, res.Error 49 - } 50 - 51 - var seg Segment 52 - err := m.DB.First(&seg, "id = ?", thumbnail.SegmentID).Error 53 - if err != nil { 54 - return nil, fmt.Errorf("could not find segment for thumbnail SegmentID=%s", thumbnail.SegmentID) 55 - } 56 - 57 - thumbnail.Segment = seg 58 - 59 - return &thumbnail, nil 60 - }
··· 1 package model
+1 -1
pkg/spxrpc/app_bsky_feed.go
··· 56 outCursor = fmt.Sprintf("%d::%s", ts, last.CID) 57 } 58 } else if name == FeedLiveStreams { 59 - segs, err := s.model.MostRecentSegments() 60 if err != nil { 61 return nil, echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to get recent segments: %v", err)) 62 }
··· 56 outCursor = fmt.Sprintf("%d::%s", ts, last.CID) 57 } 58 } else if name == FeedLiveStreams { 59 + segs, err := s.localDB.MostRecentSegments() 60 if err != nil { 61 return nil, echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to get recent segments: %v", err)) 62 }
+2 -1
pkg/spxrpc/com_atproto_identity.go
··· 5 6 comatprototypes "github.com/bluesky-social/indigo/api/atproto" 7 "github.com/streamplace/oatproxy/pkg/oatproxy" 8 ) 9 10 func (s *Server) handleComAtprotoIdentityResolveHandle(ctx context.Context, handle string) (*comatprototypes.IdentityResolveHandle_Output, error) { 11 - did, err := oatproxy.ResolveHandle(ctx, handle) 12 if err != nil { 13 return nil, err 14 }
··· 5 6 comatprototypes "github.com/bluesky-social/indigo/api/atproto" 7 "github.com/streamplace/oatproxy/pkg/oatproxy" 8 + "stream.place/streamplace/pkg/aqhttp" 9 ) 10 11 func (s *Server) handleComAtprotoIdentityResolveHandle(ctx context.Context, handle string) (*comatprototypes.IdentityResolveHandle_Output, error) { 12 + did, err := oatproxy.ResolveHandleWithClient(ctx, handle, &aqhttp.Client) 13 if err != nil { 14 return nil, err 15 }
+4 -4
pkg/spxrpc/com_atproto_moderation.go
··· 13 "github.com/labstack/echo/v4" 14 "github.com/streamplace/oatproxy/pkg/oatproxy" 15 "stream.place/streamplace/pkg/config" 16 "stream.place/streamplace/pkg/log" 17 "stream.place/streamplace/pkg/media" 18 - "stream.place/streamplace/pkg/model" 19 ) 20 21 func (s *Server) handleComAtprotoModerationCreateReport(ctx context.Context, body *comatprototypes.ModerationCreateReport_Input) (*comatprototypes.ModerationCreateReport_Output, error) { ··· 76 return nil, echo.NewHTTPError(http.StatusBadRequest, "invalid subject") 77 } 78 79 - clipID, err := makeClip(ctx, s.cli, s.model, did) 80 if err != nil { 81 // we still want the report to go through! 82 log.Error(ctx, "failed to make clip for report", "error", err) ··· 99 return &output, nil 100 } 101 102 - func makeClip(ctx context.Context, cli *config.CLI, mod model.Model, did string) (string, error) { 103 after := time.Now().Add(-time.Duration(60) * time.Second) 104 105 uu, err := uuid.NewV7() ··· 113 } 114 defer fd.Close() 115 116 - err = media.ClipUser(ctx, mod, cli, did, fd, nil, &after) 117 if err != nil { 118 return "", echo.NewHTTPError(http.StatusInternalServerError, "failed to clip user") 119 }
··· 13 "github.com/labstack/echo/v4" 14 "github.com/streamplace/oatproxy/pkg/oatproxy" 15 "stream.place/streamplace/pkg/config" 16 + "stream.place/streamplace/pkg/localdb" 17 "stream.place/streamplace/pkg/log" 18 "stream.place/streamplace/pkg/media" 19 ) 20 21 func (s *Server) handleComAtprotoModerationCreateReport(ctx context.Context, body *comatprototypes.ModerationCreateReport_Input) (*comatprototypes.ModerationCreateReport_Output, error) { ··· 76 return nil, echo.NewHTTPError(http.StatusBadRequest, "invalid subject") 77 } 78 79 + clipID, err := makeClip(ctx, s.cli, s.localDB, did) 80 if err != nil { 81 // we still want the report to go through! 82 log.Error(ctx, "failed to make clip for report", "error", err) ··· 99 return &output, nil 100 } 101 102 + func makeClip(ctx context.Context, cli *config.CLI, localDB localdb.LocalDB, did string) (string, error) { 103 after := time.Now().Add(-time.Duration(60) * time.Second) 104 105 uu, err := uuid.NewV7() ··· 113 } 114 defer fd.Close() 115 116 + err = media.ClipUser(ctx, localDB, cli, did, fd, nil, &after) 117 if err != nil { 118 return "", echo.NewHTTPError(http.StatusInternalServerError, "failed to clip user") 119 }
+3 -2
pkg/spxrpc/com_atproto_repo.go
··· 15 "github.com/labstack/echo/v4" 16 "github.com/streamplace/oatproxy/pkg/oatproxy" 17 "go.opentelemetry.io/otel" 18 "stream.place/streamplace/pkg/atproto" 19 "stream.place/streamplace/pkg/log" 20 ) ··· 23 did := repo 24 var err error 25 if !strings.HasPrefix(repo, "did:") { 26 - did, err = oatproxy.ResolveHandle(ctx, repo) 27 if err != nil { 28 return "", "", "", fmt.Errorf("failed to resolve handle %q: %w", repo, err) 29 } 30 } 31 32 - service, handle, err := oatproxy.ResolveService(ctx, did) 33 if err != nil { 34 return "", "", "", fmt.Errorf("failed to resolve service for did %q: %w", did, err) 35 }
··· 15 "github.com/labstack/echo/v4" 16 "github.com/streamplace/oatproxy/pkg/oatproxy" 17 "go.opentelemetry.io/otel" 18 + "stream.place/streamplace/pkg/aqhttp" 19 "stream.place/streamplace/pkg/atproto" 20 "stream.place/streamplace/pkg/log" 21 ) ··· 24 did := repo 25 var err error 26 if !strings.HasPrefix(repo, "did:") { 27 + did, err = oatproxy.ResolveHandleWithClient(ctx, repo, &aqhttp.Client) 28 if err != nil { 29 return "", "", "", fmt.Errorf("failed to resolve handle %q: %w", repo, err) 30 } 31 } 32 33 + service, handle, err := oatproxy.ResolveServiceWithClient(ctx, did, &aqhttp.Client) 34 if err != nil { 35 return "", "", "", fmt.Errorf("failed to resolve service for did %q: %w", did, err) 36 }
+11
pkg/spxrpc/com_atproto_sync.go
··· 46 }, 47 } 48 49 func (s *Server) handleComAtprotoSyncSubscribeRepos(c echo.Context) error { 50 ctx := log.WithLogValues(c.Request().Context(), "client_ip", c.RealIP(), "user_agent", c.Request().UserAgent()) 51 cursor := c.QueryParam("cursor")
··· 46 }, 47 } 48 49 + func (s *Server) handleComAtprotoSyncGetRepo(ctx context.Context, did string, since string) (io.Reader, error) { 50 + if did != atproto.LexiconRepo.RepoDid() { 51 + return nil, echo.NewHTTPError(http.StatusNotFound, "RepoNotFound") 52 + } 53 + bs, err := atproto.LexiconRepoGetRepo(ctx, since) 54 + if err != nil { 55 + return nil, err 56 + } 57 + return bytes.NewReader(bs), nil 58 + } 59 + 60 func (s *Server) handleComAtprotoSyncSubscribeRepos(c echo.Context) error { 61 ctx := log.WithLogValues(c.Request().Context(), "client_ip", c.RealIP(), "user_agent", c.Request().UserAgent()) 62 cursor := c.QueryParam("cursor")
+4 -4
pkg/spxrpc/place_stream_branding.go
··· 38 return s.cli.BroadcasterHost 39 } 40 41 - func (s *Server) getBrandingBlob(ctx context.Context, broadcasterID, key string) ([]byte, string, *int, *int, error) { 42 // cache miss - fetch from db 43 blob, err := s.statefulDB.GetBrandingBlob(broadcasterID, key) 44 if err == gorm.ErrRecordNotFound { ··· 61 // HandlePlaceStreamBrandingGetBlobDirect is the exported version for direct calls 62 func (s *Server) HandlePlaceStreamBrandingGetBlobDirect(ctx context.Context, broadcasterDID string, key string) (io.Reader, error) { 63 broadcasterID := s.getBroadcasterID(ctx, broadcasterDID) 64 - data, _, _, _, err := s.getBrandingBlob(ctx, broadcasterID, key) 65 if err != nil { 66 return nil, err 67 } ··· 94 // build output 95 assets := make([]*placestreamtypes.BrandingGetBranding_BrandingAsset, 0, len(allKeys)) 96 for key := range allKeys { 97 - data, mimeType, width, height, err := s.getBrandingBlob(ctx, broadcasterID, key) 98 if err != nil { 99 continue // skip if error 100 } ··· 238 239 broadcasterID := s.cli.BroadcasterHost 240 log.Log(ctx, "fetching favicon", "broadcasterID", broadcasterID) 241 - data, mimeType, _, _, err := s.getBrandingBlob(ctx, "did:web:"+broadcasterID, "favicon") 242 243 if err != nil || data == nil { 244 log.Log(ctx, "using fallback favicon", "err", err, "data_nil", data == nil)
··· 38 return s.cli.BroadcasterHost 39 } 40 41 + func (s *Server) GetBrandingBlob(ctx context.Context, broadcasterID, key string) ([]byte, string, *int, *int, error) { 42 // cache miss - fetch from db 43 blob, err := s.statefulDB.GetBrandingBlob(broadcasterID, key) 44 if err == gorm.ErrRecordNotFound { ··· 61 // HandlePlaceStreamBrandingGetBlobDirect is the exported version for direct calls 62 func (s *Server) HandlePlaceStreamBrandingGetBlobDirect(ctx context.Context, broadcasterDID string, key string) (io.Reader, error) { 63 broadcasterID := s.getBroadcasterID(ctx, broadcasterDID) 64 + data, _, _, _, err := s.GetBrandingBlob(ctx, broadcasterID, key) 65 if err != nil { 66 return nil, err 67 } ··· 94 // build output 95 assets := make([]*placestreamtypes.BrandingGetBranding_BrandingAsset, 0, len(allKeys)) 96 for key := range allKeys { 97 + data, mimeType, width, height, err := s.GetBrandingBlob(ctx, broadcasterID, key) 98 if err != nil { 99 continue // skip if error 100 } ··· 238 239 broadcasterID := s.cli.BroadcasterHost 240 log.Log(ctx, "fetching favicon", "broadcasterID", broadcasterID) 241 + data, mimeType, _, _, err := s.GetBrandingBlob(ctx, "did:web:"+broadcasterID, "favicon") 242 243 if err != nil || data == nil { 244 log.Log(ctx, "using fallback favicon", "err", err, "data_nil", data == nil)
+67 -5
pkg/spxrpc/place_stream_live.go
··· 9 "github.com/bluesky-social/indigo/lex/util" 10 "github.com/gorilla/websocket" 11 "github.com/labstack/echo/v4" 12 "stream.place/streamplace/pkg/log" 13 "stream.place/streamplace/pkg/spid" 14 "stream.place/streamplace/pkg/spmetrics" ··· 16 placestreamtypes "stream.place/streamplace/pkg/streamplace" 17 ) 18 19 var replicationUpgrader = websocket.Upgrader{ 20 ReadBufferSize: 1024, 21 WriteBufferSize: 1024 * 1024 * 10, // 10MB ··· 37 beforeTime = &parsedTime 38 } 39 40 - segments, err := s.model.LatestSegmentsForUser(userDID, limit, beforeTime, nil) 41 if err != nil { 42 return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch segments") 43 } ··· 68 } 69 70 func (s *Server) handlePlaceStreamLiveGetLiveUsers(ctx context.Context, before string, limit int) (*placestreamtypes.LiveGetLiveUsers_Output, error) { 71 var beforeTime *time.Time 72 if before != "" { 73 parsedTime, err := time.Parse(time.RFC3339, before) ··· 76 } 77 beforeTime = &parsedTime 78 } 79 - ls, err := s.model.GetLatestLivestreams(limit, beforeTime) 80 if err != nil { 81 return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch livestreams") 82 } ··· 100 Streams: streams, 101 } 102 103 return liveUsers, nil 104 } 105 ··· 169 } 170 171 // Filter for only live streamers 172 - liveStreamers, err := s.model.FilterLiveRepoDIDs(streamers) 173 if err != nil { 174 return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to filter live streamers") 175 } ··· 202 followDIDs[i] = follow.SubjectDID 203 } 204 205 - liveFollows, err := s.model.FilterLiveRepoDIDs(followDIDs) 206 if err != nil { 207 return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to filter live follows") 208 } ··· 227 // Final fallback: use host's default recommendations 228 defaultStreamers := s.cli.DefaultRecommendedStreamers 229 if len(defaultStreamers) > 0 { 230 - liveDefaults, err := s.model.FilterLiveRepoDIDs(defaultStreamers) 231 if err != nil { 232 return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to filter default streamers") 233 }
··· 9 "github.com/bluesky-social/indigo/lex/util" 10 "github.com/gorilla/websocket" 11 "github.com/labstack/echo/v4" 12 + "github.com/streamplace/oatproxy/pkg/oatproxy" 13 "stream.place/streamplace/pkg/log" 14 "stream.place/streamplace/pkg/spid" 15 "stream.place/streamplace/pkg/spmetrics" ··· 17 placestreamtypes "stream.place/streamplace/pkg/streamplace" 18 ) 19 20 + func (s *Server) handlePlaceStreamLiveDenyTeleport(ctx context.Context, input *placestreamtypes.LiveDenyTeleport_Input) (*placestreamtypes.LiveDenyTeleport_Output, error) { 21 + session, _ := oatproxy.GetOAuthSession(ctx) 22 + if session == nil { 23 + return nil, echo.NewHTTPError(http.StatusUnauthorized, "oauth session not found") 24 + } 25 + 26 + if input.Uri == "" { 27 + return nil, echo.NewHTTPError(http.StatusBadRequest, "URI is required") 28 + } 29 + 30 + teleport, err := s.model.GetTeleportByURI(input.Uri) 31 + if err != nil { 32 + log.Error(ctx, "failed to get teleport", "err", err) 33 + return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to retrieve teleport") 34 + } 35 + 36 + if teleport == nil { 37 + return nil, echo.NewHTTPError(http.StatusNotFound, "Teleport not found") 38 + } 39 + 40 + if teleport.TargetDID != session.DID { 41 + return nil, echo.NewHTTPError(http.StatusForbidden, "You are not the target of this teleport") 42 + } 43 + 44 + err = s.model.DenyTeleport(ctx, input.Uri) 45 + if err != nil { 46 + log.Error(ctx, "failed to deny teleport", "err", err) 47 + return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to deny teleport") 48 + } 49 + 50 + cancelMsg := &placestreamtypes.Livestream_TeleportCanceled{ 51 + LexiconTypeID: "place.stream.livestream#teleportCanceled", 52 + TeleportUri: input.Uri, 53 + Reason: "denied", 54 + } 55 + 56 + s.bus.Publish(teleport.RepoDID, cancelMsg) 57 + s.bus.Publish(teleport.TargetDID, cancelMsg) 58 + 59 + return &placestreamtypes.LiveDenyTeleport_Output{ 60 + Success: true, 61 + }, nil 62 + } 63 + 64 var replicationUpgrader = websocket.Upgrader{ 65 ReadBufferSize: 1024, 66 WriteBufferSize: 1024 * 1024 * 10, // 10MB ··· 82 beforeTime = &parsedTime 83 } 84 85 + segments, err := s.localDB.LatestSegmentsForUser(userDID, limit, beforeTime, nil) 86 if err != nil { 87 return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch segments") 88 } ··· 113 } 114 115 func (s *Server) handlePlaceStreamLiveGetLiveUsers(ctx context.Context, before string, limit int) (*placestreamtypes.LiveGetLiveUsers_Output, error) { 116 + // Check cache first 117 + cacheKey := fmt.Sprintf("live_users_%s_%d", before, limit) 118 + if cached, found := s.LiveUsersCache.Get(cacheKey); found { 119 + return cached.(*placestreamtypes.LiveGetLiveUsers_Output), nil 120 + } 121 + 122 var beforeTime *time.Time 123 if before != "" { 124 parsedTime, err := time.Parse(time.RFC3339, before) ··· 127 } 128 beforeTime = &parsedTime 129 } 130 + segs, err := s.localDB.MostRecentSegments() 131 + if err != nil { 132 + return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch recent segments") 133 + } 134 + dids := make([]string, len(segs)) 135 + for i, seg := range segs { 136 + dids[i] = seg.RepoDID 137 + } 138 + ls, err := s.model.GetLatestLivestreams(limit, beforeTime, dids) 139 if err != nil { 140 return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch livestreams") 141 } ··· 159 Streams: streams, 160 } 161 162 + // Cache the result 163 + s.LiveUsersCache.SetDefault(cacheKey, liveUsers) 164 + 165 return liveUsers, nil 166 } 167 ··· 231 } 232 233 // Filter for only live streamers 234 + liveStreamers, err := s.localDB.FilterLiveRepoDIDs(streamers) 235 if err != nil { 236 return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to filter live streamers") 237 } ··· 264 followDIDs[i] = follow.SubjectDID 265 } 266 267 + liveFollows, err := s.localDB.FilterLiveRepoDIDs(followDIDs) 268 if err != nil { 269 return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to filter live follows") 270 } ··· 289 // Final fallback: use host's default recommendations 290 defaultStreamers := s.cli.DefaultRecommendedStreamers 291 if len(defaultStreamers) > 0 { 292 + liveDefaults, err := s.localDB.FilterLiveRepoDIDs(defaultStreamers) 293 if err != nil { 294 return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to filter default streamers") 295 }
+22 -17
pkg/spxrpc/spxrpc.go
··· 18 "stream.place/streamplace/pkg/atproto" 19 "stream.place/streamplace/pkg/bus" 20 "stream.place/streamplace/pkg/config" 21 "stream.place/streamplace/pkg/log" 22 "stream.place/streamplace/pkg/model" 23 "stream.place/streamplace/pkg/statedb" 24 ) 25 26 type Server struct { 27 - e *echo.Echo 28 - cli *config.CLI 29 - model model.Model 30 - OGImageCache *cache.Cache 31 - ATSync *atproto.ATProtoSynchronizer 32 - statefulDB *statedb.StatefulDB 33 - bus *bus.Bus 34 - op *oatproxy.OATProxy 35 } 36 37 - func NewServer(ctx context.Context, cli *config.CLI, model model.Model, statefulDB *statedb.StatefulDB, op *oatproxy.OATProxy, mdlw middleware.Middleware, atsync *atproto.ATProtoSynchronizer, bus *bus.Bus) (*Server, error) { 38 e := echo.New() 39 s := &Server{ 40 - e: e, 41 - cli: cli, 42 - model: model, 43 - OGImageCache: cache.New(5*time.Minute, 10*time.Minute), // 5min TTL, 10min cleanup 44 - ATSync: atsync, 45 - statefulDB: statefulDB, 46 - bus: bus, 47 - op: op, 48 } 49 e.Use(s.ErrorHandlingMiddleware()) 50 e.Use(s.ContextPreservingMiddleware())
··· 18 "stream.place/streamplace/pkg/atproto" 19 "stream.place/streamplace/pkg/bus" 20 "stream.place/streamplace/pkg/config" 21 + "stream.place/streamplace/pkg/localdb" 22 "stream.place/streamplace/pkg/log" 23 "stream.place/streamplace/pkg/model" 24 "stream.place/streamplace/pkg/statedb" 25 ) 26 27 type Server struct { 28 + e *echo.Echo 29 + cli *config.CLI 30 + model model.Model 31 + OGImageCache *cache.Cache 32 + LiveUsersCache *cache.Cache 33 + ATSync *atproto.ATProtoSynchronizer 34 + statefulDB *statedb.StatefulDB 35 + bus *bus.Bus 36 + op *oatproxy.OATProxy 37 + localDB localdb.LocalDB 38 } 39 40 + func NewServer(ctx context.Context, cli *config.CLI, model model.Model, statefulDB *statedb.StatefulDB, op *oatproxy.OATProxy, mdlw middleware.Middleware, atsync *atproto.ATProtoSynchronizer, bus *bus.Bus, ldb localdb.LocalDB) (*Server, error) { 41 e := echo.New() 42 s := &Server{ 43 + e: e, 44 + cli: cli, 45 + model: model, 46 + OGImageCache: cache.New(5*time.Minute, 10*time.Minute), // 5min TTL, 10min cleanup 47 + LiveUsersCache: cache.New(5*time.Second, 10*time.Second), // 5sec TTL, 10sec cleanup 48 + ATSync: atsync, 49 + statefulDB: statefulDB, 50 + bus: bus, 51 + op: op, 52 + localDB: ldb, 53 } 54 e.Use(s.ErrorHandlingMiddleware()) 55 e.Use(s.ContextPreservingMiddleware())
+35
pkg/spxrpc/stubs.go
··· 71 e.POST("/xrpc/com.atproto.repo.uploadBlob", s.HandleComAtprotoRepoUploadBlob) 72 e.GET("/xrpc/com.atproto.server.describeServer", s.HandleComAtprotoServerDescribeServer) 73 e.GET("/xrpc/com.atproto.sync.getRecord", s.HandleComAtprotoSyncGetRecord) 74 e.GET("/xrpc/com.atproto.sync.listRepos", s.HandleComAtprotoSyncListRepos) 75 return nil 76 } ··· 236 return c.Stream(200, "application/vnd.ipld.car", out) 237 } 238 239 func (s *Server) HandleComAtprotoSyncListRepos(c echo.Context) error { 240 ctx, span := otel.Tracer("server").Start(c.Request().Context(), "HandleComAtprotoSyncListRepos") 241 defer span.End() ··· 268 e.POST("/xrpc/place.stream.branding.updateBlob", s.HandlePlaceStreamBrandingUpdateBlob) 269 e.GET("/xrpc/place.stream.broadcast.getBroadcaster", s.HandlePlaceStreamBroadcastGetBroadcaster) 270 e.GET("/xrpc/place.stream.graph.getFollowingUser", s.HandlePlaceStreamGraphGetFollowingUser) 271 e.GET("/xrpc/place.stream.live.getLiveUsers", s.HandlePlaceStreamLiveGetLiveUsers) 272 e.GET("/xrpc/place.stream.live.getProfileCard", s.HandlePlaceStreamLiveGetProfileCard) 273 e.GET("/xrpc/place.stream.live.getRecommendations", s.HandlePlaceStreamLiveGetRecommendations) ··· 378 var handleErr error 379 // func (s *Server) handlePlaceStreamGraphGetFollowingUser(ctx context.Context,subjectDID string,userDID string) (*placestream.GraphGetFollowingUser_Output, error) 380 out, handleErr = s.handlePlaceStreamGraphGetFollowingUser(ctx, subjectDID, userDID) 381 if handleErr != nil { 382 return handleErr 383 }
··· 71 e.POST("/xrpc/com.atproto.repo.uploadBlob", s.HandleComAtprotoRepoUploadBlob) 72 e.GET("/xrpc/com.atproto.server.describeServer", s.HandleComAtprotoServerDescribeServer) 73 e.GET("/xrpc/com.atproto.sync.getRecord", s.HandleComAtprotoSyncGetRecord) 74 + e.GET("/xrpc/com.atproto.sync.getRepo", s.HandleComAtprotoSyncGetRepo) 75 e.GET("/xrpc/com.atproto.sync.listRepos", s.HandleComAtprotoSyncListRepos) 76 return nil 77 } ··· 237 return c.Stream(200, "application/vnd.ipld.car", out) 238 } 239 240 + func (s *Server) HandleComAtprotoSyncGetRepo(c echo.Context) error { 241 + ctx, span := otel.Tracer("server").Start(c.Request().Context(), "HandleComAtprotoSyncGetRepo") 242 + defer span.End() 243 + did := c.QueryParam("did") 244 + since := c.QueryParam("since") 245 + var out io.Reader 246 + var handleErr error 247 + // func (s *Server) handleComAtprotoSyncGetRepo(ctx context.Context,did string,since string) (io.Reader, error) 248 + out, handleErr = s.handleComAtprotoSyncGetRepo(ctx, did, since) 249 + if handleErr != nil { 250 + return handleErr 251 + } 252 + return c.Stream(200, "application/vnd.ipld.car", out) 253 + } 254 + 255 func (s *Server) HandleComAtprotoSyncListRepos(c echo.Context) error { 256 ctx, span := otel.Tracer("server").Start(c.Request().Context(), "HandleComAtprotoSyncListRepos") 257 defer span.End() ··· 284 e.POST("/xrpc/place.stream.branding.updateBlob", s.HandlePlaceStreamBrandingUpdateBlob) 285 e.GET("/xrpc/place.stream.broadcast.getBroadcaster", s.HandlePlaceStreamBroadcastGetBroadcaster) 286 e.GET("/xrpc/place.stream.graph.getFollowingUser", s.HandlePlaceStreamGraphGetFollowingUser) 287 + e.POST("/xrpc/place.stream.live.denyTeleport", s.HandlePlaceStreamLiveDenyTeleport) 288 e.GET("/xrpc/place.stream.live.getLiveUsers", s.HandlePlaceStreamLiveGetLiveUsers) 289 e.GET("/xrpc/place.stream.live.getProfileCard", s.HandlePlaceStreamLiveGetProfileCard) 290 e.GET("/xrpc/place.stream.live.getRecommendations", s.HandlePlaceStreamLiveGetRecommendations) ··· 395 var handleErr error 396 // func (s *Server) handlePlaceStreamGraphGetFollowingUser(ctx context.Context,subjectDID string,userDID string) (*placestream.GraphGetFollowingUser_Output, error) 397 out, handleErr = s.handlePlaceStreamGraphGetFollowingUser(ctx, subjectDID, userDID) 398 + if handleErr != nil { 399 + return handleErr 400 + } 401 + return c.JSON(200, out) 402 + } 403 + 404 + func (s *Server) HandlePlaceStreamLiveDenyTeleport(c echo.Context) error { 405 + ctx, span := otel.Tracer("server").Start(c.Request().Context(), "HandlePlaceStreamLiveDenyTeleport") 406 + defer span.End() 407 + 408 + var body placestream.LiveDenyTeleport_Input 409 + if err := c.Bind(&body); err != nil { 410 + return err 411 + } 412 + var out *placestream.LiveDenyTeleport_Output 413 + var handleErr error 414 + // func (s *Server) handlePlaceStreamLiveDenyTeleport(ctx context.Context,body *placestream.LiveDenyTeleport_Input) (*placestream.LiveDenyTeleport_Output, error) 415 + out, handleErr = s.handlePlaceStreamLiveDenyTeleport(ctx, &body) 416 if handleErr != nil { 417 return handleErr 418 }
+6 -6
pkg/storage/storage.go
··· 10 "golang.org/x/sync/errgroup" 11 "stream.place/streamplace/pkg/aqtime" 12 "stream.place/streamplace/pkg/config" 13 "stream.place/streamplace/pkg/log" 14 - "stream.place/streamplace/pkg/model" 15 ) 16 17 const moderationRetention = 120 * time.Second 18 19 - func StartSegmentCleaner(ctx context.Context, mod model.Model, cli *config.CLI) error { 20 ctx = log.WithLogValues(ctx, "func", "StartSegmentCleaner") 21 g, ctx := errgroup.WithContext(ctx) 22 g.Go(func() error { ··· 25 case <-ctx.Done(): 26 return nil 27 case <-time.After(60 * time.Second): 28 - expiredSegments, err := mod.GetExpiredSegments(ctx) 29 if err != nil { 30 return err 31 } 32 log.Log(ctx, "Cleaning expired segments", "count", len(expiredSegments)) 33 for _, seg := range expiredSegments { 34 g.Go(func() error { 35 - err := deleteSegment(ctx, mod, cli, seg) 36 if err != nil { 37 log.Error(ctx, "Failed to delete segment", "error", err) 38 } ··· 47 return g.Wait() 48 } 49 50 - func deleteSegment(ctx context.Context, mod model.Model, cli *config.CLI, seg model.Segment) error { 51 if time.Since(seg.StartTime) < moderationRetention { 52 log.Debug(ctx, "Skipping deletion of segment", "id", seg.ID, "time since start", time.Since(seg.StartTime)) 53 return nil ··· 61 if err != nil && !errors.Is(err, os.ErrNotExist) { 62 return err 63 } 64 - err = mod.DeleteSegment(ctx, seg.ID) 65 if err != nil { 66 return err 67 }
··· 10 "golang.org/x/sync/errgroup" 11 "stream.place/streamplace/pkg/aqtime" 12 "stream.place/streamplace/pkg/config" 13 + "stream.place/streamplace/pkg/localdb" 14 "stream.place/streamplace/pkg/log" 15 ) 16 17 const moderationRetention = 120 * time.Second 18 19 + func StartSegmentCleaner(ctx context.Context, localDB localdb.LocalDB, cli *config.CLI) error { 20 ctx = log.WithLogValues(ctx, "func", "StartSegmentCleaner") 21 g, ctx := errgroup.WithContext(ctx) 22 g.Go(func() error { ··· 25 case <-ctx.Done(): 26 return nil 27 case <-time.After(60 * time.Second): 28 + expiredSegments, err := localDB.GetExpiredSegments(ctx) 29 if err != nil { 30 return err 31 } 32 log.Log(ctx, "Cleaning expired segments", "count", len(expiredSegments)) 33 for _, seg := range expiredSegments { 34 g.Go(func() error { 35 + err := deleteSegment(ctx, localDB, cli, seg) 36 if err != nil { 37 log.Error(ctx, "Failed to delete segment", "error", err) 38 } ··· 47 return g.Wait() 48 } 49 50 + func deleteSegment(ctx context.Context, localDB localdb.LocalDB, cli *config.CLI, seg localdb.Segment) error { 51 if time.Since(seg.StartTime) < moderationRetention { 52 log.Debug(ctx, "Skipping deletion of segment", "id", seg.ID, "time since start", time.Since(seg.StartTime)) 53 return nil ··· 61 if err != nil && !errors.Is(err, os.ErrNotExist) { 62 return err 63 } 64 + err = localDB.DeleteSegment(ctx, seg.ID) 65 if err != nil { 66 return err 67 }
+18
pkg/streamplace/badgedefs.go
···
··· 1 + // Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT. 2 + 3 + // Lexicon schema: place.stream.badge.defs 4 + 5 + package streamplace 6 + 7 + // BadgeDefs_BadgeView is a "badgeView" in the place.stream.badge.defs schema. 8 + // 9 + // View of a badge record, with fields resolved for display. If the DID in issuer is not the current streamplace node, the signature field shall be required. 10 + type BadgeDefs_BadgeView struct { 11 + BadgeType string `json:"badgeType" cborgen:"badgeType"` 12 + // issuer: DID of the badge issuer. 13 + Issuer string `json:"issuer" cborgen:"issuer"` 14 + // recipient: DID of the badge recipient. 15 + Recipient string `json:"recipient" cborgen:"recipient"` 16 + // signature: TODO: Cryptographic signature of the badge (of a place.stream.key). 17 + Signature *string `json:"signature,omitempty" cborgen:"signature,omitempty"` 18 + }
+28
pkg/streamplace/badgedisplay.go
···
··· 1 + // Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT. 2 + 3 + // Lexicon schema: place.stream.badge.display 4 + 5 + package streamplace 6 + 7 + import ( 8 + lexutil "github.com/bluesky-social/indigo/lex/util" 9 + ) 10 + 11 + func init() { 12 + lexutil.RegisterType("place.stream.badge.display", &BadgeDisplay{}) 13 + } 14 + 15 + type BadgeDisplay struct { 16 + LexiconTypeID string `json:"$type" cborgen:"$type,const=place.stream.badge.display"` 17 + // badges: Up to 3 badge tokens to display with the message. First badge is server-controlled, remaining badges are user-settable. 18 + Badges []*BadgeDisplay_BadgeSelection `json:"badges" cborgen:"badges"` 19 + } 20 + 21 + // BadgeDisplay_BadgeSelection is a "badgeSelection" in the place.stream.badge.display schema. 22 + // 23 + // A badge selected for display. May be a full badgeView from the server, or a token representing a badge type that the client can look up for display info. 24 + type BadgeDisplay_BadgeSelection struct { 25 + BadgeType string `json:"badgeType" cborgen:"badgeType"` 26 + // issuance: URI of the badge issuance record (place.stream.badge.issuance) that represents this badge. Required if badgeType is not recognized. 27 + Issuance *string `json:"issuance,omitempty" cborgen:"issuance,omitempty"` 28 + }
+22
pkg/streamplace/badgeissuance.go
···
··· 1 + // Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT. 2 + 3 + // Lexicon schema: place.stream.badge.issuance 4 + 5 + package streamplace 6 + 7 + import ( 8 + lexutil "github.com/bluesky-social/indigo/lex/util" 9 + ) 10 + 11 + func init() { 12 + lexutil.RegisterType("place.stream.badge.issuance", &BadgeIssuance{}) 13 + } 14 + 15 + type BadgeIssuance struct { 16 + LexiconTypeID string `json:"$type" cborgen:"$type,const=place.stream.badge.issuance"` 17 + BadgeType string `json:"badgeType" cborgen:"badgeType"` 18 + // recipient: DID of the badge recipient. 19 + Recipient string `json:"recipient" cborgen:"recipient"` 20 + // signature: TODO: Cryptographic signature of the badge (of a place.stream.key). 21 + Signature string `json:"signature" cborgen:"signature"` 22 + }
+764
pkg/streamplace/cbor_gen.go
··· 5526 5527 return nil 5528 } 5529 func (t *LiveRecommendations) MarshalCBOR(w io.Writer) error { 5530 if t == nil { 5531 _, err := w.Write(cbg.CborNull) ··· 5729 5730 return nil 5731 }
··· 5526 5527 return nil 5528 } 5529 + func (t *LiveTeleport) MarshalCBOR(w io.Writer) error { 5530 + if t == nil { 5531 + _, err := w.Write(cbg.CborNull) 5532 + return err 5533 + } 5534 + 5535 + cw := cbg.NewCborWriter(w) 5536 + fieldCount := 4 5537 + 5538 + if t.DurationSeconds == nil { 5539 + fieldCount-- 5540 + } 5541 + 5542 + if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { 5543 + return err 5544 + } 5545 + 5546 + // t.LexiconTypeID (string) (string) 5547 + if len("$type") > 1000000 { 5548 + return xerrors.Errorf("Value in field \"$type\" was too long") 5549 + } 5550 + 5551 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { 5552 + return err 5553 + } 5554 + if _, err := cw.WriteString(string("$type")); err != nil { 5555 + return err 5556 + } 5557 + 5558 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("place.stream.live.teleport"))); err != nil { 5559 + return err 5560 + } 5561 + if _, err := cw.WriteString(string("place.stream.live.teleport")); err != nil { 5562 + return err 5563 + } 5564 + 5565 + // t.StartsAt (string) (string) 5566 + if len("startsAt") > 1000000 { 5567 + return xerrors.Errorf("Value in field \"startsAt\" was too long") 5568 + } 5569 + 5570 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("startsAt"))); err != nil { 5571 + return err 5572 + } 5573 + if _, err := cw.WriteString(string("startsAt")); err != nil { 5574 + return err 5575 + } 5576 + 5577 + if len(t.StartsAt) > 1000000 { 5578 + return xerrors.Errorf("Value in field t.StartsAt was too long") 5579 + } 5580 + 5581 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.StartsAt))); err != nil { 5582 + return err 5583 + } 5584 + if _, err := cw.WriteString(string(t.StartsAt)); err != nil { 5585 + return err 5586 + } 5587 + 5588 + // t.Streamer (string) (string) 5589 + if len("streamer") > 1000000 { 5590 + return xerrors.Errorf("Value in field \"streamer\" was too long") 5591 + } 5592 + 5593 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("streamer"))); err != nil { 5594 + return err 5595 + } 5596 + if _, err := cw.WriteString(string("streamer")); err != nil { 5597 + return err 5598 + } 5599 + 5600 + if len(t.Streamer) > 1000000 { 5601 + return xerrors.Errorf("Value in field t.Streamer was too long") 5602 + } 5603 + 5604 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Streamer))); err != nil { 5605 + return err 5606 + } 5607 + if _, err := cw.WriteString(string(t.Streamer)); err != nil { 5608 + return err 5609 + } 5610 + 5611 + // t.DurationSeconds (int64) (int64) 5612 + if t.DurationSeconds != nil { 5613 + 5614 + if len("durationSeconds") > 1000000 { 5615 + return xerrors.Errorf("Value in field \"durationSeconds\" was too long") 5616 + } 5617 + 5618 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("durationSeconds"))); err != nil { 5619 + return err 5620 + } 5621 + if _, err := cw.WriteString(string("durationSeconds")); err != nil { 5622 + return err 5623 + } 5624 + 5625 + if t.DurationSeconds == nil { 5626 + if _, err := cw.Write(cbg.CborNull); err != nil { 5627 + return err 5628 + } 5629 + } else { 5630 + if *t.DurationSeconds >= 0 { 5631 + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(*t.DurationSeconds)); err != nil { 5632 + return err 5633 + } 5634 + } else { 5635 + if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-*t.DurationSeconds-1)); err != nil { 5636 + return err 5637 + } 5638 + } 5639 + } 5640 + 5641 + } 5642 + return nil 5643 + } 5644 + 5645 + func (t *LiveTeleport) UnmarshalCBOR(r io.Reader) (err error) { 5646 + *t = LiveTeleport{} 5647 + 5648 + cr := cbg.NewCborReader(r) 5649 + 5650 + maj, extra, err := cr.ReadHeader() 5651 + if err != nil { 5652 + return err 5653 + } 5654 + defer func() { 5655 + if err == io.EOF { 5656 + err = io.ErrUnexpectedEOF 5657 + } 5658 + }() 5659 + 5660 + if maj != cbg.MajMap { 5661 + return fmt.Errorf("cbor input should be of type map") 5662 + } 5663 + 5664 + if extra > cbg.MaxLength { 5665 + return fmt.Errorf("LiveTeleport: map struct too large (%d)", extra) 5666 + } 5667 + 5668 + n := extra 5669 + 5670 + nameBuf := make([]byte, 15) 5671 + for i := uint64(0); i < n; i++ { 5672 + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) 5673 + if err != nil { 5674 + return err 5675 + } 5676 + 5677 + if !ok { 5678 + // Field doesn't exist on this type, so ignore it 5679 + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { 5680 + return err 5681 + } 5682 + continue 5683 + } 5684 + 5685 + switch string(nameBuf[:nameLen]) { 5686 + // t.LexiconTypeID (string) (string) 5687 + case "$type": 5688 + 5689 + { 5690 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 5691 + if err != nil { 5692 + return err 5693 + } 5694 + 5695 + t.LexiconTypeID = string(sval) 5696 + } 5697 + // t.StartsAt (string) (string) 5698 + case "startsAt": 5699 + 5700 + { 5701 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 5702 + if err != nil { 5703 + return err 5704 + } 5705 + 5706 + t.StartsAt = string(sval) 5707 + } 5708 + // t.Streamer (string) (string) 5709 + case "streamer": 5710 + 5711 + { 5712 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 5713 + if err != nil { 5714 + return err 5715 + } 5716 + 5717 + t.Streamer = string(sval) 5718 + } 5719 + // t.DurationSeconds (int64) (int64) 5720 + case "durationSeconds": 5721 + { 5722 + 5723 + b, err := cr.ReadByte() 5724 + if err != nil { 5725 + return err 5726 + } 5727 + if b != cbg.CborNull[0] { 5728 + if err := cr.UnreadByte(); err != nil { 5729 + return err 5730 + } 5731 + maj, extra, err := cr.ReadHeader() 5732 + if err != nil { 5733 + return err 5734 + } 5735 + var extraI int64 5736 + switch maj { 5737 + case cbg.MajUnsignedInt: 5738 + extraI = int64(extra) 5739 + if extraI < 0 { 5740 + return fmt.Errorf("int64 positive overflow") 5741 + } 5742 + case cbg.MajNegativeInt: 5743 + extraI = int64(extra) 5744 + if extraI < 0 { 5745 + return fmt.Errorf("int64 negative overflow") 5746 + } 5747 + extraI = -1 - extraI 5748 + default: 5749 + return fmt.Errorf("wrong type for int64 field: %d", maj) 5750 + } 5751 + 5752 + t.DurationSeconds = (*int64)(&extraI) 5753 + } 5754 + } 5755 + 5756 + default: 5757 + // Field doesn't exist on this type, so ignore it 5758 + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { 5759 + return err 5760 + } 5761 + } 5762 + } 5763 + 5764 + return nil 5765 + } 5766 func (t *LiveRecommendations) MarshalCBOR(w io.Writer) error { 5767 if t == nil { 5768 _, err := w.Write(cbg.CborNull) ··· 5966 5967 return nil 5968 } 5969 + func (t *BadgeIssuance) MarshalCBOR(w io.Writer) error { 5970 + if t == nil { 5971 + _, err := w.Write(cbg.CborNull) 5972 + return err 5973 + } 5974 + 5975 + cw := cbg.NewCborWriter(w) 5976 + 5977 + if _, err := cw.Write([]byte{164}); err != nil { 5978 + return err 5979 + } 5980 + 5981 + // t.LexiconTypeID (string) (string) 5982 + if len("$type") > 1000000 { 5983 + return xerrors.Errorf("Value in field \"$type\" was too long") 5984 + } 5985 + 5986 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { 5987 + return err 5988 + } 5989 + if _, err := cw.WriteString(string("$type")); err != nil { 5990 + return err 5991 + } 5992 + 5993 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("place.stream.badge.issuance"))); err != nil { 5994 + return err 5995 + } 5996 + if _, err := cw.WriteString(string("place.stream.badge.issuance")); err != nil { 5997 + return err 5998 + } 5999 + 6000 + // t.BadgeType (string) (string) 6001 + if len("badgeType") > 1000000 { 6002 + return xerrors.Errorf("Value in field \"badgeType\" was too long") 6003 + } 6004 + 6005 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("badgeType"))); err != nil { 6006 + return err 6007 + } 6008 + if _, err := cw.WriteString(string("badgeType")); err != nil { 6009 + return err 6010 + } 6011 + 6012 + if len(t.BadgeType) > 1000000 { 6013 + return xerrors.Errorf("Value in field t.BadgeType was too long") 6014 + } 6015 + 6016 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.BadgeType))); err != nil { 6017 + return err 6018 + } 6019 + if _, err := cw.WriteString(string(t.BadgeType)); err != nil { 6020 + return err 6021 + } 6022 + 6023 + // t.Recipient (string) (string) 6024 + if len("recipient") > 1000000 { 6025 + return xerrors.Errorf("Value in field \"recipient\" was too long") 6026 + } 6027 + 6028 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("recipient"))); err != nil { 6029 + return err 6030 + } 6031 + if _, err := cw.WriteString(string("recipient")); err != nil { 6032 + return err 6033 + } 6034 + 6035 + if len(t.Recipient) > 1000000 { 6036 + return xerrors.Errorf("Value in field t.Recipient was too long") 6037 + } 6038 + 6039 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Recipient))); err != nil { 6040 + return err 6041 + } 6042 + if _, err := cw.WriteString(string(t.Recipient)); err != nil { 6043 + return err 6044 + } 6045 + 6046 + // t.Signature (string) (string) 6047 + if len("signature") > 1000000 { 6048 + return xerrors.Errorf("Value in field \"signature\" was too long") 6049 + } 6050 + 6051 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("signature"))); err != nil { 6052 + return err 6053 + } 6054 + if _, err := cw.WriteString(string("signature")); err != nil { 6055 + return err 6056 + } 6057 + 6058 + if len(t.Signature) > 1000000 { 6059 + return xerrors.Errorf("Value in field t.Signature was too long") 6060 + } 6061 + 6062 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Signature))); err != nil { 6063 + return err 6064 + } 6065 + if _, err := cw.WriteString(string(t.Signature)); err != nil { 6066 + return err 6067 + } 6068 + return nil 6069 + } 6070 + 6071 + func (t *BadgeIssuance) UnmarshalCBOR(r io.Reader) (err error) { 6072 + *t = BadgeIssuance{} 6073 + 6074 + cr := cbg.NewCborReader(r) 6075 + 6076 + maj, extra, err := cr.ReadHeader() 6077 + if err != nil { 6078 + return err 6079 + } 6080 + defer func() { 6081 + if err == io.EOF { 6082 + err = io.ErrUnexpectedEOF 6083 + } 6084 + }() 6085 + 6086 + if maj != cbg.MajMap { 6087 + return fmt.Errorf("cbor input should be of type map") 6088 + } 6089 + 6090 + if extra > cbg.MaxLength { 6091 + return fmt.Errorf("BadgeIssuance: map struct too large (%d)", extra) 6092 + } 6093 + 6094 + n := extra 6095 + 6096 + nameBuf := make([]byte, 9) 6097 + for i := uint64(0); i < n; i++ { 6098 + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) 6099 + if err != nil { 6100 + return err 6101 + } 6102 + 6103 + if !ok { 6104 + // Field doesn't exist on this type, so ignore it 6105 + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { 6106 + return err 6107 + } 6108 + continue 6109 + } 6110 + 6111 + switch string(nameBuf[:nameLen]) { 6112 + // t.LexiconTypeID (string) (string) 6113 + case "$type": 6114 + 6115 + { 6116 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 6117 + if err != nil { 6118 + return err 6119 + } 6120 + 6121 + t.LexiconTypeID = string(sval) 6122 + } 6123 + // t.BadgeType (string) (string) 6124 + case "badgeType": 6125 + 6126 + { 6127 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 6128 + if err != nil { 6129 + return err 6130 + } 6131 + 6132 + t.BadgeType = string(sval) 6133 + } 6134 + // t.Recipient (string) (string) 6135 + case "recipient": 6136 + 6137 + { 6138 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 6139 + if err != nil { 6140 + return err 6141 + } 6142 + 6143 + t.Recipient = string(sval) 6144 + } 6145 + // t.Signature (string) (string) 6146 + case "signature": 6147 + 6148 + { 6149 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 6150 + if err != nil { 6151 + return err 6152 + } 6153 + 6154 + t.Signature = string(sval) 6155 + } 6156 + 6157 + default: 6158 + // Field doesn't exist on this type, so ignore it 6159 + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { 6160 + return err 6161 + } 6162 + } 6163 + } 6164 + 6165 + return nil 6166 + } 6167 + func (t *BadgeDisplay) MarshalCBOR(w io.Writer) error { 6168 + if t == nil { 6169 + _, err := w.Write(cbg.CborNull) 6170 + return err 6171 + } 6172 + 6173 + cw := cbg.NewCborWriter(w) 6174 + 6175 + if _, err := cw.Write([]byte{162}); err != nil { 6176 + return err 6177 + } 6178 + 6179 + // t.LexiconTypeID (string) (string) 6180 + if len("$type") > 1000000 { 6181 + return xerrors.Errorf("Value in field \"$type\" was too long") 6182 + } 6183 + 6184 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { 6185 + return err 6186 + } 6187 + if _, err := cw.WriteString(string("$type")); err != nil { 6188 + return err 6189 + } 6190 + 6191 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("place.stream.badge.display"))); err != nil { 6192 + return err 6193 + } 6194 + if _, err := cw.WriteString(string("place.stream.badge.display")); err != nil { 6195 + return err 6196 + } 6197 + 6198 + // t.Badges ([]*streamplace.BadgeDisplay_BadgeSelection) (slice) 6199 + if len("badges") > 1000000 { 6200 + return xerrors.Errorf("Value in field \"badges\" was too long") 6201 + } 6202 + 6203 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("badges"))); err != nil { 6204 + return err 6205 + } 6206 + if _, err := cw.WriteString(string("badges")); err != nil { 6207 + return err 6208 + } 6209 + 6210 + if len(t.Badges) > 8192 { 6211 + return xerrors.Errorf("Slice value in field t.Badges was too long") 6212 + } 6213 + 6214 + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Badges))); err != nil { 6215 + return err 6216 + } 6217 + for _, v := range t.Badges { 6218 + if err := v.MarshalCBOR(cw); err != nil { 6219 + return err 6220 + } 6221 + 6222 + } 6223 + return nil 6224 + } 6225 + 6226 + func (t *BadgeDisplay) UnmarshalCBOR(r io.Reader) (err error) { 6227 + *t = BadgeDisplay{} 6228 + 6229 + cr := cbg.NewCborReader(r) 6230 + 6231 + maj, extra, err := cr.ReadHeader() 6232 + if err != nil { 6233 + return err 6234 + } 6235 + defer func() { 6236 + if err == io.EOF { 6237 + err = io.ErrUnexpectedEOF 6238 + } 6239 + }() 6240 + 6241 + if maj != cbg.MajMap { 6242 + return fmt.Errorf("cbor input should be of type map") 6243 + } 6244 + 6245 + if extra > cbg.MaxLength { 6246 + return fmt.Errorf("BadgeDisplay: map struct too large (%d)", extra) 6247 + } 6248 + 6249 + n := extra 6250 + 6251 + nameBuf := make([]byte, 6) 6252 + for i := uint64(0); i < n; i++ { 6253 + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) 6254 + if err != nil { 6255 + return err 6256 + } 6257 + 6258 + if !ok { 6259 + // Field doesn't exist on this type, so ignore it 6260 + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { 6261 + return err 6262 + } 6263 + continue 6264 + } 6265 + 6266 + switch string(nameBuf[:nameLen]) { 6267 + // t.LexiconTypeID (string) (string) 6268 + case "$type": 6269 + 6270 + { 6271 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 6272 + if err != nil { 6273 + return err 6274 + } 6275 + 6276 + t.LexiconTypeID = string(sval) 6277 + } 6278 + // t.Badges ([]*streamplace.BadgeDisplay_BadgeSelection) (slice) 6279 + case "badges": 6280 + 6281 + maj, extra, err = cr.ReadHeader() 6282 + if err != nil { 6283 + return err 6284 + } 6285 + 6286 + if extra > 8192 { 6287 + return fmt.Errorf("t.Badges: array too large (%d)", extra) 6288 + } 6289 + 6290 + if maj != cbg.MajArray { 6291 + return fmt.Errorf("expected cbor array") 6292 + } 6293 + 6294 + if extra > 0 { 6295 + t.Badges = make([]*BadgeDisplay_BadgeSelection, extra) 6296 + } 6297 + 6298 + for i := 0; i < int(extra); i++ { 6299 + { 6300 + var maj byte 6301 + var extra uint64 6302 + var err error 6303 + _ = maj 6304 + _ = extra 6305 + _ = err 6306 + 6307 + { 6308 + 6309 + b, err := cr.ReadByte() 6310 + if err != nil { 6311 + return err 6312 + } 6313 + if b != cbg.CborNull[0] { 6314 + if err := cr.UnreadByte(); err != nil { 6315 + return err 6316 + } 6317 + t.Badges[i] = new(BadgeDisplay_BadgeSelection) 6318 + if err := t.Badges[i].UnmarshalCBOR(cr); err != nil { 6319 + return xerrors.Errorf("unmarshaling t.Badges[i] pointer: %w", err) 6320 + } 6321 + } 6322 + 6323 + } 6324 + 6325 + } 6326 + } 6327 + 6328 + default: 6329 + // Field doesn't exist on this type, so ignore it 6330 + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { 6331 + return err 6332 + } 6333 + } 6334 + } 6335 + 6336 + return nil 6337 + } 6338 + func (t *BadgeDisplay_BadgeSelection) MarshalCBOR(w io.Writer) error { 6339 + if t == nil { 6340 + _, err := w.Write(cbg.CborNull) 6341 + return err 6342 + } 6343 + 6344 + cw := cbg.NewCborWriter(w) 6345 + fieldCount := 2 6346 + 6347 + if t.Issuance == nil { 6348 + fieldCount-- 6349 + } 6350 + 6351 + if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { 6352 + return err 6353 + } 6354 + 6355 + // t.Issuance (string) (string) 6356 + if t.Issuance != nil { 6357 + 6358 + if len("issuance") > 1000000 { 6359 + return xerrors.Errorf("Value in field \"issuance\" was too long") 6360 + } 6361 + 6362 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("issuance"))); err != nil { 6363 + return err 6364 + } 6365 + if _, err := cw.WriteString(string("issuance")); err != nil { 6366 + return err 6367 + } 6368 + 6369 + if t.Issuance == nil { 6370 + if _, err := cw.Write(cbg.CborNull); err != nil { 6371 + return err 6372 + } 6373 + } else { 6374 + if len(*t.Issuance) > 1000000 { 6375 + return xerrors.Errorf("Value in field t.Issuance was too long") 6376 + } 6377 + 6378 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Issuance))); err != nil { 6379 + return err 6380 + } 6381 + if _, err := cw.WriteString(string(*t.Issuance)); err != nil { 6382 + return err 6383 + } 6384 + } 6385 + } 6386 + 6387 + // t.BadgeType (string) (string) 6388 + if len("badgeType") > 1000000 { 6389 + return xerrors.Errorf("Value in field \"badgeType\" was too long") 6390 + } 6391 + 6392 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("badgeType"))); err != nil { 6393 + return err 6394 + } 6395 + if _, err := cw.WriteString(string("badgeType")); err != nil { 6396 + return err 6397 + } 6398 + 6399 + if len(t.BadgeType) > 1000000 { 6400 + return xerrors.Errorf("Value in field t.BadgeType was too long") 6401 + } 6402 + 6403 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.BadgeType))); err != nil { 6404 + return err 6405 + } 6406 + if _, err := cw.WriteString(string(t.BadgeType)); err != nil { 6407 + return err 6408 + } 6409 + return nil 6410 + } 6411 + 6412 + func (t *BadgeDisplay_BadgeSelection) UnmarshalCBOR(r io.Reader) (err error) { 6413 + *t = BadgeDisplay_BadgeSelection{} 6414 + 6415 + cr := cbg.NewCborReader(r) 6416 + 6417 + maj, extra, err := cr.ReadHeader() 6418 + if err != nil { 6419 + return err 6420 + } 6421 + defer func() { 6422 + if err == io.EOF { 6423 + err = io.ErrUnexpectedEOF 6424 + } 6425 + }() 6426 + 6427 + if maj != cbg.MajMap { 6428 + return fmt.Errorf("cbor input should be of type map") 6429 + } 6430 + 6431 + if extra > cbg.MaxLength { 6432 + return fmt.Errorf("BadgeDisplay_BadgeSelection: map struct too large (%d)", extra) 6433 + } 6434 + 6435 + n := extra 6436 + 6437 + nameBuf := make([]byte, 9) 6438 + for i := uint64(0); i < n; i++ { 6439 + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) 6440 + if err != nil { 6441 + return err 6442 + } 6443 + 6444 + if !ok { 6445 + // Field doesn't exist on this type, so ignore it 6446 + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { 6447 + return err 6448 + } 6449 + continue 6450 + } 6451 + 6452 + switch string(nameBuf[:nameLen]) { 6453 + // t.Issuance (string) (string) 6454 + case "issuance": 6455 + 6456 + { 6457 + b, err := cr.ReadByte() 6458 + if err != nil { 6459 + return err 6460 + } 6461 + if b != cbg.CborNull[0] { 6462 + if err := cr.UnreadByte(); err != nil { 6463 + return err 6464 + } 6465 + 6466 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 6467 + if err != nil { 6468 + return err 6469 + } 6470 + 6471 + t.Issuance = (*string)(&sval) 6472 + } 6473 + } 6474 + // t.BadgeType (string) (string) 6475 + case "badgeType": 6476 + 6477 + { 6478 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 6479 + if err != nil { 6480 + return err 6481 + } 6482 + 6483 + t.BadgeType = string(sval) 6484 + } 6485 + 6486 + default: 6487 + // Field doesn't exist on this type, so ignore it 6488 + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { 6489 + return err 6490 + } 6491 + } 6492 + } 6493 + 6494 + return nil 6495 + }
+4 -2
pkg/streamplace/chatdefs.go
··· 16 type ChatDefs_MessageView struct { 17 LexiconTypeID string `json:"$type" cborgen:"$type,const=place.stream.chat.defs#messageView"` 18 Author *appbsky.ActorDefs_ProfileViewBasic `json:"author" cborgen:"author"` 19 - ChatProfile *ChatProfile `json:"chatProfile,omitempty" cborgen:"chatProfile,omitempty"` 20 - Cid string `json:"cid" cborgen:"cid"` 21 // deleted: If true, this message has been deleted or labeled and should be cleared from the cache 22 Deleted *bool `json:"deleted,omitempty" cborgen:"deleted,omitempty"` 23 IndexedAt string `json:"indexedAt" cborgen:"indexedAt"`
··· 16 type ChatDefs_MessageView struct { 17 LexiconTypeID string `json:"$type" cborgen:"$type,const=place.stream.chat.defs#messageView"` 18 Author *appbsky.ActorDefs_ProfileViewBasic `json:"author" cborgen:"author"` 19 + // badges: Up to 3 badge tokens to display with the message. First badge is server-controlled, remaining badges are user-settable. Tokens are looked up in badges.json for display info. 20 + Badges []*BadgeDefs_BadgeView `json:"badges,omitempty" cborgen:"badges,omitempty"` 21 + ChatProfile *ChatProfile `json:"chatProfile,omitempty" cborgen:"chatProfile,omitempty"` 22 + Cid string `json:"cid" cborgen:"cid"` 23 // deleted: If true, this message has been deleted or labeled and should be cleared from the cache 24 Deleted *bool `json:"deleted,omitempty" cborgen:"deleted,omitempty"` 25 IndexedAt string `json:"indexedAt" cborgen:"indexedAt"`
+33
pkg/streamplace/livedenyTeleport.go
···
··· 1 + // Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT. 2 + 3 + // Lexicon schema: place.stream.live.denyTeleport 4 + 5 + package streamplace 6 + 7 + import ( 8 + "context" 9 + 10 + lexutil "github.com/bluesky-social/indigo/lex/util" 11 + ) 12 + 13 + // LiveDenyTeleport_Input is the input argument to a place.stream.live.denyTeleport call. 14 + type LiveDenyTeleport_Input struct { 15 + // uri: The URI of the teleport record to deny. 16 + Uri string `json:"uri" cborgen:"uri"` 17 + } 18 + 19 + // LiveDenyTeleport_Output is the output of a place.stream.live.denyTeleport call. 20 + type LiveDenyTeleport_Output struct { 21 + // success: Whether the teleport was successfully denied. 22 + Success bool `json:"success" cborgen:"success"` 23 + } 24 + 25 + // LiveDenyTeleport calls the XRPC method "place.stream.live.denyTeleport". 26 + func LiveDenyTeleport(ctx context.Context, c lexutil.LexClient, input *LiveDenyTeleport_Input) (*LiveDenyTeleport_Output, error) { 27 + var out LiveDenyTeleport_Output 28 + if err := c.LexDo(ctx, lexutil.Procedure, "application/json", "place.stream.live.denyTeleport", nil, input, &out); err != nil { 29 + return nil, err 30 + } 31 + 32 + return &out, nil 33 + }
+23
pkg/streamplace/liveteleport.go
···
··· 1 + // Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT. 2 + 3 + // Lexicon schema: place.stream.live.teleport 4 + 5 + package streamplace 6 + 7 + import ( 8 + lexutil "github.com/bluesky-social/indigo/lex/util" 9 + ) 10 + 11 + func init() { 12 + lexutil.RegisterType("place.stream.live.teleport", &LiveTeleport{}) 13 + } 14 + 15 + type LiveTeleport struct { 16 + LexiconTypeID string `json:"$type" cborgen:"$type,const=place.stream.live.teleport"` 17 + // durationSeconds: The time limit in seconds for the teleport. If not set, the teleport is permanent. Must be at least 60 seconds, and no more than 32,400 seconds (9 hours). 18 + DurationSeconds *int64 `json:"durationSeconds,omitempty" cborgen:"durationSeconds,omitempty"` 19 + // startsAt: The time the teleport becomes active. 20 + StartsAt string `json:"startsAt" cborgen:"startsAt"` 21 + // streamer: The DID of the streamer to teleport to. 22 + Streamer string `json:"streamer" cborgen:"streamer"` 23 + }
+46 -6
pkg/streamplace/streamlivestream.go
··· 59 } 60 61 type Livestream_StreamplaceAnything_Livestream struct { 62 - Livestream_LivestreamView *Livestream_LivestreamView 63 - Livestream_ViewerCount *Livestream_ViewerCount 64 - Defs_BlockView *Defs_BlockView 65 - Defs_Renditions *Defs_Renditions 66 - Defs_Rendition *Defs_Rendition 67 - ChatDefs_MessageView *ChatDefs_MessageView 68 } 69 70 func (t *Livestream_StreamplaceAnything_Livestream) MarshalJSON() ([]byte, error) { ··· 75 if t.Livestream_ViewerCount != nil { 76 t.Livestream_ViewerCount.LexiconTypeID = "place.stream.livestream#viewerCount" 77 return json.Marshal(t.Livestream_ViewerCount) 78 } 79 if t.Defs_BlockView != nil { 80 t.Defs_BlockView.LexiconTypeID = "place.stream.defs#blockView" ··· 108 case "place.stream.livestream#viewerCount": 109 t.Livestream_ViewerCount = new(Livestream_ViewerCount) 110 return json.Unmarshal(b, t.Livestream_ViewerCount) 111 case "place.stream.defs#blockView": 112 t.Defs_BlockView = new(Defs_BlockView) 113 return json.Unmarshal(b, t.Defs_BlockView) ··· 123 default: 124 return nil 125 } 126 } 127 128 // Livestream_ViewerCount is a "viewerCount" in the place.stream.livestream schema.
··· 59 } 60 61 type Livestream_StreamplaceAnything_Livestream struct { 62 + Livestream_LivestreamView *Livestream_LivestreamView 63 + Livestream_ViewerCount *Livestream_ViewerCount 64 + Livestream_TeleportArrival *Livestream_TeleportArrival 65 + Livestream_TeleportCanceled *Livestream_TeleportCanceled 66 + Defs_BlockView *Defs_BlockView 67 + Defs_Renditions *Defs_Renditions 68 + Defs_Rendition *Defs_Rendition 69 + ChatDefs_MessageView *ChatDefs_MessageView 70 } 71 72 func (t *Livestream_StreamplaceAnything_Livestream) MarshalJSON() ([]byte, error) { ··· 77 if t.Livestream_ViewerCount != nil { 78 t.Livestream_ViewerCount.LexiconTypeID = "place.stream.livestream#viewerCount" 79 return json.Marshal(t.Livestream_ViewerCount) 80 + } 81 + if t.Livestream_TeleportArrival != nil { 82 + t.Livestream_TeleportArrival.LexiconTypeID = "place.stream.livestream#teleportArrival" 83 + return json.Marshal(t.Livestream_TeleportArrival) 84 + } 85 + if t.Livestream_TeleportCanceled != nil { 86 + t.Livestream_TeleportCanceled.LexiconTypeID = "place.stream.livestream#teleportCanceled" 87 + return json.Marshal(t.Livestream_TeleportCanceled) 88 } 89 if t.Defs_BlockView != nil { 90 t.Defs_BlockView.LexiconTypeID = "place.stream.defs#blockView" ··· 118 case "place.stream.livestream#viewerCount": 119 t.Livestream_ViewerCount = new(Livestream_ViewerCount) 120 return json.Unmarshal(b, t.Livestream_ViewerCount) 121 + case "place.stream.livestream#teleportArrival": 122 + t.Livestream_TeleportArrival = new(Livestream_TeleportArrival) 123 + return json.Unmarshal(b, t.Livestream_TeleportArrival) 124 + case "place.stream.livestream#teleportCanceled": 125 + t.Livestream_TeleportCanceled = new(Livestream_TeleportCanceled) 126 + return json.Unmarshal(b, t.Livestream_TeleportCanceled) 127 case "place.stream.defs#blockView": 128 t.Defs_BlockView = new(Defs_BlockView) 129 return json.Unmarshal(b, t.Defs_BlockView) ··· 139 default: 140 return nil 141 } 142 + } 143 + 144 + // Livestream_TeleportArrival is a "teleportArrival" in the place.stream.livestream schema. 145 + type Livestream_TeleportArrival struct { 146 + LexiconTypeID string `json:"$type" cborgen:"$type,const=place.stream.livestream#teleportArrival"` 147 + // chatProfile: The chat profile of the source streamer 148 + ChatProfile *ChatProfile `json:"chatProfile,omitempty" cborgen:"chatProfile,omitempty"` 149 + // source: The streamer who is teleporting their viewers here 150 + Source *appbsky.ActorDefs_ProfileViewBasic `json:"source" cborgen:"source"` 151 + // startsAt: When this teleport started 152 + StartsAt string `json:"startsAt" cborgen:"startsAt"` 153 + // teleportUri: The URI of the teleport record 154 + TeleportUri string `json:"teleportUri" cborgen:"teleportUri"` 155 + // viewerCount: How many viewers are arriving from this teleport 156 + ViewerCount int64 `json:"viewerCount" cborgen:"viewerCount"` 157 + } 158 + 159 + // Livestream_TeleportCanceled is a "teleportCanceled" in the place.stream.livestream schema. 160 + type Livestream_TeleportCanceled struct { 161 + LexiconTypeID string `json:"$type" cborgen:"$type,const=place.stream.livestream#teleportCanceled"` 162 + // reason: Why this teleport was canceled 163 + Reason string `json:"reason" cborgen:"reason"` 164 + // teleportUri: The URI of the teleport record that was canceled 165 + TeleportUri string `json:"teleportUri" cborgen:"teleportUri"` 166 } 167 168 // Livestream_ViewerCount is a "viewerCount" in the place.stream.livestream schema.
+1503 -1611
pnpm-lock.yaml
··· 4 autoInstallPeers: true 5 excludeLinksFromLockfile: false 6 7 - overrides: 8 - '@types/react': 19.0.0 9 - '@types/react-dom': 19.0.0 10 - react: 19.0.0 11 - react-dom: 19.0.0 12 - 13 importers: 14 15 .: ··· 77 version: 0.3.31 78 '@bacons/text-decoder': 79 specifier: ^0.0.0 80 - version: 0.0.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 81 '@emoji-mart/react': 82 specifier: ^1.1.1 83 version: 1.1.1(emoji-mart@5.6.0)(react@19.0.0) ··· 92 version: 0.15.2(@fluent/bundle@0.19.1)(react@19.0.0) 93 '@react-native-firebase/app': 94 specifier: ^22.2.1 95 - version: 22.2.1(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 96 '@react-native-firebase/messaging': 97 specifier: ^22.2.1 98 - version: 22.2.1(a0b2fe09fd8d447d016daffd4232dc3c) 99 '@react-navigation/bottom-tabs': 100 specifier: ^6.6.1 101 - version: 6.6.1(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 102 '@react-navigation/drawer': 103 specifier: ^6.7.2 104 - version: 6.7.2(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 105 '@react-navigation/native': 106 specifier: ^6.1.18 107 - version: 6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 108 '@react-navigation/native-stack': 109 specifier: ^6.11.0 110 - version: 6.11.0(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 111 '@sentry/react-native': 112 specifier: ^6.14.0 113 - version: 6.14.0(encoding@0.1.13)(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 114 '@streamplace/atproto-oauth-client-react-native': 115 specifier: workspace:* 116 version: link:../atproto-oauth-client-react-native ··· 131 version: 1.7.6 132 babel-preset-expo: 133 specifier: ~13.0.0 134 - version: 13.0.0(@babel/core@7.28.6) 135 buffer: 136 specifier: ^6.0.3 137 version: 6.0.3 138 burnt: 139 specifier: ^0.12.2 140 - version: 0.12.2(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 141 chrono-node: 142 specifier: 2.7.7 143 version: 2.7.7 ··· 152 version: 6.0.2 153 expo: 154 specifier: ~53.0.11 155 - version: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 156 expo-build-properties: 157 specifier: ~0.14.6 158 - version: 0.14.6(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 159 expo-dev-client: 160 specifier: ~5.2.0 161 - version: 5.2.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 162 expo-file-system: 163 specifier: ~18.1.10 164 - version: 18.1.10(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 165 expo-font: 166 specifier: ~13.3.1 167 - version: 13.3.1(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 168 expo-keep-awake: 169 specifier: ~14.1.4 170 - version: 14.1.4(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 171 expo-linking: 172 specifier: ~7.1.5 173 - version: 7.1.5(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 174 expo-localization: 175 specifier: ^17.0.7 176 - version: 17.0.7(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 177 expo-notifications: 178 specifier: ~0.31.3 179 - version: 0.31.3(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 180 expo-screen-orientation: 181 specifier: ^9.0.7 182 - version: 9.0.7(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 183 expo-splash-screen: 184 specifier: ~0.30.9 185 - version: 0.30.9(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 186 expo-sqlite: 187 specifier: ~15.2.12 188 - version: 15.2.12(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 189 expo-system-ui: 190 specifier: ~5.0.8 191 - version: 5.0.8(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 192 expo-updates: 193 specifier: ~0.28.14 194 - version: 0.28.14(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 195 expo-video: 196 specifier: ~2.2.1 197 - version: 2.2.1(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 198 expo-web-browser: 199 specifier: ^14.1.6 200 - version: 14.1.6(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 201 hls.js: 202 specifier: ^1.5.17 203 version: 1.5.17 ··· 224 version: 5.9.6 225 lucide-react-native: 226 specifier: ^0.514.0 227 - version: 0.514.0(react-native-svg@15.12.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 228 multiformats: 229 specifier: ^13.3.1 230 version: 13.3.1 ··· 242 version: 19.0.0(react@19.0.0) 243 react-i18next: 244 specifier: ^15.7.3 245 - version: 15.7.4(i18next@25.5.2(typescript@5.3.3))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(typescript@5.3.3) 246 react-native: 247 specifier: 0.79.3 248 - version: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 249 react-native-draggable-flatlist: 250 specifier: ^4.0.3 251 - version: 4.0.3(@babel/core@7.28.6)(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 252 react-native-edge-to-edge: 253 specifier: ^1.6.2 254 - version: 1.6.2(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 255 react-native-gesture-handler: 256 specifier: ~2.26.0 257 - version: 2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 258 react-native-localize: 259 specifier: ^3.5.2 260 - version: 3.5.2(@expo/config-plugins@10.0.2)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 261 react-native-markdown-display: 262 specifier: ^7.0.2 263 - version: 7.0.2(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 264 react-native-quick-crypto: 265 specifier: ^0.7.14 266 - version: 0.7.14(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 267 react-native-reanimated: 268 specifier: ~3.18.0 269 - version: 3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 270 react-native-safe-area-context: 271 specifier: 5.4.1 272 - version: 5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 273 react-native-screens: 274 specifier: ~4.11.1 275 - version: 4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 276 react-native-sortables: 277 specifier: ^1.9.4 278 - version: 1.9.4(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 279 react-native-svg: 280 specifier: 15.12.0 281 - version: 15.12.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 282 react-native-web: 283 specifier: ^0.20.0 284 version: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 285 react-native-webrtc: 286 specifier: git+https://github.com/streamplace/react-native-webrtc.git#6b8472a771ac47f89217d327058a8a4124a6ae56 287 - version: https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 288 react-native-webview: 289 specifier: 13.15.0 290 - version: 13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 291 react-use-websocket: 292 specifier: ^4.13.0 293 version: 4.13.0 294 reanimated-color-picker: 295 specifier: ^4.0.0 296 - version: 4.0.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 297 rtcaudiodevice: 298 specifier: git+https://github.com/streamplace/RTCAudioDevice.git#918e08a0f6f0818fb495a0db0b696b44d11d1336 299 version: https://codeload.github.com/streamplace/RTCAudioDevice/tar.gz/918e08a0f6f0818fb495a0db0b696b44d11d1336 ··· 317 version: 2.21.44(bufferutil@4.0.8)(typescript@5.3.3)(utf-8-validate@5.0.10)(zod@3.24.4) 318 zustand: 319 specifier: ^5.0.5 320 - version: 5.0.5(@types/react@19.0.0)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.6.0(react@19.0.0)) 321 devDependencies: 322 '@babel/core': 323 specifier: ^7.26.0 324 - version: 7.28.6 325 '@babel/plugin-proposal-export-default-from': 326 specifier: ^7.25.9 327 - version: 7.25.9(@babel/core@7.28.6) 328 '@babel/plugin-syntax-export-default-from': 329 specifier: ^7.25.9 330 - version: 7.25.9(@babel/core@7.28.6) 331 '@babel/plugin-transform-flow-strip-types': 332 specifier: ^7.25.9 333 - version: 7.25.9(@babel/core@7.28.6) 334 '@babel/plugin-transform-private-methods': 335 specifier: ^7.25.9 336 - version: 7.27.1(@babel/core@7.28.6) 337 '@babel/plugin-transform-private-property-in-object': 338 specifier: ^7.25.9 339 - version: 7.27.1(@babel/core@7.28.6) 340 '@babel/plugin-transform-runtime': 341 specifier: ^7.25.9 342 - version: 7.25.9(@babel/core@7.28.6) 343 '@config-plugins/react-native-webrtc': 344 specifier: ^10.0.0 345 - version: 10.0.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 346 '@expo/metro-config': 347 specifier: ~0.19.0 348 version: 0.19.4 349 '@expo/metro-runtime': 350 specifier: ~5.0.4 351 - version: 5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 352 '@types/babel__plugin-transform-runtime': 353 specifier: ^7 354 version: 7.9.5 ··· 356 specifier: ^1 357 version: 1.5.5 358 '@types/react': 359 - specifier: 19.0.0 360 - version: 19.0.0 361 '@types/sdp-transform': 362 specifier: ^2.15.0 363 version: 2.15.0 ··· 414 version: 6.0.2 415 expo-sqlite: 416 specifier: ^15.0.3 417 - version: 15.2.12(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 418 jose: 419 specifier: ^5.2.0 420 version: 5.9.6 421 react-native-quick-crypto: 422 specifier: ^0.7.7 423 - version: 0.7.14(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 424 devDependencies: 425 '@types/node': 426 specifier: ^22.10.1 ··· 451 version: 0.15.2(@fluent/bundle@0.19.1)(react@19.0.0) 452 '@gorhom/bottom-sheet': 453 specifier: ^5.1.6 454 - version: 5.1.6(@types/react@19.0.0)(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 455 '@radix-ui/react-dropdown-menu': 456 specifier: ^2.1.16 457 - version: 2.1.16(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 458 '@rn-primitives/dropdown-menu': 459 specifier: ^1.2.0 460 - version: 1.2.0(@rn-primitives/portal@1.3.0(@types/react@19.0.0)(immer@10.1.1)(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(use-sync-external-store@1.6.0(react@19.0.0)))(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 461 '@rn-primitives/portal': 462 specifier: ^1.3.0 463 - version: 1.3.0(@types/react@19.0.0)(immer@10.1.1)(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(use-sync-external-store@1.6.0(react@19.0.0)) 464 '@rn-primitives/slider': 465 specifier: ^1.2.0 466 - version: 1.2.0(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 467 class-variance-authority: 468 specifier: ^0.6.1 469 version: 0.6.1 470 expo-keep-awake: 471 specifier: ^14.0.0 472 - version: 14.1.4(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 473 expo-localization: 474 specifier: '*' 475 - version: 17.0.7(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 476 expo-screen-orientation: 477 specifier: ^9.0.7 478 - version: 9.0.7(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 479 expo-sensors: 480 specifier: ^15.0.7 481 - version: 15.0.7(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 482 expo-sqlite: 483 specifier: ~15.2.12 484 - version: 15.2.12(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 485 expo-video: 486 specifier: ^2.0.0 487 - version: 2.2.1(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 488 hls.js: 489 specifier: ^1.5.17 490 version: 1.5.17 ··· 508 version: 2.0.1 509 lucide-react-native: 510 specifier: ^0.514.0 511 - version: 0.514.0(react-native-svg@15.12.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 512 react: 513 - specifier: 19.0.0 514 version: 19.0.0 515 react-i18next: 516 specifier: ^15.7.3 517 - version: 15.7.4(i18next@25.5.2(typescript@5.8.3))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(typescript@5.8.3) 518 react-native: 519 specifier: ^0.79.0 520 - version: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 521 react-native-edge-to-edge: 522 specifier: ^1.6.2 523 - version: 1.6.2(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 524 react-native-gesture-handler: 525 specifier: ^2.20.0 526 - version: 2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 527 react-native-reanimated: 528 specifier: ^3.0.0 529 - version: 3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 530 react-native-safe-area-context: 531 specifier: ^5.0.0 532 - version: 5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 533 react-native-svg: 534 specifier: ^15.0.0 535 - version: 15.12.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 536 react-native-webrtc: 537 specifier: git+https://github.com/streamplace/react-native-webrtc.git#6b8472a771ac47f89217d327058a8a4124a6ae56 538 - version: https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 539 react-use-websocket: 540 specifier: ^4.13.0 541 version: 4.13.0 ··· 547 version: 2.21.44(bufferutil@4.0.8)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.4) 548 zustand: 549 specifier: ^5.0.5 550 - version: 5.0.5(@types/react@19.0.0)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.6.0(react@19.0.0)) 551 devDependencies: 552 '@fluent/syntax': 553 specifier: ^0.19.0 554 version: 0.19.0 555 '@types/react-dom': 556 - specifier: 19.0.0 557 - version: 19.0.0 558 '@types/sdp-transform': 559 specifier: ^2.15.0 560 version: 2.15.0 ··· 566 version: 3.1.10 567 tsup: 568 specifier: ^8.5.0 569 - version: 8.5.0(@swc/core@1.15.4(@swc/helpers@0.5.17))(jiti@2.6.1)(postcss@8.5.3)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2) 570 571 js/config-react-native-webrtc: 572 dependencies: 573 '@config-plugins/react-native-webrtc': 574 specifier: 10.0.0 575 - version: 10.0.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 576 react-native-webrtc: 577 specifier: git+https://github.com/streamplace/react-native-webrtc.git#6b8472a771ac47f89217d327058a8a4124a6ae56 578 - version: https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 579 rtcaudiodevice: 580 specifier: git+https://github.com/streamplace/RTCAudioDevice.git#918e08a0f6f0818fb495a0db0b696b44d11d1336 581 version: https://codeload.github.com/streamplace/RTCAudioDevice/tar.gz/918e08a0f6f0818fb495a0db0b696b44d11d1336 ··· 718 dependencies: 719 '@astrojs/starlight': 720 specifier: ^0.34.1 721 - version: 0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2)) 722 '@fontsource/atkinson-hyperlegible-next': 723 specifier: ^5.2.2 724 version: 5.2.2 ··· 727 version: link:../app 728 astro: 729 specifier: ^5.6.1 730 - version: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2) 731 sharp: 732 specifier: ^0.32.5 733 version: 0.32.6 734 starlight-openapi: 735 specifier: ^0.17.0 736 - version: 0.17.0(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2)))(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2))(openapi-types@12.1.3) 737 starlight-openapi-rapidoc: 738 specifier: ^0.8.1-beta 739 - version: 0.8.1-beta(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2)))(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2))(openapi-types@12.1.3) 740 streamplace: 741 specifier: workspace:* 742 version: link:../streamplace 743 744 js/streamplace: 745 dependencies: ··· 776 '@adraffy/ens-normalize@1.11.0': 777 resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==} 778 779 '@apidevtools/openapi-schemas@2.1.0': 780 resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==} 781 engines: {node: '>=10'} ··· 1229 resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} 1230 engines: {node: '>=6.9.0'} 1231 1232 - '@babel/code-frame@7.28.6': 1233 - resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} 1234 - engines: {node: '>=6.9.0'} 1235 - 1236 '@babel/compat-data@7.26.2': 1237 resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} 1238 engines: {node: '>=6.9.0'} ··· 1241 resolution: {integrity: sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==} 1242 engines: {node: '>=6.9.0'} 1243 1244 - '@babel/compat-data@7.28.6': 1245 - resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} 1246 - engines: {node: '>=6.9.0'} 1247 - 1248 - '@babel/core@7.28.6': 1249 - resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==} 1250 engines: {node: '>=6.9.0'} 1251 1252 '@babel/generator@7.26.2': ··· 1257 resolution: {integrity: sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==} 1258 engines: {node: '>=6.9.0'} 1259 1260 - '@babel/generator@7.28.6': 1261 - resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} 1262 engines: {node: '>=6.9.0'} 1263 1264 - '@babel/helper-annotate-as-pure@7.27.3': 1265 - resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} 1266 engines: {node: '>=6.9.0'} 1267 1268 '@babel/helper-compilation-targets@7.27.2': 1269 resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} 1270 engines: {node: '>=6.9.0'} 1271 1272 - '@babel/helper-compilation-targets@7.28.6': 1273 - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} 1274 - engines: {node: '>=6.9.0'} 1275 - 1276 '@babel/helper-create-class-features-plugin@7.27.1': 1277 resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==} 1278 engines: {node: '>=6.9.0'} ··· 1290 peerDependencies: 1291 '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 1292 1293 - '@babel/helper-globals@7.28.0': 1294 - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} 1295 - engines: {node: '>=6.9.0'} 1296 - 1297 '@babel/helper-member-expression-to-functions@7.27.1': 1298 resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} 1299 engines: {node: '>=6.9.0'} ··· 1306 resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} 1307 engines: {node: '>=6.9.0'} 1308 1309 - '@babel/helper-module-imports@7.28.6': 1310 - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} 1311 - engines: {node: '>=6.9.0'} 1312 - 1313 - '@babel/helper-module-transforms@7.27.3': 1314 - resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} 1315 engines: {node: '>=6.9.0'} 1316 peerDependencies: 1317 '@babel/core': ^7.0.0 1318 1319 - '@babel/helper-module-transforms@7.28.6': 1320 - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} 1321 engines: {node: '>=6.9.0'} 1322 peerDependencies: 1323 '@babel/core': ^7.0.0 ··· 1366 resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} 1367 engines: {node: '>=6.9.0'} 1368 1369 - '@babel/helper-validator-identifier@7.28.5': 1370 - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} 1371 engines: {node: '>=6.9.0'} 1372 1373 '@babel/helper-validator-option@7.27.1': ··· 1378 resolution: {integrity: sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==} 1379 engines: {node: '>=6.9.0'} 1380 1381 - '@babel/helpers@7.28.6': 1382 - resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} 1383 engines: {node: '>=6.9.0'} 1384 1385 '@babel/highlight@7.24.7': ··· 1393 1394 '@babel/parser@7.27.3': 1395 resolution: {integrity: sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==} 1396 - engines: {node: '>=6.0.0'} 1397 - hasBin: true 1398 - 1399 - '@babel/parser@7.28.6': 1400 - resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} 1401 engines: {node: '>=6.0.0'} 1402 hasBin: true 1403 ··· 1775 resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} 1776 engines: {node: '>=6.9.0'} 1777 1778 '@babel/template@7.27.2': 1779 resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} 1780 engines: {node: '>=6.9.0'} 1781 1782 - '@babel/template@7.28.6': 1783 - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} 1784 engines: {node: '>=6.9.0'} 1785 1786 '@babel/traverse@7.27.3': 1787 resolution: {integrity: sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==} 1788 engines: {node: '>=6.9.0'} 1789 1790 - '@babel/traverse@7.28.6': 1791 - resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==} 1792 - engines: {node: '>=6.9.0'} 1793 - 1794 '@babel/types@7.26.0': 1795 resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} 1796 engines: {node: '>=6.9.0'} 1797 1798 '@babel/types@7.27.3': 1799 resolution: {integrity: sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==} 1800 - engines: {node: '>=6.9.0'} 1801 - 1802 - '@babel/types@7.28.6': 1803 - resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} 1804 engines: {node: '>=6.9.0'} 1805 1806 '@bacons/text-decoder@0.0.0': ··· 2030 resolution: {integrity: sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==} 2031 peerDependencies: 2032 emoji-mart: ^5.2 2033 - react: 19.0.0 2034 2035 '@esbuild/aix-ppc64@0.25.3': 2036 resolution: {integrity: sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==} ··· 2038 cpu: [ppc64] 2039 os: [aix] 2040 2041 - '@esbuild/aix-ppc64@0.27.2': 2042 - resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} 2043 - engines: {node: '>=18'} 2044 - cpu: [ppc64] 2045 - os: [aix] 2046 - 2047 '@esbuild/android-arm64@0.25.3': 2048 resolution: {integrity: sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==} 2049 engines: {node: '>=18'} 2050 cpu: [arm64] 2051 os: [android] 2052 2053 - '@esbuild/android-arm64@0.27.2': 2054 - resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} 2055 - engines: {node: '>=18'} 2056 - cpu: [arm64] 2057 - os: [android] 2058 - 2059 '@esbuild/android-arm@0.25.3': 2060 resolution: {integrity: sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==} 2061 engines: {node: '>=18'} 2062 cpu: [arm] 2063 os: [android] 2064 2065 - '@esbuild/android-arm@0.27.2': 2066 - resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} 2067 - engines: {node: '>=18'} 2068 - cpu: [arm] 2069 - os: [android] 2070 - 2071 '@esbuild/android-x64@0.25.3': 2072 resolution: {integrity: sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==} 2073 engines: {node: '>=18'} 2074 cpu: [x64] 2075 os: [android] 2076 2077 - '@esbuild/android-x64@0.27.2': 2078 - resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} 2079 - engines: {node: '>=18'} 2080 - cpu: [x64] 2081 - os: [android] 2082 - 2083 '@esbuild/darwin-arm64@0.25.3': 2084 resolution: {integrity: sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==} 2085 - engines: {node: '>=18'} 2086 - cpu: [arm64] 2087 - os: [darwin] 2088 - 2089 - '@esbuild/darwin-arm64@0.27.2': 2090 - resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} 2091 engines: {node: '>=18'} 2092 cpu: [arm64] 2093 os: [darwin] 2094 2095 '@esbuild/darwin-x64@0.25.3': 2096 resolution: {integrity: sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==} 2097 - engines: {node: '>=18'} 2098 - cpu: [x64] 2099 - os: [darwin] 2100 - 2101 - '@esbuild/darwin-x64@0.27.2': 2102 - resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} 2103 engines: {node: '>=18'} 2104 cpu: [x64] 2105 os: [darwin] ··· 2110 cpu: [arm64] 2111 os: [freebsd] 2112 2113 - '@esbuild/freebsd-arm64@0.27.2': 2114 - resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} 2115 - engines: {node: '>=18'} 2116 - cpu: [arm64] 2117 - os: [freebsd] 2118 - 2119 '@esbuild/freebsd-x64@0.25.3': 2120 resolution: {integrity: sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==} 2121 - engines: {node: '>=18'} 2122 - cpu: [x64] 2123 - os: [freebsd] 2124 - 2125 - '@esbuild/freebsd-x64@0.27.2': 2126 - resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} 2127 engines: {node: '>=18'} 2128 cpu: [x64] 2129 os: [freebsd] ··· 2134 cpu: [arm64] 2135 os: [linux] 2136 2137 - '@esbuild/linux-arm64@0.27.2': 2138 - resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} 2139 - engines: {node: '>=18'} 2140 - cpu: [arm64] 2141 - os: [linux] 2142 - 2143 '@esbuild/linux-arm@0.25.3': 2144 resolution: {integrity: sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==} 2145 - engines: {node: '>=18'} 2146 - cpu: [arm] 2147 - os: [linux] 2148 - 2149 - '@esbuild/linux-arm@0.27.2': 2150 - resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} 2151 engines: {node: '>=18'} 2152 cpu: [arm] 2153 os: [linux] ··· 2158 cpu: [ia32] 2159 os: [linux] 2160 2161 - '@esbuild/linux-ia32@0.27.2': 2162 - resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} 2163 - engines: {node: '>=18'} 2164 - cpu: [ia32] 2165 - os: [linux] 2166 - 2167 '@esbuild/linux-loong64@0.25.3': 2168 resolution: {integrity: sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==} 2169 - engines: {node: '>=18'} 2170 - cpu: [loong64] 2171 - os: [linux] 2172 - 2173 - '@esbuild/linux-loong64@0.27.2': 2174 - resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} 2175 engines: {node: '>=18'} 2176 cpu: [loong64] 2177 os: [linux] ··· 2182 cpu: [mips64el] 2183 os: [linux] 2184 2185 - '@esbuild/linux-mips64el@0.27.2': 2186 - resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} 2187 - engines: {node: '>=18'} 2188 - cpu: [mips64el] 2189 - os: [linux] 2190 - 2191 '@esbuild/linux-ppc64@0.25.3': 2192 resolution: {integrity: sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==} 2193 - engines: {node: '>=18'} 2194 - cpu: [ppc64] 2195 - os: [linux] 2196 - 2197 - '@esbuild/linux-ppc64@0.27.2': 2198 - resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} 2199 engines: {node: '>=18'} 2200 cpu: [ppc64] 2201 os: [linux] ··· 2206 cpu: [riscv64] 2207 os: [linux] 2208 2209 - '@esbuild/linux-riscv64@0.27.2': 2210 - resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} 2211 - engines: {node: '>=18'} 2212 - cpu: [riscv64] 2213 - os: [linux] 2214 - 2215 '@esbuild/linux-s390x@0.25.3': 2216 resolution: {integrity: sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==} 2217 - engines: {node: '>=18'} 2218 - cpu: [s390x] 2219 - os: [linux] 2220 - 2221 - '@esbuild/linux-s390x@0.27.2': 2222 - resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} 2223 engines: {node: '>=18'} 2224 cpu: [s390x] 2225 os: [linux] ··· 2230 cpu: [x64] 2231 os: [linux] 2232 2233 - '@esbuild/linux-x64@0.27.2': 2234 - resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} 2235 - engines: {node: '>=18'} 2236 - cpu: [x64] 2237 - os: [linux] 2238 - 2239 '@esbuild/netbsd-arm64@0.25.3': 2240 resolution: {integrity: sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==} 2241 - engines: {node: '>=18'} 2242 - cpu: [arm64] 2243 - os: [netbsd] 2244 - 2245 - '@esbuild/netbsd-arm64@0.27.2': 2246 - resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} 2247 engines: {node: '>=18'} 2248 cpu: [arm64] 2249 os: [netbsd] ··· 2254 cpu: [x64] 2255 os: [netbsd] 2256 2257 - '@esbuild/netbsd-x64@0.27.2': 2258 - resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} 2259 - engines: {node: '>=18'} 2260 - cpu: [x64] 2261 - os: [netbsd] 2262 - 2263 '@esbuild/openbsd-arm64@0.25.3': 2264 resolution: {integrity: sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==} 2265 - engines: {node: '>=18'} 2266 - cpu: [arm64] 2267 - os: [openbsd] 2268 - 2269 - '@esbuild/openbsd-arm64@0.27.2': 2270 - resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} 2271 engines: {node: '>=18'} 2272 cpu: [arm64] 2273 os: [openbsd] ··· 2278 cpu: [x64] 2279 os: [openbsd] 2280 2281 - '@esbuild/openbsd-x64@0.27.2': 2282 - resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} 2283 - engines: {node: '>=18'} 2284 - cpu: [x64] 2285 - os: [openbsd] 2286 - 2287 - '@esbuild/openharmony-arm64@0.27.2': 2288 - resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} 2289 - engines: {node: '>=18'} 2290 - cpu: [arm64] 2291 - os: [openharmony] 2292 - 2293 '@esbuild/sunos-x64@0.25.3': 2294 resolution: {integrity: sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==} 2295 engines: {node: '>=18'} 2296 cpu: [x64] 2297 os: [sunos] 2298 2299 - '@esbuild/sunos-x64@0.27.2': 2300 - resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} 2301 - engines: {node: '>=18'} 2302 - cpu: [x64] 2303 - os: [sunos] 2304 - 2305 '@esbuild/win32-arm64@0.25.3': 2306 resolution: {integrity: sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==} 2307 engines: {node: '>=18'} 2308 cpu: [arm64] 2309 os: [win32] 2310 2311 - '@esbuild/win32-arm64@0.27.2': 2312 - resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} 2313 - engines: {node: '>=18'} 2314 - cpu: [arm64] 2315 - os: [win32] 2316 - 2317 '@esbuild/win32-ia32@0.25.3': 2318 resolution: {integrity: sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==} 2319 engines: {node: '>=18'} 2320 cpu: [ia32] 2321 os: [win32] 2322 2323 - '@esbuild/win32-ia32@0.27.2': 2324 - resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} 2325 - engines: {node: '>=18'} 2326 - cpu: [ia32] 2327 - os: [win32] 2328 - 2329 '@esbuild/win32-x64@0.25.3': 2330 resolution: {integrity: sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==} 2331 - engines: {node: '>=18'} 2332 - cpu: [x64] 2333 - os: [win32] 2334 - 2335 - '@esbuild/win32-x64@0.27.2': 2336 - resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} 2337 engines: {node: '>=18'} 2338 cpu: [x64] 2339 os: [win32] ··· 2724 '@floating-ui/react-dom@2.1.3': 2725 resolution: {integrity: sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==} 2726 peerDependencies: 2727 - react: 19.0.0 2728 - react-dom: 19.0.0 2729 2730 '@floating-ui/utils@0.2.9': 2731 resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} ··· 2747 engines: {node: '>=14.0.0', npm: '>=7.0.0'} 2748 peerDependencies: 2749 '@fluent/bundle': '>=0.16.0' 2750 - react: 19.0.0 2751 2752 '@fluent/sequence@0.8.0': 2753 resolution: {integrity: sha512-eV5QlEEVV/wR3AFQLXO67x4yPRPQXyqke0c8yucyMSeW36B3ecZyVFlY1UprzrfFV8iPJB4TAehDy/dLGbvQ1Q==} ··· 2794 '@gorhom/bottom-sheet@5.1.6': 2795 resolution: {integrity: sha512-0b5tQj4fTaZAjST1PnkCp0p7d8iRqMezibTcqc8Kkn3N23Vn6upORNTD1fH0bLfwRt6e0WnZ7DjAmq315lrcKQ==} 2796 peerDependencies: 2797 - '@types/react': 19.0.0 2798 '@types/react-native': '*' 2799 - react: 19.0.0 2800 react-native: '*' 2801 react-native-gesture-handler: '>=2.16.1' 2802 react-native-reanimated: '>=3.16.0' ··· 2809 '@gorhom/portal@1.0.14': 2810 resolution: {integrity: sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A==} 2811 peerDependencies: 2812 - react: 19.0.0 2813 react-native: '*' 2814 2815 '@grpc/grpc-js@1.10.10': ··· 3179 resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} 3180 engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} 3181 3182 - '@jridgewell/gen-mapping@0.3.13': 3183 - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} 3184 - 3185 '@jridgewell/gen-mapping@0.3.5': 3186 resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} 3187 engines: {node: '>=6.0.0'} 3188 - 3189 - '@jridgewell/remapping@2.3.5': 3190 - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} 3191 3192 '@jridgewell/resolve-uri@3.1.2': 3193 resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} ··· 3205 3206 '@jridgewell/trace-mapping@0.3.25': 3207 resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 3208 - 3209 - '@jridgewell/trace-mapping@0.3.31': 3210 - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} 3211 3212 '@jridgewell/trace-mapping@0.3.9': 3213 resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} ··· 3606 '@radix-ui/react-arrow@1.1.7': 3607 resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} 3608 peerDependencies: 3609 - '@types/react': 19.0.0 3610 - '@types/react-dom': 19.0.0 3611 - react: 19.0.0 3612 - react-dom: 19.0.0 3613 peerDependenciesMeta: 3614 '@types/react': 3615 optional: true ··· 3619 '@radix-ui/react-collection@1.1.7': 3620 resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} 3621 peerDependencies: 3622 - '@types/react': 19.0.0 3623 - '@types/react-dom': 19.0.0 3624 - react: 19.0.0 3625 - react-dom: 19.0.0 3626 peerDependenciesMeta: 3627 '@types/react': 3628 optional: true ··· 3632 '@radix-ui/react-compose-refs@1.1.2': 3633 resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} 3634 peerDependencies: 3635 - '@types/react': 19.0.0 3636 - react: 19.0.0 3637 peerDependenciesMeta: 3638 '@types/react': 3639 optional: true ··· 3641 '@radix-ui/react-context@1.1.2': 3642 resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} 3643 peerDependencies: 3644 - '@types/react': 19.0.0 3645 - react: 19.0.0 3646 peerDependenciesMeta: 3647 '@types/react': 3648 optional: true ··· 3650 '@radix-ui/react-direction@1.1.1': 3651 resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} 3652 peerDependencies: 3653 - '@types/react': 19.0.0 3654 - react: 19.0.0 3655 peerDependenciesMeta: 3656 '@types/react': 3657 optional: true ··· 3659 '@radix-ui/react-dismissable-layer@1.1.11': 3660 resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} 3661 peerDependencies: 3662 - '@types/react': 19.0.0 3663 - '@types/react-dom': 19.0.0 3664 - react: 19.0.0 3665 - react-dom: 19.0.0 3666 peerDependenciesMeta: 3667 '@types/react': 3668 optional: true ··· 3672 '@radix-ui/react-dropdown-menu@2.1.16': 3673 resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} 3674 peerDependencies: 3675 - '@types/react': 19.0.0 3676 - '@types/react-dom': 19.0.0 3677 - react: 19.0.0 3678 - react-dom: 19.0.0 3679 peerDependenciesMeta: 3680 '@types/react': 3681 optional: true ··· 3685 '@radix-ui/react-focus-guards@1.1.3': 3686 resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} 3687 peerDependencies: 3688 - '@types/react': 19.0.0 3689 - react: 19.0.0 3690 peerDependenciesMeta: 3691 '@types/react': 3692 optional: true ··· 3694 '@radix-ui/react-focus-scope@1.1.7': 3695 resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} 3696 peerDependencies: 3697 - '@types/react': 19.0.0 3698 - '@types/react-dom': 19.0.0 3699 - react: 19.0.0 3700 - react-dom: 19.0.0 3701 peerDependenciesMeta: 3702 '@types/react': 3703 optional: true ··· 3707 '@radix-ui/react-id@1.1.1': 3708 resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} 3709 peerDependencies: 3710 - '@types/react': 19.0.0 3711 - react: 19.0.0 3712 peerDependenciesMeta: 3713 '@types/react': 3714 optional: true ··· 3716 '@radix-ui/react-menu@2.1.16': 3717 resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} 3718 peerDependencies: 3719 - '@types/react': 19.0.0 3720 - '@types/react-dom': 19.0.0 3721 - react: 19.0.0 3722 - react-dom: 19.0.0 3723 peerDependenciesMeta: 3724 '@types/react': 3725 optional: true ··· 3729 '@radix-ui/react-popper@1.2.8': 3730 resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} 3731 peerDependencies: 3732 - '@types/react': 19.0.0 3733 - '@types/react-dom': 19.0.0 3734 - react: 19.0.0 3735 - react-dom: 19.0.0 3736 peerDependenciesMeta: 3737 '@types/react': 3738 optional: true ··· 3742 '@radix-ui/react-portal@1.1.9': 3743 resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} 3744 peerDependencies: 3745 - '@types/react': 19.0.0 3746 - '@types/react-dom': 19.0.0 3747 - react: 19.0.0 3748 - react-dom: 19.0.0 3749 peerDependenciesMeta: 3750 '@types/react': 3751 optional: true ··· 3755 '@radix-ui/react-presence@1.1.5': 3756 resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} 3757 peerDependencies: 3758 - '@types/react': 19.0.0 3759 - '@types/react-dom': 19.0.0 3760 - react: 19.0.0 3761 - react-dom: 19.0.0 3762 peerDependenciesMeta: 3763 '@types/react': 3764 optional: true ··· 3768 '@radix-ui/react-primitive@2.1.3': 3769 resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} 3770 peerDependencies: 3771 - '@types/react': 19.0.0 3772 - '@types/react-dom': 19.0.0 3773 - react: 19.0.0 3774 - react-dom: 19.0.0 3775 peerDependenciesMeta: 3776 '@types/react': 3777 optional: true ··· 3781 '@radix-ui/react-roving-focus@1.1.11': 3782 resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} 3783 peerDependencies: 3784 - '@types/react': 19.0.0 3785 - '@types/react-dom': 19.0.0 3786 - react: 19.0.0 3787 - react-dom: 19.0.0 3788 peerDependenciesMeta: 3789 '@types/react': 3790 optional: true ··· 3794 '@radix-ui/react-slider@1.3.5': 3795 resolution: {integrity: sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw==} 3796 peerDependencies: 3797 - '@types/react': 19.0.0 3798 - '@types/react-dom': 19.0.0 3799 - react: 19.0.0 3800 - react-dom: 19.0.0 3801 peerDependenciesMeta: 3802 '@types/react': 3803 optional: true ··· 3807 '@radix-ui/react-slot@1.2.3': 3808 resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} 3809 peerDependencies: 3810 - '@types/react': 19.0.0 3811 - react: 19.0.0 3812 peerDependenciesMeta: 3813 '@types/react': 3814 optional: true ··· 3816 '@radix-ui/react-use-callback-ref@1.1.1': 3817 resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} 3818 peerDependencies: 3819 - '@types/react': 19.0.0 3820 - react: 19.0.0 3821 peerDependenciesMeta: 3822 '@types/react': 3823 optional: true ··· 3825 '@radix-ui/react-use-controllable-state@1.2.2': 3826 resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} 3827 peerDependencies: 3828 - '@types/react': 19.0.0 3829 - react: 19.0.0 3830 peerDependenciesMeta: 3831 '@types/react': 3832 optional: true ··· 3834 '@radix-ui/react-use-effect-event@0.0.2': 3835 resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} 3836 peerDependencies: 3837 - '@types/react': 19.0.0 3838 - react: 19.0.0 3839 peerDependenciesMeta: 3840 '@types/react': 3841 optional: true ··· 3843 '@radix-ui/react-use-escape-keydown@1.1.1': 3844 resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} 3845 peerDependencies: 3846 - '@types/react': 19.0.0 3847 - react: 19.0.0 3848 peerDependenciesMeta: 3849 '@types/react': 3850 optional: true ··· 3852 '@radix-ui/react-use-layout-effect@1.1.1': 3853 resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} 3854 peerDependencies: 3855 - '@types/react': 19.0.0 3856 - react: 19.0.0 3857 peerDependenciesMeta: 3858 '@types/react': 3859 optional: true ··· 3861 '@radix-ui/react-use-previous@1.1.1': 3862 resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} 3863 peerDependencies: 3864 - '@types/react': 19.0.0 3865 - react: 19.0.0 3866 peerDependenciesMeta: 3867 '@types/react': 3868 optional: true ··· 3870 '@radix-ui/react-use-rect@1.1.1': 3871 resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} 3872 peerDependencies: 3873 - '@types/react': 19.0.0 3874 - react: 19.0.0 3875 peerDependenciesMeta: 3876 '@types/react': 3877 optional: true ··· 3879 '@radix-ui/react-use-size@1.1.1': 3880 resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} 3881 peerDependencies: 3882 - '@types/react': 19.0.0 3883 - react: 19.0.0 3884 peerDependenciesMeta: 3885 '@types/react': 3886 optional: true ··· 3892 resolution: {integrity: sha512-FNekjZgvLLBWLNMGKfKUHR4TTu8OY1YnvlQV9HaNboF5U5+CvTcK8IKycXKdhVP8YfcILTaM3AFraoQsQsy3/w==} 3893 peerDependencies: 3894 expo: '>=47.0.0' 3895 - react: 19.0.0 3896 react-native: '*' 3897 peerDependenciesMeta: 3898 expo: ··· 3981 resolution: {integrity: sha512-/0rRozkn+iIHya2vnnvprDgT7QkfI54FLrACAN3BLP7MRlfOIGOrZsXpRLndnLBVnjNzkcre84i1RecjoXnwIA==} 3982 engines: {node: '>=18'} 3983 peerDependencies: 3984 - '@types/react': 19.0.0 3985 - react: 19.0.0 3986 react-native: '*' 3987 peerDependenciesMeta: 3988 '@types/react': ··· 3992 resolution: {integrity: sha512-9oD4cypEBjPuaMiu9tevWGiQ4w/d6l3HNhcJ1IjXZ24xvYDSs0mqjUcdt8SWUolCvRrYc/DmNBLlT83bk0bHTw==} 3993 peerDependencies: 3994 '@react-navigation/native': ^6.0.0 3995 - react: 19.0.0 3996 react-native: '*' 3997 react-native-safe-area-context: '>= 3.0.0' 3998 react-native-screens: '>= 3.0.0' ··· 4000 '@react-navigation/core@6.4.17': 4001 resolution: {integrity: sha512-Nd76EpomzChWAosGqWOYE3ItayhDzIEzzZsT7PfGcRFDgW5miHV2t4MZcq9YIK4tzxZjVVpYbIynOOQQd1e0Cg==} 4002 peerDependencies: 4003 - react: 19.0.0 4004 4005 '@react-navigation/drawer@6.7.2': 4006 resolution: {integrity: sha512-o4g2zgTZa2+oLd+8V33etrSM38KIqu8S/zCBTsdsHUoQyVE7JNRiv3Qgq/jMvEb8PZCqWmm7jHItcgzrBuwyOQ==} 4007 peerDependencies: 4008 '@react-navigation/native': ^6.0.0 4009 - react: 19.0.0 4010 react-native: '*' 4011 react-native-gesture-handler: '>= 1.0.0' 4012 react-native-reanimated: '>= 1.0.0' ··· 4017 resolution: {integrity: sha512-bUzP4Awlljx5RKEExw8WYtif8EuQni2glDaieYROKTnaxsu9kEIA515sXQgUDZU4Ob12VoL7+z70uO3qrlfXcQ==} 4018 peerDependencies: 4019 '@react-navigation/native': ^6.0.0 4020 - react: 19.0.0 4021 react-native: '*' 4022 react-native-safe-area-context: '>= 3.0.0' 4023 ··· 4025 resolution: {integrity: sha512-U5EcUB9Q2NQspCFwYGGNJm0h6wBCOv7T30QjndmvlawLkNt7S7KWbpWyxS9XBHSIKF57RgWjfxuJNTgTstpXxw==} 4026 peerDependencies: 4027 '@react-navigation/native': ^6.0.0 4028 - react: 19.0.0 4029 react-native: '*' 4030 react-native-safe-area-context: '>= 3.0.0' 4031 react-native-screens: '>= 3.0.0' ··· 4033 '@react-navigation/native@6.1.18': 4034 resolution: {integrity: sha512-mIT9MiL/vMm4eirLcmw2h6h/Nm5FICtnYSdohq4vTLA2FF/6PNhByM7s8ffqoVfE5L0uAa6Xda1B7oddolUiGg==} 4035 peerDependencies: 4036 - react: 19.0.0 4037 react-native: '*' 4038 4039 '@react-navigation/routers@6.1.9': ··· 4082 resolution: {integrity: sha512-TJDDr8VQfw9CRZ7xZ6kBYLVMqL1xFVC5ZZ4sfRmWP6PCT0lNks4XqGuTFLeVVlNLPSmzt9GKC2DZqzDXui8/NQ==} 4083 peerDependencies: 4084 '@rn-primitives/portal': '*' 4085 - react: 19.0.0 4086 react-native: '*' 4087 react-native-web: '*' 4088 peerDependenciesMeta: ··· 4094 '@rn-primitives/hooks@1.3.0': 4095 resolution: {integrity: sha512-BR97reSu7uVDpyMeQdRJHT0w8KdS6jdYnOL6xQtqS2q3H6N7vXBlX4LFERqJZphD+aziJFIAJ3HJF1vtt6XlpQ==} 4096 peerDependencies: 4097 - react: 19.0.0 4098 react-native: '*' 4099 react-native-web: '*' 4100 peerDependenciesMeta: ··· 4106 '@rn-primitives/portal@1.3.0': 4107 resolution: {integrity: sha512-a2DSce7TcSfcs0cCngLadAJOvx/+mdH9NRu+GxkX8NPRsGGhJvDEOqouMgDqLwx7z9mjXoUaZcwaVcemUSW9/A==} 4108 peerDependencies: 4109 - react: 19.0.0 4110 react-native: '*' 4111 react-native-web: '*' 4112 peerDependenciesMeta: ··· 4118 '@rn-primitives/slider@1.2.0': 4119 resolution: {integrity: sha512-JRxTQelfEdG7tWA+7v5YY/9hUeZXe99BrfRH4b/kUbdMdzMp+MEEvJ6y1iqUlNIys5B6uuTWLnFjI8IhG/MkXw==} 4120 peerDependencies: 4121 - react: 19.0.0 4122 react-native: '*' 4123 react-native-web: '*' 4124 peerDependenciesMeta: ··· 4130 '@rn-primitives/slot@1.2.0': 4131 resolution: {integrity: sha512-cpbn+JLjSeq3wcA4uqgFsUimMrWYWx2Ks7r5rkwd1ds1utxynsGkLOKpYVQkATwWrYhtcoF1raxIKEqXuMN+/w==} 4132 peerDependencies: 4133 - react: 19.0.0 4134 react-native: '*' 4135 react-native-web: '*' 4136 peerDependenciesMeta: ··· 4142 '@rn-primitives/types@1.2.0': 4143 resolution: {integrity: sha512-b+6zKgdKVqAfaFPSfhwlQL0dnPQXPpW890m3eguC0VDI1eOsoEvUfVb6lmgH4bum9MmI0xymq4tOUI/fsKLoCQ==} 4144 peerDependencies: 4145 - react: 19.0.0 4146 react-native: '*' 4147 react-native-web: '*' 4148 peerDependenciesMeta: ··· 4154 '@rn-primitives/utils@1.2.0': 4155 resolution: {integrity: sha512-vLXV5NuxIHDeb4Bw57FzdUh89/g8gz6GERm8TsbJaSUPsDXfnC/ffeYiZJb0LxNteKE3Nr8na4Jy2n26tFil7w==} 4156 peerDependencies: 4157 - react: 19.0.0 4158 react-native: '*' 4159 react-native-web: '*' 4160 peerDependenciesMeta: ··· 4372 hasBin: true 4373 peerDependencies: 4374 expo: '>=49.0.0' 4375 - react: 19.0.0 4376 react-native: '>=0.65.0' 4377 peerDependenciesMeta: 4378 expo: ··· 4382 resolution: {integrity: sha512-42T/fp8snYN19Fy/2P0Mwotu4gcdy+1Lx+uYCNcYP1o7wNGigJ7qb27sW7W34GyCCHjoCCfQgeOqDQsyY8LC9w==} 4383 engines: {node: '>=14.18'} 4384 peerDependencies: 4385 - react: 19.0.0 4386 4387 '@sentry/types@8.54.0': 4388 resolution: {integrity: sha512-wztdtr7dOXQKi0iRvKc8XJhJ7HaAfOv8lGu0yqFOFwBZucO/SHnu87GOPi8mvrTiy1bentQO5l+zXWAaMvG4uw==} ··· 4911 '@tanstack/react-query@5.59.19': 4912 resolution: {integrity: sha512-xLRfyFyQOFcLltKCds0LijfC6/HQJrrTTnZB8ciyn74LIkVAm++vZJ6eUVG20RmJtdP8REdy7vSOYW4M3//XLA==} 4913 peerDependencies: 4914 - react: 19.0.0 4915 4916 '@tokenizer/token@0.3.0': 4917 resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} ··· 5099 '@types/normalize-package-data@2.4.4': 5100 resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} 5101 5102 '@types/qrcode@1.5.5': 5103 resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==} 5104 ··· 5108 '@types/range-parser@1.2.7': 5109 resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} 5110 5111 - '@types/react-dom@19.0.0': 5112 - resolution: {integrity: sha512-1KfiQKsH1o00p9m5ag12axHQSb3FOU9H20UTrujVSkNhuCrRHiQWFqgEnTNK5ZNfnzZv8UWrnXVqCmCF9fgY3w==} 5113 5114 - '@types/react@19.0.0': 5115 - resolution: {integrity: sha512-MY3oPudxvMYyesqs/kW1Bh8y9VqSmf+tzqw3ae8a9DZW68pUe3zAdHeI1jc6iAysuRdACnVknHP8AhwD4/dxtg==} 5116 5117 '@types/request@2.48.12': 5118 resolution: {integrity: sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==} ··· 5789 base64-js@1.5.1: 5790 resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 5791 5792 - baseline-browser-mapping@2.9.14: 5793 - resolution: {integrity: sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==} 5794 - hasBin: true 5795 - 5796 batch@0.6.1: 5797 resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} 5798 ··· 5916 browser-or-node@3.0.0: 5917 resolution: {integrity: sha512-iczIdVJzGEYhP5DqQxYM9Hh7Ztpqqi+CXZpSmX8ALFs9ecXkQIeqRyM6TfxEfMVpwhl3dSuDvxdzzo9sUOIVBQ==} 5918 5919 - browserslist@4.24.5: 5920 - resolution: {integrity: sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==} 5921 engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 5922 hasBin: true 5923 5924 - browserslist@4.28.1: 5925 - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} 5926 engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 5927 hasBin: true 5928 ··· 5964 resolution: {integrity: sha512-bbZjGN4Om7dykr8ZcLb0tTO5L2becMR+HIez1ySUGgG/rvK+ePgBEuBA6lMOZqOTsUXhIKFUBH0sCXQ25fq5SA==} 5965 peerDependencies: 5966 expo: '*' 5967 - react: 19.0.0 5968 react-native: '*' 5969 5970 byte-size@8.1.1: ··· 6051 6052 camelize@1.0.1: 6053 resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} 6054 6055 caniuse-lite@1.0.30001718: 6056 resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==} 6057 6058 - caniuse-lite@1.0.30001764: 6059 - resolution: {integrity: sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==} 6060 - 6061 cbor-extract@2.2.0: 6062 resolution: {integrity: sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==} 6063 hasBin: true ··· 6602 engines: {node: '>=4'} 6603 hasBin: true 6604 6605 - csstype@3.2.3: 6606 - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} 6607 6608 dargs@7.0.0: 6609 resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} ··· 6948 electron-to-chromium@1.5.159: 6949 resolution: {integrity: sha512-CEvHptWAMV5p6GJ0Lq8aheyvVbfzVrv5mmidu1D3pidoVNkB3tTBsTMVtPJ+rzRK5oV229mCLz9Zj/hNvU8GBA==} 6950 6951 - electron-to-chromium@1.5.267: 6952 - resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} 6953 6954 electron-winstaller@5.4.0: 6955 resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==} ··· 7109 engines: {node: '>=18'} 7110 hasBin: true 7111 7112 - esbuild@0.27.2: 7113 - resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} 7114 - engines: {node: '>=18'} 7115 - hasBin: true 7116 - 7117 escalade@3.2.0: 7118 resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 7119 engines: {node: '>=6'} ··· 7312 resolution: {integrity: sha512-GEQDCqC25uDBoXHEnXeBuwpeXvI+3fRGvtzwwt0ZKKzWaN+TgeF8H7c76p3Zi4DfBMFDcduM0CmOvJX+yCCLUQ==} 7313 peerDependencies: 7314 expo: '*' 7315 - react: 19.0.0 7316 react-native: '*' 7317 7318 expo-build-properties@0.14.6: ··· 7359 resolution: {integrity: sha512-d+xrHYvSM9WB42wj8vP9OOFWyxed5R1evphfDb6zYBmC1dA9Hf89FpT7TNFtj2Bk3clTnpmVqQTCYbbA2P3CLg==} 7360 peerDependencies: 7361 expo: '*' 7362 - react: 19.0.0 7363 7364 expo-json-utils@0.15.0: 7365 resolution: {integrity: sha512-duRT6oGl80IDzH2LD2yEFWNwGIC2WkozsB6HF3cDYNoNNdUvFk6uN3YiwsTsqVM/D0z6LEAQ01/SlYvN+Fw0JQ==} ··· 7368 resolution: {integrity: sha512-wU9qOnosy4+U4z/o4h8W9PjPvcFMfZXrlUoKTMBW7F4pLqhkkP/5G4EviPZixv4XWFMjn1ExQ5rV6BX8GwJsWA==} 7369 peerDependencies: 7370 expo: '*' 7371 - react: 19.0.0 7372 7373 expo-linking@7.1.5: 7374 resolution: {integrity: sha512-8g20zOpROW78bF+bLI4a3ZWj4ntLgM0rCewKycPL0jk9WGvBrBtFtwwADJgOiV1EurNp3lcquerXGlWS+SOQyA==} 7375 peerDependencies: 7376 - react: 19.0.0 7377 react-native: '*' 7378 7379 expo-localization@17.0.7: 7380 resolution: {integrity: sha512-ACg1B0tJLNa+f8mZfAaNrMyNzrrzHAARVH1sHHvh+LolKdQpgSKX69Uroz1Llv4C71furpwBklVStbNcEwVVVA==} 7381 peerDependencies: 7382 expo: '*' 7383 - react: 19.0.0 7384 7385 expo-manifests@0.16.5: 7386 resolution: {integrity: sha512-zLUeJogn2C7qOE75Zz7jcmJorMfIbSRR35ctspN0OK/Hq/+PAAptA8p9jNVC8xp/91uP9uI8f3xPhh+A11eR2A==} ··· 7398 resolution: {integrity: sha512-AATxKoav5ZvwcRel2SKYNZc+EvOAKvAjxyBezC8y3J5fMNe/uKIhMzh3FN4fKdOi9ao/UBHkvLiUO2MqVnvBNg==} 7399 peerDependencies: 7400 expo: '*' 7401 - react: 19.0.0 7402 react-native: '*' 7403 7404 expo-screen-orientation@9.0.7: ··· 7422 resolution: {integrity: sha512-J2Y7tChIFEcpgiVxxAXWaArOSIaHxct6keNZPs/6aHrSzUWmAlQS5vzGQueB1II65rl47ZtZcQEIl0NpiRhxxQ==} 7423 peerDependencies: 7424 expo: '*' 7425 - react: 19.0.0 7426 react-native: '*' 7427 7428 expo-structured-headers@4.1.0: ··· 7448 hasBin: true 7449 peerDependencies: 7450 expo: '*' 7451 - react: 19.0.0 7452 7453 expo-video@2.2.1: 7454 resolution: {integrity: sha512-dw3h0eMLK8WpY1Tnwsgrxx3sFqXiOujmurjGdr+RFG63ZurAze/H9uuKMVl3ps/ZNuK4q/2ifIiJudoFJfwKwA==} 7455 peerDependencies: 7456 expo: '*' 7457 - react: 19.0.0 7458 react-native: '*' 7459 7460 expo-web-browser@14.1.6: ··· 7469 peerDependencies: 7470 '@expo/dom-webview': '*' 7471 '@expo/metro-runtime': '*' 7472 - react: 19.0.0 7473 react-native: '*' 7474 react-native-webview: '*' 7475 peerDependenciesMeta: ··· 7933 resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} 7934 engines: {node: '>= 0.4'} 7935 7936 - get-tsconfig@4.13.0: 7937 - resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} 7938 - 7939 getenv@1.0.0: 7940 resolution: {integrity: sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==} 7941 engines: {node: '>=6'} ··· 8104 has-flag@4.0.0: 8105 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 8106 engines: {node: '>=8'} 8107 8108 has-property-descriptors@1.0.2: 8109 resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} ··· 8555 iron-webcrypto@1.2.1: 8556 resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} 8557 8558 is-alphabetical@2.0.1: 8559 resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} 8560 ··· 9102 lighthouse-logger@1.4.2: 9103 resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==} 9104 9105 - lightningcss-android-arm64@1.30.2: 9106 - resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} 9107 - engines: {node: '>= 12.0.0'} 9108 - cpu: [arm64] 9109 - os: [android] 9110 - 9111 lightningcss-darwin-arm64@1.27.0: 9112 resolution: {integrity: sha512-Gl/lqIXY+d+ySmMbgDf0pgaWSqrWYxVHoc88q+Vhf2YNzZ8DwoRzGt5NZDVqqIW5ScpSnmmjcgXP87Dn2ylSSQ==} 9113 engines: {node: '>= 12.0.0'} 9114 cpu: [arm64] 9115 os: [darwin] 9116 9117 - lightningcss-darwin-arm64@1.30.2: 9118 - resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} 9119 engines: {node: '>= 12.0.0'} 9120 cpu: [arm64] 9121 os: [darwin] ··· 9126 cpu: [x64] 9127 os: [darwin] 9128 9129 - lightningcss-darwin-x64@1.30.2: 9130 - resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} 9131 engines: {node: '>= 12.0.0'} 9132 cpu: [x64] 9133 os: [darwin] ··· 9138 cpu: [x64] 9139 os: [freebsd] 9140 9141 - lightningcss-freebsd-x64@1.30.2: 9142 - resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} 9143 engines: {node: '>= 12.0.0'} 9144 cpu: [x64] 9145 os: [freebsd] ··· 9150 cpu: [arm] 9151 os: [linux] 9152 9153 - lightningcss-linux-arm-gnueabihf@1.30.2: 9154 - resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} 9155 engines: {node: '>= 12.0.0'} 9156 cpu: [arm] 9157 os: [linux] ··· 9162 cpu: [arm64] 9163 os: [linux] 9164 9165 - lightningcss-linux-arm64-gnu@1.30.2: 9166 - resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} 9167 engines: {node: '>= 12.0.0'} 9168 cpu: [arm64] 9169 os: [linux] ··· 9174 cpu: [arm64] 9175 os: [linux] 9176 9177 - lightningcss-linux-arm64-musl@1.30.2: 9178 - resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} 9179 engines: {node: '>= 12.0.0'} 9180 cpu: [arm64] 9181 os: [linux] ··· 9186 cpu: [x64] 9187 os: [linux] 9188 9189 - lightningcss-linux-x64-gnu@1.30.2: 9190 - resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} 9191 engines: {node: '>= 12.0.0'} 9192 cpu: [x64] 9193 os: [linux] ··· 9198 cpu: [x64] 9199 os: [linux] 9200 9201 - lightningcss-linux-x64-musl@1.30.2: 9202 - resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} 9203 engines: {node: '>= 12.0.0'} 9204 cpu: [x64] 9205 os: [linux] ··· 9210 cpu: [arm64] 9211 os: [win32] 9212 9213 - lightningcss-win32-arm64-msvc@1.30.2: 9214 - resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} 9215 engines: {node: '>= 12.0.0'} 9216 cpu: [arm64] 9217 os: [win32] ··· 9222 cpu: [x64] 9223 os: [win32] 9224 9225 - lightningcss-win32-x64-msvc@1.30.2: 9226 - resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} 9227 engines: {node: '>= 12.0.0'} 9228 cpu: [x64] 9229 os: [win32] ··· 9232 resolution: {integrity: sha512-8f7aNmS1+etYSLHht0fQApPc2kNO8qGRutifN5rVIc6Xo6ABsEbqOr758UwI7ALVbTt4x1fllKt0PYgzD9S3yQ==} 9233 engines: {node: '>= 12.0.0'} 9234 9235 - lightningcss@1.30.2: 9236 - resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} 9237 engines: {node: '>= 12.0.0'} 9238 9239 lilconfig@3.1.2: ··· 9422 lucide-react-native@0.514.0: 9423 resolution: {integrity: sha512-IaW5ItnJ9TDv9lZJOtjBRc2r217BRO4xNhd9g1hmW5GKvOtFzFYYfkogktUihiniXThwo1NBmNMa82mbWKMJVQ==} 9424 peerDependencies: 9425 - react: 19.0.0 9426 react-native: '*' 9427 react-native-svg: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 9428 ··· 10089 node-mock-http@1.0.0: 10090 resolution: {integrity: sha512-0uGYQ1WQL1M5kKvGRXWQ3uZCHtLTO8hln3oBjIusM75WoesZ909uQJs/Hb946i2SS+Gsrhkaa6iAO17jRIv6DQ==} 10091 10092 node-releases@2.0.19: 10093 resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} 10094 - 10095 - node-releases@2.0.27: 10096 - resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} 10097 10098 nodemailer-html-to-text@3.2.0: 10099 resolution: {integrity: sha512-RJUC6640QV1PzTHHapOrc6IzrAJUZtk2BdVdINZ9VTLm+mcQNyBO9LYyhrnufkzqiD9l8hPLJ97rSyK4WanPNg==} ··· 10789 postcss-value-parser@4.2.0: 10790 resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} 10791 10792 - postcss@8.4.49: 10793 - resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} 10794 engines: {node: ^10 || ^12 || >=14} 10795 10796 postcss@8.5.3: ··· 11040 react-dom@19.0.0: 11041 resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} 11042 peerDependencies: 11043 - react: 19.0.0 11044 11045 react-freeze@1.0.4: 11046 resolution: {integrity: sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==} 11047 engines: {node: '>=10'} 11048 peerDependencies: 11049 - react: 19.0.0 11050 11051 react-i18next@15.7.4: 11052 resolution: {integrity: sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw==} 11053 peerDependencies: 11054 i18next: '>= 23.4.0' 11055 - react: 19.0.0 11056 react-dom: '*' 11057 react-native: '*' 11058 typescript: ^5 ··· 11080 react-native-edge-to-edge@1.6.0: 11081 resolution: {integrity: sha512-2WCNdE3Qd6Fwg9+4BpbATUxCLcouF6YRY7K+J36KJ4l3y+tWN6XCqAC4DuoGblAAbb2sLkhEDp4FOlbOIot2Og==} 11082 peerDependencies: 11083 - react: 19.0.0 11084 react-native: '*' 11085 11086 react-native-edge-to-edge@1.6.2: 11087 resolution: {integrity: sha512-koEF6WRAfdGNelXlP7NtHrQhFGtplwciYNWLHOCTCk0Thc7dlxtqxHRYSA5vPJgWOEkVBFqxcoOqKwAtqOmLNw==} 11088 peerDependencies: 11089 - react: 19.0.0 11090 react-native: '*' 11091 11092 react-native-fit-image@1.5.5: ··· 11095 react-native-gesture-handler@2.26.0: 11096 resolution: {integrity: sha512-pfE1j9Vzu0qpWj/Aq1IK+cYnougN69mCKvWuq1rdNjH2zs1WIszF0Mum9/oGQTemgjyc/JgiqOOTgwcleAMAGg==} 11097 peerDependencies: 11098 - react: 19.0.0 11099 react-native: '*' 11100 11101 react-native-haptic-feedback@2.3.3: ··· 11106 react-native-is-edge-to-edge@1.1.7: 11107 resolution: {integrity: sha512-EH6i7E8epJGIcu7KpfXYXiV2JFIYITtq+rVS8uEb+92naMRBdxhTuS8Wn2Q7j9sqyO0B+Xbaaf9VdipIAmGW4w==} 11108 peerDependencies: 11109 - react: 19.0.0 11110 react-native: '*' 11111 11112 react-native-localize@3.5.2: 11113 resolution: {integrity: sha512-HfQdwv5sRjh4AQ8a97OTjXYcxPNRlBxiQb861c7Ob6mRuNYCPtaJ45QTcZxZr31vAM3THvtOBp1soqWlQFxjnA==} 11114 peerDependencies: 11115 '@expo/config-plugins': ^9.0.0 || ^10.0.0 11116 - react: 19.0.0 11117 react-native: '*' 11118 react-native-macos: '*' 11119 peerDependenciesMeta: ··· 11125 react-native-markdown-display@7.0.2: 11126 resolution: {integrity: sha512-Mn4wotMvMfLAwbX/huMLt202W5DsdpMO/kblk+6eUs55S57VVNni1gzZCh5qpznYLjIQELNh50VIozEfY6fvaQ==} 11127 peerDependencies: 11128 - react: 19.0.0 11129 react-native: '>=0.50.4' 11130 11131 react-native-quick-base64@2.1.2: 11132 resolution: {integrity: sha512-xghaXpWdB0ji8OwYyo0fWezRroNxiNFCNFpGUIyE7+qc4gA/IGWnysIG5L0MbdoORv8FkTKUvfd6yCUN5R2VFA==} 11133 peerDependencies: 11134 - react: 19.0.0 11135 react-native: '*' 11136 11137 react-native-quick-crypto@0.7.14: ··· 11141 resolution: {integrity: sha512-eVcNcqeOkMW+BUWAHdtvN3FKgC8J8wiEJkX6bNGGQaLS7m7e4amTfjIcqf/Ta+lerZLurmDaQ0lICI1CKPrb1Q==} 11142 peerDependencies: 11143 '@babel/core': ^7.0.0-0 11144 - react: 19.0.0 11145 react-native: '*' 11146 11147 react-native-safe-area-context@5.4.1: 11148 resolution: {integrity: sha512-x+g3NblZ9jof8y+XkVvaGlpMrSlixhrJJ33BRzhTAKUKctQVecO1heSXmzxc5UdjvGYBKS6kPZVUw2b8NxHcPg==} 11149 peerDependencies: 11150 - react: 19.0.0 11151 react-native: '*' 11152 11153 react-native-screens@4.11.1: 11154 resolution: {integrity: sha512-F0zOzRVa3ptZfLpD0J8ROdo+y1fEPw+VBFq1MTY/iyDu08al7qFUO5hLMd+EYMda5VXGaTFCa8q7bOppUszhJw==} 11155 peerDependencies: 11156 - react: 19.0.0 11157 react-native: '*' 11158 11159 react-native-sortables@1.9.4: 11160 resolution: {integrity: sha512-a6hxT+gl14HA5Sm8UiLXJqF8KMEQVa+mUJd75OnzoVsmrxUDtjAatlMdV0kI9qTQDT/ZSFLPRmdUhOR762IA4g==} 11161 peerDependencies: 11162 - react: 19.0.0 11163 react-native: '*' 11164 react-native-gesture-handler: '>=2.0.0' 11165 react-native-reanimated: '>=3.0.0' ··· 11167 react-native-svg@15.12.0: 11168 resolution: {integrity: sha512-iE25PxIJ6V0C6krReLquVw6R0QTsRTmEQc4K2Co3P6zsimU/jltcDBKYDy1h/5j9S/fqmMeXnpM+9LEWKJKI6A==} 11169 peerDependencies: 11170 - react: 19.0.0 11171 react-native: '*' 11172 11173 react-native-web@0.20.0: 11174 resolution: {integrity: sha512-OOSgrw+aON6R3hRosCau/xVxdLzbjEcsLysYedka0ZON4ZZe6n9xgeN9ZkoejhARM36oTlUgHIQqxGutEJ9Wxg==} 11175 peerDependencies: 11176 - react: 19.0.0 11177 - react-dom: 19.0.0 11178 11179 react-native-webrtc@https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56: 11180 resolution: {tarball: https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56} ··· 11185 react-native-webview@13.15.0: 11186 resolution: {integrity: sha512-Vzjgy8mmxa/JO6l5KZrsTC7YemSdq+qB01diA0FqjUTaWGAGwuykpJ73MDj3+mzBSlaDxAEugHzTtkUQkQEQeQ==} 11187 peerDependencies: 11188 - react: 19.0.0 11189 react-native: '*' 11190 11191 react-native@0.79.3: ··· 11193 engines: {node: '>=18'} 11194 hasBin: true 11195 peerDependencies: 11196 - '@types/react': 19.0.0 11197 - react: 19.0.0 11198 peerDependenciesMeta: 11199 '@types/react': 11200 optional: true ··· 11207 resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} 11208 engines: {node: '>=10'} 11209 peerDependencies: 11210 - '@types/react': 19.0.0 11211 - react: 19.0.0 11212 peerDependenciesMeta: 11213 '@types/react': 11214 optional: true ··· 11217 resolution: {integrity: sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==} 11218 engines: {node: '>=10'} 11219 peerDependencies: 11220 - '@types/react': 19.0.0 11221 - react: 19.0.0 11222 peerDependenciesMeta: 11223 '@types/react': 11224 optional: true ··· 11227 resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} 11228 engines: {node: '>=10'} 11229 peerDependencies: 11230 - '@types/react': 19.0.0 11231 - react: 19.0.0 11232 peerDependenciesMeta: 11233 '@types/react': 11234 optional: true ··· 11319 resolution: {integrity: sha512-AA9iIVcrFiE70oyGuOvh2Vy7D5R2MVPig8dxzHuFyCnbO+AmMzn3JYNERp/PHsI2G0/aPeCuPZu6vOL1jZAeRg==} 11320 peerDependencies: 11321 expo: '>=44.0.0' 11322 - react: 19.0.0 11323 react-native: '*' 11324 react-native-gesture-handler: '>=2.0.0' 11325 react-native-reanimated: ^2.0.0 || ^3.0.0 ··· 11506 resolution: {integrity: sha512-rzB7NnQpOkPHBWFPP3prUMqOP6yg3HkRGgcvR+lDyvyHoY3fZLFLYDkPXh78SPVBAE6VTCk/V+j8we4djg6o4g==} 11507 engines: {node: '>=4', npm: '>=2'} 11508 11509 - resolve-pkg-maps@1.0.0: 11510 - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} 11511 - 11512 resolve-workspace-root@2.0.0: 11513 resolution: {integrity: sha512-IsaBUZETJD5WsI11Wt8PKHwaIe45or6pwNc8yflvLJ4DWtImK9kuLoH5kUva/2Mmx/RdIyr4aONNSa2v9LTJsw==} 11514 ··· 11867 sonner@0.3.5: 11868 resolution: {integrity: sha512-yIwaQ4dftMvFApuruto2t7wGyyaPRpj5qYBWYJIz4Z7uGcVn0IfqI/hWN0JyJN4izNbZFuCYZISf3fOGnvSlNQ==} 11869 peerDependencies: 11870 - react: 19.0.0 11871 - react-dom: 19.0.0 11872 11873 sort-keys@2.0.0: 11874 resolution: {integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==} ··· 11966 standard-as-callback@2.1.0: 11967 resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} 11968 11969 starlight-openapi-rapidoc@0.8.1-beta: 11970 resolution: {integrity: sha512-CicjuydKZsO8jZvhrtzz+GGWyfHnOZCZY/ww562H58CP/zSnskWcmcgVnCuD7DkKfi0ofvqumyyee1KgfkVipQ==} 11971 engines: {node: '>=18.14.1'} ··· 11981 '@astrojs/starlight': '>=0.34.0' 11982 astro: '>=5.5.0' 11983 11984 statuses@1.5.0: 11985 resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} 11986 engines: {node: '>= 0.6'} ··· 12188 resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} 12189 engines: {node: '>= 8.0'} 12190 12191 supports-color@5.5.0: 12192 resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} 12193 engines: {node: '>=4'} ··· 12204 resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} 12205 engines: {node: '>=8'} 12206 12207 supports-preserve-symlinks-flag@1.0.0: 12208 resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 12209 engines: {node: '>= 0.4'} ··· 12266 terminal-link@2.1.1: 12267 resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} 12268 engines: {node: '>=8'} 12269 12270 terser-webpack-plugin@5.3.10: 12271 resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} ··· 12485 optional: true 12486 typescript: 12487 optional: true 12488 - 12489 - tsx@4.21.0: 12490 - resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} 12491 - engines: {node: '>=18.0.0'} 12492 - hasBin: true 12493 12494 tuf-js@2.2.1: 12495 resolution: {integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==} ··· 12823 resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} 12824 engines: {node: '>=4'} 12825 12826 - update-browserslist-db@1.1.3: 12827 - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} 12828 hasBin: true 12829 peerDependencies: 12830 browserslist: '>= 4.21.0' 12831 12832 - update-browserslist-db@1.2.3: 12833 - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} 12834 hasBin: true 12835 peerDependencies: 12836 browserslist: '>= 4.21.0' ··· 12852 resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} 12853 engines: {node: '>=10'} 12854 peerDependencies: 12855 - '@types/react': 19.0.0 12856 - react: 19.0.0 12857 peerDependenciesMeta: 12858 '@types/react': 12859 optional: true ··· 12861 use-latest-callback@0.2.1: 12862 resolution: {integrity: sha512-QWlq8Is8BGWBf883QOEQP5HWYX/kMI+JTbJ5rdtvJLmXTIh9XoHIO3PQcmQl8BU44VKxow1kbQUHa6mQSMALDQ==} 12863 peerDependencies: 12864 - react: 19.0.0 12865 12866 use-sidecar@1.1.3: 12867 resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} 12868 engines: {node: '>=10'} 12869 peerDependencies: 12870 - '@types/react': 19.0.0 12871 - react: 19.0.0 12872 peerDependenciesMeta: 12873 '@types/react': 12874 optional: true 12875 12876 - use-sync-external-store@1.6.0: 12877 - resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} 12878 peerDependencies: 12879 - react: 19.0.0 12880 12881 username@5.1.0: 12882 resolution: {integrity: sha512-PCKbdWw85JsYMvmCv5GH3kXmM66rCd9m1hBEDutPNv94b/pqCMT4NtcKyeWYvLFiE8b+ha1Jdl8XAaUdPn5QTg==} ··· 13419 resolution: {integrity: sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==} 13420 engines: {node: '>=12.20.0'} 13421 peerDependencies: 13422 - '@types/react': 19.0.0 13423 immer: '>=9.0.6' 13424 - react: 19.0.0 13425 use-sync-external-store: '>=1.2.0' 13426 peerDependenciesMeta: 13427 '@types/react': ··· 13441 '@0no-co/graphql.web@1.0.11': {} 13442 13443 '@adraffy/ens-normalize@1.11.0': {} 13444 13445 '@apidevtools/openapi-schemas@2.1.0': {} 13446 ··· 13476 transitivePeerDependencies: 13477 - supports-color 13478 13479 - '@astrojs/mdx@4.2.6(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2))': 13480 dependencies: 13481 '@astrojs/markdown-remark': 6.3.1 13482 '@mdx-js/mdx': 3.1.0(acorn@8.14.1) 13483 acorn: 8.14.1 13484 - astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2) 13485 es-module-lexer: 1.7.0 13486 estree-util-visit: 2.0.0 13487 hast-util-to-html: 9.0.5 ··· 13505 stream-replace-string: 2.0.0 13506 zod: 3.24.4 13507 13508 - '@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2))': 13509 dependencies: 13510 '@astrojs/markdown-remark': 6.3.1 13511 - '@astrojs/mdx': 4.2.6(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2)) 13512 '@astrojs/sitemap': 3.3.1 13513 '@pagefind/default-ui': 1.3.0 13514 '@types/hast': 3.0.4 13515 '@types/js-yaml': 4.0.9 13516 '@types/mdast': 4.0.4 13517 - astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2) 13518 - astro-expressive-code: 0.41.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2)) 13519 bcp-47: 2.1.0 13520 hast-util-from-html: 2.0.3 13521 hast-util-select: 6.0.4 ··· 14808 js-tokens: 4.0.0 14809 picocolors: 1.1.1 14810 14811 - '@babel/code-frame@7.28.6': 14812 - dependencies: 14813 - '@babel/helper-validator-identifier': 7.28.5 14814 - js-tokens: 4.0.0 14815 - picocolors: 1.1.1 14816 - 14817 '@babel/compat-data@7.26.2': {} 14818 14819 '@babel/compat-data@7.27.3': {} 14820 14821 - '@babel/compat-data@7.28.6': {} 14822 - 14823 - '@babel/core@7.28.6': 14824 dependencies: 14825 - '@babel/code-frame': 7.28.6 14826 - '@babel/generator': 7.28.6 14827 - '@babel/helper-compilation-targets': 7.28.6 14828 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) 14829 - '@babel/helpers': 7.28.6 14830 - '@babel/parser': 7.28.6 14831 - '@babel/template': 7.28.6 14832 - '@babel/traverse': 7.28.6 14833 - '@babel/types': 7.28.6 14834 - '@jridgewell/remapping': 2.3.5 14835 convert-source-map: 2.0.0 14836 debug: 4.4.0(supports-color@5.5.0) 14837 gensync: 1.0.0-beta.2 ··· 14843 '@babel/generator@7.26.2': 14844 dependencies: 14845 '@babel/parser': 7.26.2 14846 - '@babel/types': 7.27.3 14847 '@jridgewell/gen-mapping': 0.3.5 14848 '@jridgewell/trace-mapping': 0.3.25 14849 jsesc: 3.0.2 14850 14851 '@babel/generator@7.27.3': 14852 dependencies: 14853 - '@babel/parser': 7.28.6 14854 - '@babel/types': 7.28.6 14855 '@jridgewell/gen-mapping': 0.3.5 14856 '@jridgewell/trace-mapping': 0.3.25 14857 jsesc: 3.0.2 14858 14859 - '@babel/generator@7.28.6': 14860 - dependencies: 14861 - '@babel/parser': 7.28.6 14862 - '@babel/types': 7.28.6 14863 - '@jridgewell/gen-mapping': 0.3.13 14864 - '@jridgewell/trace-mapping': 0.3.31 14865 - jsesc: 3.0.2 14866 - 14867 '@babel/helper-annotate-as-pure@7.27.3': 14868 dependencies: 14869 '@babel/types': 7.27.3 14870 14871 - '@babel/helper-compilation-targets@7.27.2': 14872 dependencies: 14873 - '@babel/compat-data': 7.27.3 14874 - '@babel/helper-validator-option': 7.27.1 14875 - browserslist: 4.24.5 14876 lru-cache: 5.1.1 14877 semver: 6.3.1 14878 14879 - '@babel/helper-compilation-targets@7.28.6': 14880 dependencies: 14881 - '@babel/compat-data': 7.28.6 14882 '@babel/helper-validator-option': 7.27.1 14883 - browserslist: 4.28.1 14884 lru-cache: 5.1.1 14885 semver: 6.3.1 14886 14887 - '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.6)': 14888 dependencies: 14889 - '@babel/core': 7.28.6 14890 '@babel/helper-annotate-as-pure': 7.27.3 14891 '@babel/helper-member-expression-to-functions': 7.27.1 14892 '@babel/helper-optimise-call-expression': 7.27.1 14893 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.6) 14894 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 14895 '@babel/traverse': 7.27.3 14896 semver: 6.3.1 14897 transitivePeerDependencies: 14898 - supports-color 14899 14900 - '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.6)': 14901 dependencies: 14902 - '@babel/core': 7.28.6 14903 '@babel/helper-annotate-as-pure': 7.27.3 14904 regexpu-core: 6.2.0 14905 semver: 6.3.1 14906 14907 - '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.28.6)': 14908 dependencies: 14909 - '@babel/core': 7.28.6 14910 - '@babel/helper-compilation-targets': 7.28.6 14911 '@babel/helper-plugin-utils': 7.27.1 14912 debug: 4.4.0(supports-color@5.5.0) 14913 lodash.debounce: 4.0.8 ··· 14915 transitivePeerDependencies: 14916 - supports-color 14917 14918 - '@babel/helper-globals@7.28.0': {} 14919 - 14920 '@babel/helper-member-expression-to-functions@7.27.1': 14921 dependencies: 14922 - '@babel/traverse': 7.28.6 14923 - '@babel/types': 7.28.6 14924 transitivePeerDependencies: 14925 - supports-color 14926 14927 '@babel/helper-module-imports@7.25.9': 14928 dependencies: 14929 - '@babel/traverse': 7.27.3 14930 - '@babel/types': 7.27.3 14931 transitivePeerDependencies: 14932 - supports-color 14933 ··· 14938 transitivePeerDependencies: 14939 - supports-color 14940 14941 - '@babel/helper-module-imports@7.28.6': 14942 dependencies: 14943 - '@babel/traverse': 7.28.6 14944 - '@babel/types': 7.28.6 14945 transitivePeerDependencies: 14946 - supports-color 14947 14948 - '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.6)': 14949 dependencies: 14950 - '@babel/core': 7.28.6 14951 '@babel/helper-module-imports': 7.27.1 14952 '@babel/helper-validator-identifier': 7.27.1 14953 - '@babel/traverse': 7.28.6 14954 - transitivePeerDependencies: 14955 - - supports-color 14956 - 14957 - '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.6)': 14958 - dependencies: 14959 - '@babel/core': 7.28.6 14960 - '@babel/helper-module-imports': 7.28.6 14961 - '@babel/helper-validator-identifier': 7.28.5 14962 - '@babel/traverse': 7.28.6 14963 transitivePeerDependencies: 14964 - supports-color 14965 14966 '@babel/helper-optimise-call-expression@7.27.1': 14967 dependencies: 14968 - '@babel/types': 7.28.6 14969 14970 '@babel/helper-plugin-utils@7.25.9': {} 14971 14972 '@babel/helper-plugin-utils@7.27.1': {} 14973 14974 - '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.6)': 14975 dependencies: 14976 - '@babel/core': 7.28.6 14977 '@babel/helper-annotate-as-pure': 7.27.3 14978 '@babel/helper-wrap-function': 7.27.1 14979 - '@babel/traverse': 7.28.6 14980 transitivePeerDependencies: 14981 - supports-color 14982 14983 - '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.6)': 14984 dependencies: 14985 - '@babel/core': 7.28.6 14986 '@babel/helper-member-expression-to-functions': 7.27.1 14987 '@babel/helper-optimise-call-expression': 7.27.1 14988 - '@babel/traverse': 7.28.6 14989 transitivePeerDependencies: 14990 - supports-color 14991 14992 '@babel/helper-skip-transparent-expression-wrappers@7.27.1': 14993 dependencies: 14994 - '@babel/traverse': 7.28.6 14995 - '@babel/types': 7.28.6 14996 transitivePeerDependencies: 14997 - supports-color 14998 ··· 15004 15005 '@babel/helper-validator-identifier@7.27.1': {} 15006 15007 - '@babel/helper-validator-identifier@7.28.5': {} 15008 15009 '@babel/helper-validator-option@7.27.1': {} 15010 15011 '@babel/helper-wrap-function@7.27.1': 15012 dependencies: 15013 - '@babel/template': 7.28.6 15014 - '@babel/traverse': 7.28.6 15015 - '@babel/types': 7.28.6 15016 transitivePeerDependencies: 15017 - supports-color 15018 15019 - '@babel/helpers@7.28.6': 15020 dependencies: 15021 - '@babel/template': 7.28.6 15022 - '@babel/types': 7.28.6 15023 15024 '@babel/highlight@7.24.7': 15025 dependencies: 15026 - '@babel/helper-validator-identifier': 7.28.5 15027 chalk: 2.4.2 15028 js-tokens: 4.0.0 15029 picocolors: 1.1.1 15030 15031 '@babel/parser@7.26.2': 15032 dependencies: 15033 - '@babel/types': 7.27.3 15034 15035 '@babel/parser@7.27.3': 15036 dependencies: 15037 - '@babel/types': 7.28.6 15038 - 15039 - '@babel/parser@7.28.6': 15040 - dependencies: 15041 - '@babel/types': 7.28.6 15042 15043 - '@babel/plugin-proposal-decorators@7.24.7(@babel/core@7.28.6)': 15044 dependencies: 15045 - '@babel/core': 7.28.6 15046 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.6) 15047 '@babel/helper-plugin-utils': 7.27.1 15048 - '@babel/plugin-syntax-decorators': 7.24.7(@babel/core@7.28.6) 15049 transitivePeerDependencies: 15050 - supports-color 15051 15052 - '@babel/plugin-proposal-export-default-from@7.25.9(@babel/core@7.28.6)': 15053 dependencies: 15054 - '@babel/core': 7.28.6 15055 '@babel/helper-plugin-utils': 7.25.9 15056 15057 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.6)': 15058 dependencies: 15059 - '@babel/core': 7.28.6 15060 '@babel/helper-plugin-utils': 7.27.1 15061 15062 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.6)': 15063 dependencies: 15064 - '@babel/core': 7.28.6 15065 '@babel/helper-plugin-utils': 7.27.1 15066 15067 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.6)': 15068 dependencies: 15069 - '@babel/core': 7.28.6 15070 '@babel/helper-plugin-utils': 7.27.1 15071 15072 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.6)': 15073 dependencies: 15074 - '@babel/core': 7.28.6 15075 '@babel/helper-plugin-utils': 7.27.1 15076 15077 - '@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.28.6)': 15078 dependencies: 15079 - '@babel/core': 7.28.6 15080 '@babel/helper-plugin-utils': 7.27.1 15081 15082 - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.28.6)': 15083 dependencies: 15084 - '@babel/core': 7.28.6 15085 '@babel/helper-plugin-utils': 7.27.1 15086 15087 - '@babel/plugin-syntax-export-default-from@7.25.9(@babel/core@7.28.6)': 15088 dependencies: 15089 - '@babel/core': 7.28.6 15090 '@babel/helper-plugin-utils': 7.25.9 15091 15092 - '@babel/plugin-syntax-flow@7.26.0(@babel/core@7.28.6)': 15093 dependencies: 15094 - '@babel/core': 7.28.6 15095 '@babel/helper-plugin-utils': 7.25.9 15096 15097 - '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.6)': 15098 dependencies: 15099 - '@babel/core': 7.28.6 15100 '@babel/helper-plugin-utils': 7.27.1 15101 15102 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.6)': 15103 dependencies: 15104 - '@babel/core': 7.28.6 15105 '@babel/helper-plugin-utils': 7.27.1 15106 15107 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.6)': 15108 dependencies: 15109 - '@babel/core': 7.28.6 15110 '@babel/helper-plugin-utils': 7.27.1 15111 15112 - '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.28.6)': 15113 dependencies: 15114 - '@babel/core': 7.28.6 15115 '@babel/helper-plugin-utils': 7.27.1 15116 15117 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.6)': 15118 dependencies: 15119 - '@babel/core': 7.28.6 15120 '@babel/helper-plugin-utils': 7.27.1 15121 15122 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.6)': 15123 dependencies: 15124 - '@babel/core': 7.28.6 15125 '@babel/helper-plugin-utils': 7.27.1 15126 15127 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.6)': 15128 dependencies: 15129 - '@babel/core': 7.28.6 15130 '@babel/helper-plugin-utils': 7.27.1 15131 15132 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.6)': 15133 dependencies: 15134 - '@babel/core': 7.28.6 15135 '@babel/helper-plugin-utils': 7.27.1 15136 15137 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.6)': 15138 dependencies: 15139 - '@babel/core': 7.28.6 15140 '@babel/helper-plugin-utils': 7.27.1 15141 15142 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.6)': 15143 dependencies: 15144 - '@babel/core': 7.28.6 15145 '@babel/helper-plugin-utils': 7.27.1 15146 15147 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.6)': 15148 dependencies: 15149 - '@babel/core': 7.28.6 15150 '@babel/helper-plugin-utils': 7.27.1 15151 15152 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.6)': 15153 dependencies: 15154 - '@babel/core': 7.28.6 15155 '@babel/helper-plugin-utils': 7.27.1 15156 15157 - '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.28.6)': 15158 dependencies: 15159 - '@babel/core': 7.28.6 15160 '@babel/helper-plugin-utils': 7.27.1 15161 15162 - '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.6)': 15163 dependencies: 15164 - '@babel/core': 7.28.6 15165 '@babel/helper-plugin-utils': 7.27.1 15166 15167 - '@babel/plugin-transform-async-generator-functions@7.27.1(@babel/core@7.28.6)': 15168 dependencies: 15169 - '@babel/core': 7.28.6 15170 '@babel/helper-plugin-utils': 7.27.1 15171 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6) 15172 - '@babel/traverse': 7.28.6 15173 transitivePeerDependencies: 15174 - supports-color 15175 15176 - '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.6)': 15177 dependencies: 15178 - '@babel/core': 7.28.6 15179 '@babel/helper-module-imports': 7.27.1 15180 '@babel/helper-plugin-utils': 7.27.1 15181 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6) 15182 transitivePeerDependencies: 15183 - supports-color 15184 15185 - '@babel/plugin-transform-block-scoping@7.27.3(@babel/core@7.28.6)': 15186 dependencies: 15187 - '@babel/core': 7.28.6 15188 '@babel/helper-plugin-utils': 7.27.1 15189 15190 - '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.6)': 15191 dependencies: 15192 - '@babel/core': 7.28.6 15193 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.6) 15194 '@babel/helper-plugin-utils': 7.27.1 15195 transitivePeerDependencies: 15196 - supports-color 15197 15198 - '@babel/plugin-transform-classes@7.27.1(@babel/core@7.28.6)': 15199 dependencies: 15200 - '@babel/core': 7.28.6 15201 '@babel/helper-annotate-as-pure': 7.27.3 15202 '@babel/helper-compilation-targets': 7.27.2 15203 '@babel/helper-plugin-utils': 7.27.1 15204 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.6) 15205 '@babel/traverse': 7.27.3 15206 globals: 11.12.0 15207 transitivePeerDependencies: 15208 - supports-color 15209 15210 - '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.6)': 15211 dependencies: 15212 - '@babel/core': 7.28.6 15213 '@babel/helper-plugin-utils': 7.27.1 15214 - '@babel/template': 7.28.6 15215 15216 - '@babel/plugin-transform-destructuring@7.27.3(@babel/core@7.28.6)': 15217 dependencies: 15218 - '@babel/core': 7.28.6 15219 '@babel/helper-plugin-utils': 7.27.1 15220 15221 - '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.6)': 15222 dependencies: 15223 - '@babel/core': 7.28.6 15224 '@babel/helper-plugin-utils': 7.27.1 15225 15226 - '@babel/plugin-transform-flow-strip-types@7.25.9(@babel/core@7.28.6)': 15227 dependencies: 15228 - '@babel/core': 7.28.6 15229 '@babel/helper-plugin-utils': 7.25.9 15230 - '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.28.6) 15231 15232 - '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.6)': 15233 dependencies: 15234 - '@babel/core': 7.28.6 15235 '@babel/helper-plugin-utils': 7.27.1 15236 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 15237 transitivePeerDependencies: 15238 - supports-color 15239 15240 - '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.6)': 15241 dependencies: 15242 - '@babel/core': 7.28.6 15243 - '@babel/helper-compilation-targets': 7.28.6 15244 '@babel/helper-plugin-utils': 7.27.1 15245 - '@babel/traverse': 7.28.6 15246 transitivePeerDependencies: 15247 - supports-color 15248 15249 - '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.6)': 15250 dependencies: 15251 - '@babel/core': 7.28.6 15252 '@babel/helper-plugin-utils': 7.27.1 15253 15254 - '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.28.6)': 15255 dependencies: 15256 - '@babel/core': 7.28.6 15257 '@babel/helper-plugin-utils': 7.27.1 15258 15259 - '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.6)': 15260 dependencies: 15261 - '@babel/core': 7.28.6 15262 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.6) 15263 '@babel/helper-plugin-utils': 7.27.1 15264 transitivePeerDependencies: 15265 - supports-color 15266 15267 - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.6)': 15268 dependencies: 15269 - '@babel/core': 7.28.6 15270 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6) 15271 '@babel/helper-plugin-utils': 7.27.1 15272 15273 - '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.6)': 15274 dependencies: 15275 - '@babel/core': 7.28.6 15276 '@babel/helper-plugin-utils': 7.27.1 15277 15278 - '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.6)': 15279 dependencies: 15280 - '@babel/core': 7.28.6 15281 '@babel/helper-plugin-utils': 7.27.1 15282 15283 - '@babel/plugin-transform-object-rest-spread@7.27.3(@babel/core@7.28.6)': 15284 dependencies: 15285 - '@babel/core': 7.28.6 15286 '@babel/helper-compilation-targets': 7.27.2 15287 '@babel/helper-plugin-utils': 7.27.1 15288 - '@babel/plugin-transform-destructuring': 7.27.3(@babel/core@7.28.6) 15289 - '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.28.6) 15290 15291 - '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.6)': 15292 dependencies: 15293 - '@babel/core': 7.28.6 15294 '@babel/helper-plugin-utils': 7.27.1 15295 15296 - '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.28.6)': 15297 dependencies: 15298 - '@babel/core': 7.28.6 15299 '@babel/helper-plugin-utils': 7.27.1 15300 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 15301 transitivePeerDependencies: 15302 - supports-color 15303 15304 - '@babel/plugin-transform-parameters@7.27.1(@babel/core@7.28.6)': 15305 dependencies: 15306 - '@babel/core': 7.28.6 15307 '@babel/helper-plugin-utils': 7.27.1 15308 15309 - '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.6)': 15310 dependencies: 15311 - '@babel/core': 7.28.6 15312 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.6) 15313 '@babel/helper-plugin-utils': 7.27.1 15314 transitivePeerDependencies: 15315 - supports-color 15316 15317 - '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.6)': 15318 dependencies: 15319 - '@babel/core': 7.28.6 15320 '@babel/helper-annotate-as-pure': 7.27.3 15321 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.6) 15322 '@babel/helper-plugin-utils': 7.27.1 15323 transitivePeerDependencies: 15324 - supports-color 15325 15326 - '@babel/plugin-transform-react-display-name@7.24.7(@babel/core@7.28.6)': 15327 dependencies: 15328 - '@babel/core': 7.28.6 15329 '@babel/helper-plugin-utils': 7.27.1 15330 15331 - '@babel/plugin-transform-react-jsx-development@7.24.7(@babel/core@7.28.6)': 15332 dependencies: 15333 - '@babel/core': 7.28.6 15334 - '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.28.6) 15335 transitivePeerDependencies: 15336 - supports-color 15337 15338 - '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.28.6)': 15339 dependencies: 15340 - '@babel/core': 7.28.6 15341 '@babel/helper-plugin-utils': 7.27.1 15342 15343 - '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.28.6)': 15344 dependencies: 15345 - '@babel/core': 7.28.6 15346 '@babel/helper-plugin-utils': 7.27.1 15347 15348 - '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.28.6)': 15349 dependencies: 15350 - '@babel/core': 7.28.6 15351 '@babel/helper-annotate-as-pure': 7.27.3 15352 '@babel/helper-module-imports': 7.27.1 15353 '@babel/helper-plugin-utils': 7.27.1 15354 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.28.6) 15355 - '@babel/types': 7.28.6 15356 transitivePeerDependencies: 15357 - supports-color 15358 15359 - '@babel/plugin-transform-react-pure-annotations@7.24.7(@babel/core@7.28.6)': 15360 dependencies: 15361 - '@babel/core': 7.28.6 15362 '@babel/helper-annotate-as-pure': 7.27.3 15363 '@babel/helper-plugin-utils': 7.27.1 15364 15365 - '@babel/plugin-transform-regenerator@7.27.1(@babel/core@7.28.6)': 15366 dependencies: 15367 - '@babel/core': 7.28.6 15368 '@babel/helper-plugin-utils': 7.27.1 15369 15370 - '@babel/plugin-transform-runtime@7.25.9(@babel/core@7.28.6)': 15371 dependencies: 15372 - '@babel/core': 7.28.6 15373 '@babel/helper-module-imports': 7.25.9 15374 '@babel/helper-plugin-utils': 7.25.9 15375 - babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.28.6) 15376 - babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.28.6) 15377 - babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.28.6) 15378 semver: 6.3.1 15379 transitivePeerDependencies: 15380 - supports-color 15381 15382 - '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.6)': 15383 dependencies: 15384 - '@babel/core': 7.28.6 15385 '@babel/helper-plugin-utils': 7.27.1 15386 15387 - '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.6)': 15388 dependencies: 15389 - '@babel/core': 7.28.6 15390 '@babel/helper-plugin-utils': 7.27.1 15391 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 15392 transitivePeerDependencies: 15393 - supports-color 15394 15395 - '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.6)': 15396 dependencies: 15397 - '@babel/core': 7.28.6 15398 '@babel/helper-plugin-utils': 7.27.1 15399 15400 - '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.6)': 15401 dependencies: 15402 - '@babel/core': 7.28.6 15403 '@babel/helper-plugin-utils': 7.27.1 15404 15405 - '@babel/plugin-transform-typescript@7.25.9(@babel/core@7.28.6)': 15406 dependencies: 15407 - '@babel/core': 7.28.6 15408 '@babel/helper-annotate-as-pure': 7.27.3 15409 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.6) 15410 '@babel/helper-plugin-utils': 7.27.1 15411 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 15412 - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.28.6) 15413 transitivePeerDependencies: 15414 - supports-color 15415 15416 - '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.6)': 15417 dependencies: 15418 - '@babel/core': 7.28.6 15419 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6) 15420 '@babel/helper-plugin-utils': 7.27.1 15421 15422 - '@babel/preset-react@7.24.7(@babel/core@7.28.6)': 15423 dependencies: 15424 - '@babel/core': 7.28.6 15425 '@babel/helper-plugin-utils': 7.27.1 15426 '@babel/helper-validator-option': 7.27.1 15427 - '@babel/plugin-transform-react-display-name': 7.24.7(@babel/core@7.28.6) 15428 - '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.28.6) 15429 - '@babel/plugin-transform-react-jsx-development': 7.24.7(@babel/core@7.28.6) 15430 - '@babel/plugin-transform-react-pure-annotations': 7.24.7(@babel/core@7.28.6) 15431 transitivePeerDependencies: 15432 - supports-color 15433 15434 - '@babel/preset-typescript@7.24.7(@babel/core@7.28.6)': 15435 dependencies: 15436 - '@babel/core': 7.28.6 15437 '@babel/helper-plugin-utils': 7.27.1 15438 '@babel/helper-validator-option': 7.27.1 15439 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.28.6) 15440 - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.6) 15441 - '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.28.6) 15442 transitivePeerDependencies: 15443 - supports-color 15444 ··· 15448 15449 '@babel/runtime@7.28.4': {} 15450 15451 '@babel/template@7.27.2': 15452 dependencies: 15453 '@babel/code-frame': 7.27.1 15454 '@babel/parser': 7.27.3 15455 - '@babel/types': 7.28.6 15456 - 15457 - '@babel/template@7.28.6': 15458 - dependencies: 15459 - '@babel/code-frame': 7.28.6 15460 - '@babel/parser': 7.28.6 15461 - '@babel/types': 7.28.6 15462 15463 - '@babel/traverse@7.27.3': 15464 dependencies: 15465 - '@babel/code-frame': 7.28.6 15466 - '@babel/generator': 7.28.6 15467 - '@babel/parser': 7.28.6 15468 - '@babel/template': 7.28.6 15469 - '@babel/types': 7.28.6 15470 debug: 4.4.0(supports-color@5.5.0) 15471 globals: 11.12.0 15472 transitivePeerDependencies: 15473 - supports-color 15474 15475 - '@babel/traverse@7.28.6': 15476 dependencies: 15477 - '@babel/code-frame': 7.28.6 15478 - '@babel/generator': 7.28.6 15479 - '@babel/helper-globals': 7.28.0 15480 - '@babel/parser': 7.28.6 15481 - '@babel/template': 7.28.6 15482 - '@babel/types': 7.28.6 15483 debug: 4.4.0(supports-color@5.5.0) 15484 transitivePeerDependencies: 15485 - supports-color 15486 ··· 15494 '@babel/helper-string-parser': 7.27.1 15495 '@babel/helper-validator-identifier': 7.27.1 15496 15497 - '@babel/types@7.28.6': 15498 - dependencies: 15499 - '@babel/helper-string-parser': 7.27.1 15500 - '@babel/helper-validator-identifier': 7.28.5 15501 - 15502 - '@bacons/text-decoder@0.0.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))': 15503 dependencies: 15504 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 15505 15506 '@capsizecss/unpack@2.4.0(encoding@0.1.13)': 15507 dependencies: ··· 15529 '@cbor-extract/cbor-extract-win32-x64@2.2.0': 15530 optional: true 15531 15532 - '@config-plugins/react-native-webrtc@10.0.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))': 15533 dependencies: 15534 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 15535 15536 - '@craftzdog/react-native-buffer@6.0.5(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 15537 dependencies: 15538 ieee754: 1.2.1 15539 - react-native-quick-base64: 2.1.2(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 15540 transitivePeerDependencies: 15541 - react 15542 - react-native ··· 15640 '@malept/cross-spawn-promise': 2.0.0 15641 chalk: 4.1.2 15642 debug: 4.4.0(supports-color@5.5.0) 15643 - fast-glob: 3.3.3 15644 filenamify: 4.3.0 15645 find-up: 5.0.0 15646 fs-extra: 10.1.0 ··· 16023 '@esbuild/aix-ppc64@0.25.3': 16024 optional: true 16025 16026 - '@esbuild/aix-ppc64@0.27.2': 16027 - optional: true 16028 - 16029 '@esbuild/android-arm64@0.25.3': 16030 - optional: true 16031 - 16032 - '@esbuild/android-arm64@0.27.2': 16033 optional: true 16034 16035 '@esbuild/android-arm@0.25.3': 16036 optional: true 16037 16038 - '@esbuild/android-arm@0.27.2': 16039 - optional: true 16040 - 16041 '@esbuild/android-x64@0.25.3': 16042 optional: true 16043 16044 - '@esbuild/android-x64@0.27.2': 16045 - optional: true 16046 - 16047 '@esbuild/darwin-arm64@0.25.3': 16048 optional: true 16049 16050 - '@esbuild/darwin-arm64@0.27.2': 16051 - optional: true 16052 - 16053 '@esbuild/darwin-x64@0.25.3': 16054 optional: true 16055 16056 - '@esbuild/darwin-x64@0.27.2': 16057 - optional: true 16058 - 16059 '@esbuild/freebsd-arm64@0.25.3': 16060 - optional: true 16061 - 16062 - '@esbuild/freebsd-arm64@0.27.2': 16063 optional: true 16064 16065 '@esbuild/freebsd-x64@0.25.3': 16066 optional: true 16067 16068 - '@esbuild/freebsd-x64@0.27.2': 16069 - optional: true 16070 - 16071 '@esbuild/linux-arm64@0.25.3': 16072 optional: true 16073 16074 - '@esbuild/linux-arm64@0.27.2': 16075 - optional: true 16076 - 16077 '@esbuild/linux-arm@0.25.3': 16078 optional: true 16079 16080 - '@esbuild/linux-arm@0.27.2': 16081 - optional: true 16082 - 16083 '@esbuild/linux-ia32@0.25.3': 16084 optional: true 16085 16086 - '@esbuild/linux-ia32@0.27.2': 16087 - optional: true 16088 - 16089 '@esbuild/linux-loong64@0.25.3': 16090 - optional: true 16091 - 16092 - '@esbuild/linux-loong64@0.27.2': 16093 optional: true 16094 16095 '@esbuild/linux-mips64el@0.25.3': 16096 optional: true 16097 16098 - '@esbuild/linux-mips64el@0.27.2': 16099 - optional: true 16100 - 16101 '@esbuild/linux-ppc64@0.25.3': 16102 optional: true 16103 16104 - '@esbuild/linux-ppc64@0.27.2': 16105 - optional: true 16106 - 16107 '@esbuild/linux-riscv64@0.25.3': 16108 - optional: true 16109 - 16110 - '@esbuild/linux-riscv64@0.27.2': 16111 optional: true 16112 16113 '@esbuild/linux-s390x@0.25.3': 16114 optional: true 16115 16116 - '@esbuild/linux-s390x@0.27.2': 16117 - optional: true 16118 - 16119 '@esbuild/linux-x64@0.25.3': 16120 optional: true 16121 16122 - '@esbuild/linux-x64@0.27.2': 16123 - optional: true 16124 - 16125 '@esbuild/netbsd-arm64@0.25.3': 16126 optional: true 16127 16128 - '@esbuild/netbsd-arm64@0.27.2': 16129 - optional: true 16130 - 16131 '@esbuild/netbsd-x64@0.25.3': 16132 optional: true 16133 16134 - '@esbuild/netbsd-x64@0.27.2': 16135 - optional: true 16136 - 16137 '@esbuild/openbsd-arm64@0.25.3': 16138 optional: true 16139 16140 - '@esbuild/openbsd-arm64@0.27.2': 16141 - optional: true 16142 - 16143 '@esbuild/openbsd-x64@0.25.3': 16144 optional: true 16145 16146 - '@esbuild/openbsd-x64@0.27.2': 16147 - optional: true 16148 - 16149 - '@esbuild/openharmony-arm64@0.27.2': 16150 - optional: true 16151 - 16152 '@esbuild/sunos-x64@0.25.3': 16153 - optional: true 16154 - 16155 - '@esbuild/sunos-x64@0.27.2': 16156 optional: true 16157 16158 '@esbuild/win32-arm64@0.25.3': 16159 optional: true 16160 16161 - '@esbuild/win32-arm64@0.27.2': 16162 - optional: true 16163 - 16164 '@esbuild/win32-ia32@0.25.3': 16165 optional: true 16166 16167 - '@esbuild/win32-ia32@0.27.2': 16168 - optional: true 16169 - 16170 '@esbuild/win32-x64@0.25.3': 16171 - optional: true 16172 - 16173 - '@esbuild/win32-x64@0.27.2': 16174 optional: true 16175 16176 '@eslint-community/eslint-utils@4.4.1(eslint@9.14.0(jiti@2.6.1))': ··· 16442 16443 '@expo/metro-config@0.19.4': 16444 dependencies: 16445 - '@babel/core': 7.28.6 16446 '@babel/generator': 7.26.2 16447 '@babel/parser': 7.26.2 16448 '@babel/types': 7.26.0 ··· 16458 jsc-safe-url: 0.2.4 16459 lightningcss: 1.27.0 16460 minimatch: 3.1.2 16461 - postcss: 8.4.49 16462 resolve-from: 5.0.0 16463 transitivePeerDependencies: 16464 - supports-color 16465 16466 '@expo/metro-config@0.20.14': 16467 dependencies: 16468 - '@babel/core': 7.28.6 16469 '@babel/generator': 7.27.3 16470 '@babel/parser': 7.27.3 16471 '@babel/types': 7.27.3 ··· 16482 jsc-safe-url: 0.2.4 16483 lightningcss: 1.27.0 16484 minimatch: 9.0.5 16485 - postcss: 8.4.49 16486 resolve-from: 5.0.0 16487 transitivePeerDependencies: 16488 - supports-color 16489 16490 - '@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))': 16491 dependencies: 16492 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 16493 16494 '@expo/osascript@2.2.4': 16495 dependencies: ··· 17028 - supports-color 17029 optional: true 17030 17031 - '@gorhom/bottom-sheet@5.1.6(@types/react@19.0.0)(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 17032 dependencies: 17033 - '@gorhom/portal': 1.0.14(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 17034 invariant: 2.2.4 17035 react: 19.0.0 17036 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 17037 - react-native-gesture-handler: 2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 17038 - react-native-reanimated: 3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 17039 optionalDependencies: 17040 - '@types/react': 19.0.0 17041 17042 - '@gorhom/portal@1.0.14(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 17043 dependencies: 17044 nanoid: 3.3.11 17045 react: 19.0.0 17046 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 17047 17048 '@grpc/grpc-js@1.10.10': 17049 dependencies: ··· 17367 17368 '@jest/transform@29.7.0': 17369 dependencies: 17370 - '@babel/core': 7.28.6 17371 '@jest/types': 29.6.3 17372 '@jridgewell/trace-mapping': 0.3.25 17373 babel-plugin-istanbul: 6.1.1 ··· 17394 '@types/yargs': 17.0.32 17395 chalk: 4.1.2 17396 17397 - '@jridgewell/gen-mapping@0.3.13': 17398 - dependencies: 17399 - '@jridgewell/sourcemap-codec': 1.5.0 17400 - '@jridgewell/trace-mapping': 0.3.31 17401 - 17402 '@jridgewell/gen-mapping@0.3.5': 17403 dependencies: 17404 '@jridgewell/set-array': 1.2.1 17405 '@jridgewell/sourcemap-codec': 1.5.0 17406 '@jridgewell/trace-mapping': 0.3.25 17407 17408 - '@jridgewell/remapping@2.3.5': 17409 - dependencies: 17410 - '@jridgewell/gen-mapping': 0.3.13 17411 - '@jridgewell/trace-mapping': 0.3.31 17412 - 17413 '@jridgewell/resolve-uri@3.1.2': {} 17414 17415 '@jridgewell/set-array@1.2.1': {} 17416 17417 '@jridgewell/source-map@0.3.6': 17418 dependencies: 17419 - '@jridgewell/gen-mapping': 0.3.13 17420 - '@jridgewell/trace-mapping': 0.3.31 17421 17422 '@jridgewell/sourcemap-codec@1.5.0': {} 17423 17424 '@jridgewell/trace-mapping@0.3.25': 17425 - dependencies: 17426 - '@jridgewell/resolve-uri': 3.1.2 17427 - '@jridgewell/sourcemap-codec': 1.5.0 17428 - 17429 - '@jridgewell/trace-mapping@0.3.31': 17430 dependencies: 17431 '@jridgewell/resolve-uri': 3.1.2 17432 '@jridgewell/sourcemap-codec': 1.5.0 ··· 17956 17957 '@radix-ui/primitive@1.1.3': {} 17958 17959 - '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17960 dependencies: 17961 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17962 react: 19.0.0 17963 react-dom: 19.0.0(react@19.0.0) 17964 optionalDependencies: 17965 - '@types/react': 19.0.0 17966 - '@types/react-dom': 19.0.0 17967 17968 - '@radix-ui/react-collection@1.1.7(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17969 dependencies: 17970 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.0)(react@19.0.0) 17971 - '@radix-ui/react-context': 1.1.2(@types/react@19.0.0)(react@19.0.0) 17972 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17973 - '@radix-ui/react-slot': 1.2.3(@types/react@19.0.0)(react@19.0.0) 17974 react: 19.0.0 17975 react-dom: 19.0.0(react@19.0.0) 17976 optionalDependencies: 17977 - '@types/react': 19.0.0 17978 - '@types/react-dom': 19.0.0 17979 17980 - '@radix-ui/react-compose-refs@1.1.2(@types/react@19.0.0)(react@19.0.0)': 17981 dependencies: 17982 react: 19.0.0 17983 optionalDependencies: 17984 - '@types/react': 19.0.0 17985 17986 - '@radix-ui/react-context@1.1.2(@types/react@19.0.0)(react@19.0.0)': 17987 dependencies: 17988 react: 19.0.0 17989 optionalDependencies: 17990 - '@types/react': 19.0.0 17991 17992 - '@radix-ui/react-direction@1.1.1(@types/react@19.0.0)(react@19.0.0)': 17993 dependencies: 17994 react: 19.0.0 17995 optionalDependencies: 17996 - '@types/react': 19.0.0 17997 17998 - '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17999 dependencies: 18000 '@radix-ui/primitive': 1.1.3 18001 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18002 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18003 - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18004 - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18005 react: 19.0.0 18006 react-dom: 19.0.0(react@19.0.0) 18007 optionalDependencies: 18008 - '@types/react': 19.0.0 18009 - '@types/react-dom': 19.0.0 18010 18011 - '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 18012 dependencies: 18013 '@radix-ui/primitive': 1.1.3 18014 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18015 - '@radix-ui/react-context': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18016 - '@radix-ui/react-id': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18017 - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18018 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18019 - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.0.0)(react@19.0.0) 18020 react: 19.0.0 18021 react-dom: 19.0.0(react@19.0.0) 18022 optionalDependencies: 18023 - '@types/react': 19.0.0 18024 - '@types/react-dom': 19.0.0 18025 18026 - '@radix-ui/react-focus-guards@1.1.3(@types/react@19.0.0)(react@19.0.0)': 18027 dependencies: 18028 react: 19.0.0 18029 optionalDependencies: 18030 - '@types/react': 19.0.0 18031 18032 - '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 18033 dependencies: 18034 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18035 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18036 - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18037 react: 19.0.0 18038 react-dom: 19.0.0(react@19.0.0) 18039 optionalDependencies: 18040 - '@types/react': 19.0.0 18041 - '@types/react-dom': 19.0.0 18042 18043 - '@radix-ui/react-id@1.1.1(@types/react@19.0.0)(react@19.0.0)': 18044 dependencies: 18045 - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18046 react: 19.0.0 18047 optionalDependencies: 18048 - '@types/react': 19.0.0 18049 18050 - '@radix-ui/react-menu@2.1.16(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 18051 dependencies: 18052 '@radix-ui/primitive': 1.1.3 18053 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18054 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18055 - '@radix-ui/react-context': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18056 - '@radix-ui/react-direction': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18057 - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18058 - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.0.0)(react@19.0.0) 18059 - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18060 - '@radix-ui/react-id': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18061 - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18062 - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18063 - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18064 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18065 - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18066 - '@radix-ui/react-slot': 1.2.3(@types/react@19.0.0)(react@19.0.0) 18067 - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18068 aria-hidden: 1.2.4 18069 react: 19.0.0 18070 react-dom: 19.0.0(react@19.0.0) 18071 - react-remove-scroll: 2.7.1(@types/react@19.0.0)(react@19.0.0) 18072 optionalDependencies: 18073 - '@types/react': 19.0.0 18074 - '@types/react-dom': 19.0.0 18075 18076 - '@radix-ui/react-popper@1.2.8(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 18077 dependencies: 18078 '@floating-ui/react-dom': 2.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18079 - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18080 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18081 - '@radix-ui/react-context': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18082 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18083 - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18084 - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18085 - '@radix-ui/react-use-rect': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18086 - '@radix-ui/react-use-size': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18087 '@radix-ui/rect': 1.1.1 18088 react: 19.0.0 18089 react-dom: 19.0.0(react@19.0.0) 18090 optionalDependencies: 18091 - '@types/react': 19.0.0 18092 - '@types/react-dom': 19.0.0 18093 18094 - '@radix-ui/react-portal@1.1.9(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 18095 dependencies: 18096 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18097 - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18098 react: 19.0.0 18099 react-dom: 19.0.0(react@19.0.0) 18100 optionalDependencies: 18101 - '@types/react': 19.0.0 18102 - '@types/react-dom': 19.0.0 18103 18104 - '@radix-ui/react-presence@1.1.5(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 18105 dependencies: 18106 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18107 - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18108 react: 19.0.0 18109 react-dom: 19.0.0(react@19.0.0) 18110 optionalDependencies: 18111 - '@types/react': 19.0.0 18112 - '@types/react-dom': 19.0.0 18113 18114 - '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 18115 dependencies: 18116 - '@radix-ui/react-slot': 1.2.3(@types/react@19.0.0)(react@19.0.0) 18117 react: 19.0.0 18118 react-dom: 19.0.0(react@19.0.0) 18119 optionalDependencies: 18120 - '@types/react': 19.0.0 18121 - '@types/react-dom': 19.0.0 18122 18123 - '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 18124 dependencies: 18125 '@radix-ui/primitive': 1.1.3 18126 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18127 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18128 - '@radix-ui/react-context': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18129 - '@radix-ui/react-direction': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18130 - '@radix-ui/react-id': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18131 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18132 - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18133 - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.0.0)(react@19.0.0) 18134 react: 19.0.0 18135 react-dom: 19.0.0(react@19.0.0) 18136 optionalDependencies: 18137 - '@types/react': 19.0.0 18138 - '@types/react-dom': 19.0.0 18139 18140 - '@radix-ui/react-slider@1.3.5(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 18141 dependencies: 18142 '@radix-ui/number': 1.1.1 18143 '@radix-ui/primitive': 1.1.2 18144 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18145 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18146 - '@radix-ui/react-context': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18147 - '@radix-ui/react-direction': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18148 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18149 - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.0.0)(react@19.0.0) 18150 - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18151 - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18152 - '@radix-ui/react-use-size': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18153 react: 19.0.0 18154 react-dom: 19.0.0(react@19.0.0) 18155 optionalDependencies: 18156 - '@types/react': 19.0.0 18157 - '@types/react-dom': 19.0.0 18158 18159 - '@radix-ui/react-slot@1.2.3(@types/react@19.0.0)(react@19.0.0)': 18160 dependencies: 18161 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.0)(react@19.0.0) 18162 react: 19.0.0 18163 optionalDependencies: 18164 - '@types/react': 19.0.0 18165 18166 - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.0.0)(react@19.0.0)': 18167 dependencies: 18168 react: 19.0.0 18169 optionalDependencies: 18170 - '@types/react': 19.0.0 18171 18172 - '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.0.0)(react@19.0.0)': 18173 dependencies: 18174 - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.0.0)(react@19.0.0) 18175 - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18176 react: 19.0.0 18177 optionalDependencies: 18178 - '@types/react': 19.0.0 18179 18180 - '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.0.0)(react@19.0.0)': 18181 dependencies: 18182 - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18183 react: 19.0.0 18184 optionalDependencies: 18185 - '@types/react': 19.0.0 18186 18187 - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.0.0)(react@19.0.0)': 18188 dependencies: 18189 - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18190 react: 19.0.0 18191 optionalDependencies: 18192 - '@types/react': 19.0.0 18193 18194 - '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.0.0)(react@19.0.0)': 18195 dependencies: 18196 react: 19.0.0 18197 optionalDependencies: 18198 - '@types/react': 19.0.0 18199 18200 - '@radix-ui/react-use-previous@1.1.1(@types/react@19.0.0)(react@19.0.0)': 18201 dependencies: 18202 react: 19.0.0 18203 optionalDependencies: 18204 - '@types/react': 19.0.0 18205 18206 - '@radix-ui/react-use-rect@1.1.1(@types/react@19.0.0)(react@19.0.0)': 18207 dependencies: 18208 '@radix-ui/rect': 1.1.1 18209 react: 19.0.0 18210 optionalDependencies: 18211 - '@types/react': 19.0.0 18212 18213 - '@radix-ui/react-use-size@1.1.1(@types/react@19.0.0)(react@19.0.0)': 18214 dependencies: 18215 - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.0)(react@19.0.0) 18216 react: 19.0.0 18217 optionalDependencies: 18218 - '@types/react': 19.0.0 18219 18220 '@radix-ui/rect@1.1.1': {} 18221 18222 - '@react-native-firebase/app@22.2.1(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18223 dependencies: 18224 firebase: 11.3.1 18225 react: 19.0.0 18226 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18227 optionalDependencies: 18228 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 18229 transitivePeerDependencies: 18230 - '@react-native-async-storage/async-storage' 18231 18232 - '@react-native-firebase/messaging@22.2.1(a0b2fe09fd8d447d016daffd4232dc3c)': 18233 dependencies: 18234 - '@react-native-firebase/app': 22.2.1(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18235 optionalDependencies: 18236 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 18237 18238 '@react-native/assets-registry@0.79.3': {} 18239 18240 - '@react-native/babel-plugin-codegen@0.79.0-rc.4(@babel/core@7.28.6)': 18241 dependencies: 18242 - '@babel/traverse': 7.28.6 18243 - '@react-native/codegen': 0.79.0-rc.4(@babel/core@7.28.6) 18244 transitivePeerDependencies: 18245 - '@babel/core' 18246 - supports-color 18247 18248 - '@react-native/babel-plugin-codegen@0.79.3(@babel/core@7.28.6)': 18249 dependencies: 18250 - '@babel/traverse': 7.28.6 18251 - '@react-native/codegen': 0.79.3(@babel/core@7.28.6) 18252 transitivePeerDependencies: 18253 - '@babel/core' 18254 - supports-color 18255 18256 - '@react-native/babel-preset@0.79.0-rc.4(@babel/core@7.28.6)': 18257 dependencies: 18258 - '@babel/core': 7.28.6 18259 - '@babel/plugin-proposal-export-default-from': 7.25.9(@babel/core@7.28.6) 18260 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.6) 18261 - '@babel/plugin-syntax-export-default-from': 7.25.9(@babel/core@7.28.6) 18262 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6) 18263 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6) 18264 - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.6) 18265 - '@babel/plugin-transform-async-generator-functions': 7.27.1(@babel/core@7.28.6) 18266 - '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.6) 18267 - '@babel/plugin-transform-block-scoping': 7.27.3(@babel/core@7.28.6) 18268 - '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.6) 18269 - '@babel/plugin-transform-classes': 7.27.1(@babel/core@7.28.6) 18270 - '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.6) 18271 - '@babel/plugin-transform-destructuring': 7.27.3(@babel/core@7.28.6) 18272 - '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.28.6) 18273 - '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.6) 18274 - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.6) 18275 - '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.6) 18276 - '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.28.6) 18277 - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.6) 18278 - '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.6) 18279 - '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.6) 18280 - '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.6) 18281 - '@babel/plugin-transform-object-rest-spread': 7.27.3(@babel/core@7.28.6) 18282 - '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.6) 18283 - '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.6) 18284 - '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.28.6) 18285 - '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.6) 18286 - '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.6) 18287 - '@babel/plugin-transform-react-display-name': 7.24.7(@babel/core@7.28.6) 18288 - '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.28.6) 18289 - '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.28.6) 18290 - '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.28.6) 18291 - '@babel/plugin-transform-regenerator': 7.27.1(@babel/core@7.28.6) 18292 - '@babel/plugin-transform-runtime': 7.25.9(@babel/core@7.28.6) 18293 - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.6) 18294 - '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.6) 18295 - '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.6) 18296 - '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.28.6) 18297 - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.6) 18298 '@babel/template': 7.27.2 18299 - '@react-native/babel-plugin-codegen': 0.79.0-rc.4(@babel/core@7.28.6) 18300 babel-plugin-syntax-hermes-parser: 0.25.1 18301 - babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.28.6) 18302 react-refresh: 0.14.2 18303 transitivePeerDependencies: 18304 - supports-color 18305 18306 - '@react-native/babel-preset@0.79.3(@babel/core@7.28.6)': 18307 dependencies: 18308 - '@babel/core': 7.28.6 18309 - '@babel/plugin-proposal-export-default-from': 7.25.9(@babel/core@7.28.6) 18310 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.6) 18311 - '@babel/plugin-syntax-export-default-from': 7.25.9(@babel/core@7.28.6) 18312 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6) 18313 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6) 18314 - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.6) 18315 - '@babel/plugin-transform-async-generator-functions': 7.27.1(@babel/core@7.28.6) 18316 - '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.6) 18317 - '@babel/plugin-transform-block-scoping': 7.27.3(@babel/core@7.28.6) 18318 - '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.6) 18319 - '@babel/plugin-transform-classes': 7.27.1(@babel/core@7.28.6) 18320 - '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.6) 18321 - '@babel/plugin-transform-destructuring': 7.27.3(@babel/core@7.28.6) 18322 - '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.28.6) 18323 - '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.6) 18324 - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.6) 18325 - '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.6) 18326 - '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.28.6) 18327 - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.6) 18328 - '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.6) 18329 - '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.6) 18330 - '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.6) 18331 - '@babel/plugin-transform-object-rest-spread': 7.27.3(@babel/core@7.28.6) 18332 - '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.6) 18333 - '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.6) 18334 - '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.28.6) 18335 - '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.6) 18336 - '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.6) 18337 - '@babel/plugin-transform-react-display-name': 7.24.7(@babel/core@7.28.6) 18338 - '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.28.6) 18339 - '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.28.6) 18340 - '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.28.6) 18341 - '@babel/plugin-transform-regenerator': 7.27.1(@babel/core@7.28.6) 18342 - '@babel/plugin-transform-runtime': 7.25.9(@babel/core@7.28.6) 18343 - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.6) 18344 - '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.6) 18345 - '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.6) 18346 - '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.28.6) 18347 - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.6) 18348 - '@babel/template': 7.28.6 18349 - '@react-native/babel-plugin-codegen': 0.79.3(@babel/core@7.28.6) 18350 babel-plugin-syntax-hermes-parser: 0.25.1 18351 - babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.28.6) 18352 react-refresh: 0.14.2 18353 transitivePeerDependencies: 18354 - supports-color 18355 18356 - '@react-native/codegen@0.79.0-rc.4(@babel/core@7.28.6)': 18357 dependencies: 18358 - '@babel/core': 7.28.6 18359 glob: 7.2.3 18360 hermes-parser: 0.25.1 18361 invariant: 2.2.4 18362 nullthrows: 1.1.1 18363 yargs: 17.7.2 18364 18365 - '@react-native/codegen@0.79.3(@babel/core@7.28.6)': 18366 dependencies: 18367 - '@babel/core': 7.28.6 18368 glob: 7.2.3 18369 hermes-parser: 0.25.1 18370 invariant: 2.2.4 ··· 18416 18417 '@react-native/normalize-colors@0.79.3': {} 18418 18419 - '@react-native/virtualized-lists@0.79.3(@types/react@19.0.0)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18420 dependencies: 18421 invariant: 2.2.4 18422 nullthrows: 1.1.1 18423 react: 19.0.0 18424 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18425 optionalDependencies: 18426 - '@types/react': 19.0.0 18427 18428 - '@react-navigation/bottom-tabs@6.6.1(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18429 dependencies: 18430 - '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18431 - '@react-navigation/native': 6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18432 color: 4.2.3 18433 react: 19.0.0 18434 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18435 - react-native-safe-area-context: 5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18436 - react-native-screens: 4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18437 warn-once: 0.1.1 18438 18439 '@react-navigation/core@6.4.17(react@19.0.0)': ··· 18446 react-is: 16.13.1 18447 use-latest-callback: 0.2.1(react@19.0.0) 18448 18449 - '@react-navigation/drawer@6.7.2(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18450 dependencies: 18451 - '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18452 - '@react-navigation/native': 6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18453 color: 4.2.3 18454 react: 19.0.0 18455 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18456 - react-native-gesture-handler: 2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18457 - react-native-reanimated: 3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18458 - react-native-safe-area-context: 5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18459 - react-native-screens: 4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18460 warn-once: 0.1.1 18461 18462 - '@react-navigation/elements@1.3.31(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18463 dependencies: 18464 - '@react-navigation/native': 6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18465 react: 19.0.0 18466 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18467 - react-native-safe-area-context: 5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18468 18469 - '@react-navigation/native-stack@6.11.0(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18470 dependencies: 18471 - '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18472 - '@react-navigation/native': 6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18473 react: 19.0.0 18474 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18475 - react-native-safe-area-context: 5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18476 - react-native-screens: 4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18477 warn-once: 0.1.1 18478 18479 - '@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18480 dependencies: 18481 '@react-navigation/core': 6.4.17(react@19.0.0) 18482 escape-string-regexp: 4.0.0 18483 fast-deep-equal: 3.1.3 18484 nanoid: 3.3.11 18485 react: 19.0.0 18486 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18487 18488 '@react-navigation/routers@6.1.9': 18489 dependencies: ··· 18491 18492 '@readme/better-ajv-errors@1.6.0(ajv@8.16.0)': 18493 dependencies: 18494 - '@babel/code-frame': 7.28.6 18495 '@babel/runtime': 7.26.0 18496 '@humanwhocodes/momoa': 2.0.4 18497 ajv: 8.16.0 ··· 18502 18503 '@readme/better-ajv-errors@2.3.2(ajv@8.16.0)': 18504 dependencies: 18505 - '@babel/code-frame': 7.28.6 18506 '@babel/runtime': 7.26.0 18507 '@humanwhocodes/momoa': 2.0.4 18508 ajv: 8.16.0 ··· 18555 18556 '@reforged/maker-types@1.0.1': {} 18557 18558 - '@rn-primitives/dropdown-menu@1.2.0(@rn-primitives/portal@1.3.0(@types/react@19.0.0)(immer@10.1.1)(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(use-sync-external-store@1.6.0(react@19.0.0)))(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18559 dependencies: 18560 - '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18561 - '@rn-primitives/hooks': 1.3.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18562 - '@rn-primitives/portal': 1.3.0(@types/react@19.0.0)(immer@10.1.1)(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(use-sync-external-store@1.6.0(react@19.0.0)) 18563 - '@rn-primitives/slot': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18564 - '@rn-primitives/types': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18565 - '@rn-primitives/utils': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18566 react: 19.0.0 18567 optionalDependencies: 18568 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18569 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18570 transitivePeerDependencies: 18571 - '@types/react' 18572 - '@types/react-dom' 18573 - react-dom 18574 18575 - '@rn-primitives/hooks@1.3.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18576 dependencies: 18577 - '@rn-primitives/types': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18578 react: 19.0.0 18579 optionalDependencies: 18580 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18581 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18582 18583 - '@rn-primitives/portal@1.3.0(@types/react@19.0.0)(immer@10.1.1)(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(use-sync-external-store@1.6.0(react@19.0.0))': 18584 dependencies: 18585 react: 19.0.0 18586 - zustand: 5.0.5(@types/react@19.0.0)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.6.0(react@19.0.0)) 18587 optionalDependencies: 18588 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18589 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18590 transitivePeerDependencies: 18591 - '@types/react' 18592 - immer 18593 - use-sync-external-store 18594 18595 - '@rn-primitives/slider@1.2.0(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18596 dependencies: 18597 - '@radix-ui/react-slider': 1.3.5(@types/react-dom@19.0.0)(@types/react@19.0.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18598 - '@rn-primitives/slot': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18599 - '@rn-primitives/types': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18600 react: 19.0.0 18601 optionalDependencies: 18602 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18603 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18604 transitivePeerDependencies: 18605 - '@types/react' 18606 - '@types/react-dom' 18607 - react-dom 18608 18609 - '@rn-primitives/slot@1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18610 dependencies: 18611 react: 19.0.0 18612 optionalDependencies: 18613 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18614 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18615 18616 - '@rn-primitives/types@1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18617 dependencies: 18618 react: 19.0.0 18619 optionalDependencies: 18620 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18621 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18622 18623 - '@rn-primitives/utils@1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18624 dependencies: 18625 react: 19.0.0 18626 optionalDependencies: 18627 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18628 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18629 18630 '@rollup/pluginutils@5.1.4(rollup@4.40.1)': ··· 18786 18787 '@sentry/core@8.54.0': {} 18788 18789 - '@sentry/react-native@6.14.0(encoding@0.1.13)(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18790 dependencies: 18791 '@sentry/babel-plugin-component-annotate': 3.4.0 18792 '@sentry/browser': 8.54.0 ··· 18796 '@sentry/types': 8.54.0 18797 '@sentry/utils': 8.54.0 18798 react: 19.0.0 18799 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18800 optionalDependencies: 18801 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 18802 transitivePeerDependencies: 18803 - encoding 18804 - supports-color ··· 19782 19783 '@types/normalize-package-data@2.4.4': {} 19784 19785 '@types/qrcode@1.5.5': 19786 dependencies: 19787 '@types/node': 22.15.17 ··· 19790 19791 '@types/range-parser@1.2.7': {} 19792 19793 - '@types/react-dom@19.0.0': 19794 dependencies: 19795 - '@types/react': 19.0.0 19796 19797 - '@types/react@19.0.0': 19798 dependencies: 19799 - csstype: 3.2.3 19800 19801 '@types/request@2.48.12': 19802 dependencies: ··· 19926 '@typescript-eslint/types': 8.13.0 19927 '@typescript-eslint/visitor-keys': 8.13.0 19928 debug: 4.4.0(supports-color@5.5.0) 19929 - fast-glob: 3.3.3 19930 is-glob: 4.0.3 19931 minimatch: 9.0.5 19932 semver: 7.7.1 ··· 20374 20375 astring@1.9.0: {} 20376 20377 - astro-expressive-code@0.41.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2)): 20378 dependencies: 20379 - astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2) 20380 rehype-expressive-code: 0.41.2 20381 20382 - astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2): 20383 dependencies: 20384 '@astrojs/compiler': 2.12.0 20385 '@astrojs/internal-helpers': 0.6.1 ··· 20432 unist-util-visit: 5.0.0 20433 unstorage: 1.16.0(idb-keyval@6.2.1)(ioredis@5.7.0) 20434 vfile: 6.0.3 20435 - vite: 6.3.4(@types/node@22.15.17)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.32.0)(tsx@4.21.0)(yaml@2.8.2) 20436 - vitefu: 1.0.6(vite@6.3.4(@types/node@22.15.17)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.32.0)(tsx@4.21.0)(yaml@2.8.2)) 20437 xxhash-wasm: 1.1.0 20438 yargs-parser: 21.1.1 20439 yocto-spinner: 0.2.2 ··· 20515 20516 b4a@1.6.7: {} 20517 20518 - babel-jest@29.7.0(@babel/core@7.28.6): 20519 dependencies: 20520 - '@babel/core': 7.28.6 20521 '@jest/transform': 29.7.0 20522 '@types/babel__core': 7.20.5 20523 babel-plugin-istanbul: 6.1.1 20524 - babel-preset-jest: 29.6.3(@babel/core@7.28.6) 20525 chalk: 4.1.2 20526 graceful-fs: 4.2.11 20527 slash: 3.0.0 ··· 20540 20541 babel-plugin-jest-hoist@29.6.3: 20542 dependencies: 20543 - '@babel/template': 7.28.6 20544 - '@babel/types': 7.28.6 20545 '@types/babel__core': 7.20.5 20546 '@types/babel__traverse': 7.20.6 20547 20548 - babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.28.6): 20549 dependencies: 20550 '@babel/compat-data': 7.26.2 20551 - '@babel/core': 7.28.6 20552 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.28.6) 20553 semver: 6.3.1 20554 transitivePeerDependencies: 20555 - supports-color 20556 20557 - babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.28.6): 20558 dependencies: 20559 - '@babel/core': 7.28.6 20560 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.28.6) 20561 core-js-compat: 3.39.0 20562 transitivePeerDependencies: 20563 - supports-color 20564 20565 - babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.28.6): 20566 dependencies: 20567 - '@babel/core': 7.28.6 20568 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.28.6) 20569 transitivePeerDependencies: 20570 - supports-color 20571 ··· 20575 dependencies: 20576 hermes-parser: 0.25.1 20577 20578 - babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.28.6): 20579 dependencies: 20580 - '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.28.6) 20581 transitivePeerDependencies: 20582 - '@babel/core' 20583 20584 - babel-preset-current-node-syntax@1.1.0(@babel/core@7.28.6): 20585 dependencies: 20586 - '@babel/core': 7.28.6 20587 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.6) 20588 - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.6) 20589 - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.6) 20590 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.6) 20591 - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.6) 20592 - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.6) 20593 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.6) 20594 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.6) 20595 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6) 20596 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.6) 20597 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.6) 20598 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.6) 20599 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6) 20600 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.6) 20601 - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.6) 20602 20603 - babel-preset-expo@13.0.0(@babel/core@7.28.6): 20604 dependencies: 20605 '@babel/helper-module-imports': 7.27.1 20606 - '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.28.6) 20607 - '@babel/plugin-proposal-export-default-from': 7.25.9(@babel/core@7.28.6) 20608 - '@babel/plugin-syntax-export-default-from': 7.25.9(@babel/core@7.28.6) 20609 - '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.6) 20610 - '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.28.6) 20611 - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.6) 20612 - '@babel/plugin-transform-object-rest-spread': 7.27.3(@babel/core@7.28.6) 20613 - '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.28.6) 20614 - '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.6) 20615 - '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.6) 20616 - '@babel/plugin-transform-runtime': 7.25.9(@babel/core@7.28.6) 20617 - '@babel/preset-react': 7.24.7(@babel/core@7.28.6) 20618 - '@babel/preset-typescript': 7.24.7(@babel/core@7.28.6) 20619 - '@react-native/babel-preset': 0.79.0-rc.4(@babel/core@7.28.6) 20620 babel-plugin-react-native-web: 0.19.13 20621 babel-plugin-syntax-hermes-parser: 0.25.1 20622 - babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.28.6) 20623 debug: 4.4.0(supports-color@5.5.0) 20624 react-refresh: 0.14.2 20625 resolve-from: 5.0.0 ··· 20627 - '@babel/core' 20628 - supports-color 20629 20630 - babel-preset-expo@13.2.0(@babel/core@7.28.6): 20631 dependencies: 20632 '@babel/helper-module-imports': 7.27.1 20633 - '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.28.6) 20634 - '@babel/plugin-proposal-export-default-from': 7.25.9(@babel/core@7.28.6) 20635 - '@babel/plugin-syntax-export-default-from': 7.25.9(@babel/core@7.28.6) 20636 - '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.6) 20637 - '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.28.6) 20638 - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.6) 20639 - '@babel/plugin-transform-object-rest-spread': 7.27.3(@babel/core@7.28.6) 20640 - '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.28.6) 20641 - '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.6) 20642 - '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.6) 20643 - '@babel/plugin-transform-runtime': 7.25.9(@babel/core@7.28.6) 20644 - '@babel/preset-react': 7.24.7(@babel/core@7.28.6) 20645 - '@babel/preset-typescript': 7.24.7(@babel/core@7.28.6) 20646 - '@react-native/babel-preset': 0.79.3(@babel/core@7.28.6) 20647 babel-plugin-react-native-web: 0.19.13 20648 babel-plugin-syntax-hermes-parser: 0.25.1 20649 - babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.28.6) 20650 debug: 4.4.0(supports-color@5.5.0) 20651 react-refresh: 0.14.2 20652 resolve-from: 5.0.0 ··· 20654 - '@babel/core' 20655 - supports-color 20656 20657 - babel-preset-jest@29.6.3(@babel/core@7.28.6): 20658 dependencies: 20659 - '@babel/core': 7.28.6 20660 babel-plugin-jest-hoist: 29.6.3 20661 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.6) 20662 20663 badgin@1.2.3: {} 20664 ··· 20701 base64-arraybuffer@1.0.2: {} 20702 20703 base64-js@1.5.1: {} 20704 - 20705 - baseline-browser-mapping@2.9.14: {} 20706 20707 batch@0.6.1: {} 20708 ··· 20865 20866 browser-or-node@3.0.0: {} 20867 20868 browserslist@4.24.5: 20869 dependencies: 20870 caniuse-lite: 1.0.30001718 20871 electron-to-chromium: 1.5.159 20872 node-releases: 2.0.19 20873 update-browserslist-db: 1.1.3(browserslist@4.24.5) 20874 - 20875 - browserslist@4.28.1: 20876 - dependencies: 20877 - baseline-browser-mapping: 2.9.14 20878 - caniuse-lite: 1.0.30001764 20879 - electron-to-chromium: 1.5.267 20880 - node-releases: 2.0.27 20881 - update-browserslist-db: 1.2.3(browserslist@4.28.1) 20882 20883 bser@2.1.1: 20884 dependencies: ··· 20917 esbuild: 0.25.3 20918 load-tsconfig: 0.2.5 20919 20920 - burnt@0.12.2(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 20921 dependencies: 20922 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 20923 react: 19.0.0 20924 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 20925 sf-symbols-typescript: 1.0.0 20926 sonner: 0.3.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 20927 transitivePeerDependencies: ··· 21033 21034 camelize@1.0.1: {} 21035 21036 - caniuse-lite@1.0.30001718: {} 21037 21038 - caniuse-lite@1.0.30001764: {} 21039 21040 cbor-extract@2.2.0: 21041 dependencies: ··· 21474 21475 core-js-compat@3.39.0: 21476 dependencies: 21477 - browserslist: 4.24.5 21478 21479 core-util-is@1.0.3: {} 21480 ··· 21615 21616 cssesc@3.0.0: {} 21617 21618 - csstype@3.2.3: {} 21619 21620 dargs@7.0.0: {} 21621 ··· 21948 21949 electron-to-chromium@1.5.159: {} 21950 21951 - electron-to-chromium@1.5.267: {} 21952 21953 electron-winstaller@5.4.0: 21954 dependencies: ··· 22186 '@esbuild/win32-ia32': 0.25.3 22187 '@esbuild/win32-x64': 0.25.3 22188 22189 - esbuild@0.27.2: 22190 - optionalDependencies: 22191 - '@esbuild/aix-ppc64': 0.27.2 22192 - '@esbuild/android-arm': 0.27.2 22193 - '@esbuild/android-arm64': 0.27.2 22194 - '@esbuild/android-x64': 0.27.2 22195 - '@esbuild/darwin-arm64': 0.27.2 22196 - '@esbuild/darwin-x64': 0.27.2 22197 - '@esbuild/freebsd-arm64': 0.27.2 22198 - '@esbuild/freebsd-x64': 0.27.2 22199 - '@esbuild/linux-arm': 0.27.2 22200 - '@esbuild/linux-arm64': 0.27.2 22201 - '@esbuild/linux-ia32': 0.27.2 22202 - '@esbuild/linux-loong64': 0.27.2 22203 - '@esbuild/linux-mips64el': 0.27.2 22204 - '@esbuild/linux-ppc64': 0.27.2 22205 - '@esbuild/linux-riscv64': 0.27.2 22206 - '@esbuild/linux-s390x': 0.27.2 22207 - '@esbuild/linux-x64': 0.27.2 22208 - '@esbuild/netbsd-arm64': 0.27.2 22209 - '@esbuild/netbsd-x64': 0.27.2 22210 - '@esbuild/openbsd-arm64': 0.27.2 22211 - '@esbuild/openbsd-x64': 0.27.2 22212 - '@esbuild/openharmony-arm64': 0.27.2 22213 - '@esbuild/sunos-x64': 0.27.2 22214 - '@esbuild/win32-arm64': 0.27.2 22215 - '@esbuild/win32-ia32': 0.27.2 22216 - '@esbuild/win32-x64': 0.27.2 22217 - optional: true 22218 - 22219 escalade@3.2.0: {} 22220 22221 escape-html@1.0.3: {} ··· 22469 dependencies: 22470 homedir-polyfill: 1.0.3 22471 22472 - expo-application@6.1.4(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22473 dependencies: 22474 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22475 22476 - expo-asset@11.1.5(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22477 dependencies: 22478 '@expo/image-utils': 0.7.4 22479 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22480 - expo-constants: 17.1.6(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22481 react: 19.0.0 22482 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22483 transitivePeerDependencies: 22484 - supports-color 22485 22486 - expo-build-properties@0.14.6(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22487 dependencies: 22488 ajv: 8.16.0 22489 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22490 semver: 7.7.1 22491 22492 - expo-constants@17.1.6(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22493 dependencies: 22494 '@expo/config': 11.0.10 22495 '@expo/env': 1.0.5 22496 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22497 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22498 transitivePeerDependencies: 22499 - supports-color 22500 22501 - expo-dev-client@5.2.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22502 dependencies: 22503 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22504 - expo-dev-launcher: 5.1.12(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22505 - expo-dev-menu: 6.1.11(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22506 - expo-dev-menu-interface: 1.10.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22507 - expo-manifests: 0.16.5(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22508 - expo-updates-interface: 1.1.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22509 transitivePeerDependencies: 22510 - supports-color 22511 22512 - expo-dev-launcher@5.1.12(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22513 dependencies: 22514 ajv: 8.11.0 22515 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22516 - expo-dev-menu: 6.1.11(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22517 - expo-manifests: 0.16.5(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22518 resolve-from: 5.0.0 22519 transitivePeerDependencies: 22520 - supports-color 22521 22522 - expo-dev-menu-interface@1.10.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22523 dependencies: 22524 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22525 22526 - expo-dev-menu@6.1.11(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22527 dependencies: 22528 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22529 - expo-dev-menu-interface: 1.10.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22530 22531 expo-eas-client@0.14.3: {} 22532 22533 - expo-file-system@18.1.10(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22534 dependencies: 22535 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22536 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22537 22538 - expo-font@13.3.1(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22539 dependencies: 22540 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22541 fontfaceobserver: 2.3.0 22542 react: 19.0.0 22543 22544 expo-json-utils@0.15.0: {} 22545 22546 - expo-keep-awake@14.1.4(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22547 dependencies: 22548 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22549 react: 19.0.0 22550 22551 - expo-linking@7.1.5(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22552 dependencies: 22553 - expo-constants: 17.1.6(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22554 invariant: 2.2.4 22555 react: 19.0.0 22556 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22557 transitivePeerDependencies: 22558 - expo 22559 - supports-color 22560 22561 - expo-localization@17.0.7(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22562 dependencies: 22563 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22564 react: 19.0.0 22565 rtl-detect: 1.1.2 22566 22567 - expo-manifests@0.16.5(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22568 dependencies: 22569 '@expo/config': 11.0.10 22570 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22571 expo-json-utils: 0.15.0 22572 transitivePeerDependencies: 22573 - supports-color ··· 22586 dependencies: 22587 invariant: 2.2.4 22588 22589 - expo-notifications@0.31.3(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22590 dependencies: 22591 '@expo/image-utils': 0.7.4 22592 '@ide/backoff': 1.0.0 22593 abort-controller: 3.0.0 22594 assert: 2.1.0 22595 badgin: 1.2.3 22596 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22597 - expo-application: 6.1.4(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22598 - expo-constants: 17.1.6(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22599 react: 19.0.0 22600 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22601 transitivePeerDependencies: 22602 - supports-color 22603 22604 - expo-screen-orientation@9.0.7(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22605 dependencies: 22606 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22607 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22608 22609 - expo-sensors@15.0.7(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22610 dependencies: 22611 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22612 invariant: 2.2.4 22613 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22614 22615 - expo-splash-screen@0.30.9(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22616 dependencies: 22617 '@expo/prebuild-config': 9.0.6 22618 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22619 transitivePeerDependencies: 22620 - supports-color 22621 22622 - expo-sqlite@15.2.12(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22623 dependencies: 22624 await-lock: 2.2.2 22625 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22626 react: 19.0.0 22627 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22628 22629 expo-structured-headers@4.1.0: {} 22630 22631 - expo-system-ui@5.0.8(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22632 dependencies: 22633 '@react-native/normalize-colors': 0.79.3 22634 debug: 4.4.0(supports-color@5.5.0) 22635 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22636 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22637 optionalDependencies: 22638 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 22639 transitivePeerDependencies: 22640 - supports-color 22641 22642 - expo-updates-interface@1.1.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22643 dependencies: 22644 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22645 22646 - expo-updates@0.28.14(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22647 dependencies: 22648 '@expo/code-signing-certificates': 0.0.5 22649 '@expo/config': 11.0.10 ··· 22651 '@expo/spawn-async': 1.7.2 22652 arg: 4.1.0 22653 chalk: 4.1.2 22654 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22655 expo-eas-client: 0.14.3 22656 - expo-manifests: 0.16.5(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22657 expo-structured-headers: 4.1.0 22658 - expo-updates-interface: 1.1.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22659 glob: 10.4.5 22660 ignore: 5.3.1 22661 react: 19.0.0 ··· 22663 transitivePeerDependencies: 22664 - supports-color 22665 22666 - expo-video@2.2.1(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22667 dependencies: 22668 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22669 react: 19.0.0 22670 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22671 22672 - expo-web-browser@14.1.6(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22673 dependencies: 22674 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22675 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22676 22677 - expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10): 22678 dependencies: 22679 '@babel/runtime': 7.26.0 22680 '@expo/cli': 0.24.14(bufferutil@4.0.8)(utf-8-validate@5.0.10) ··· 22683 '@expo/fingerprint': 0.13.0 22684 '@expo/metro-config': 0.20.14 22685 '@expo/vector-icons': 14.0.4 22686 - babel-preset-expo: 13.2.0(@babel/core@7.28.6) 22687 - expo-asset: 11.1.5(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22688 - expo-constants: 17.1.6(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22689 - expo-file-system: 18.1.10(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22690 - expo-font: 13.3.1(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22691 - expo-keep-awake: 14.1.4(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22692 expo-modules-autolinking: 2.1.11 22693 expo-modules-core: 2.4.0 22694 react: 19.0.0 22695 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22696 - react-native-edge-to-edge: 1.6.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22697 whatwg-url-without-unicode: 8.0.0-3 22698 optionalDependencies: 22699 - '@expo/metro-runtime': 5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22700 - react-native-webview: 13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22701 transitivePeerDependencies: 22702 - '@babel/core' 22703 - babel-plugin-react-compiler ··· 23340 es-errors: 1.3.0 23341 get-intrinsic: 1.2.4 23342 23343 - get-tsconfig@4.13.0: 23344 - dependencies: 23345 - resolve-pkg-maps: 1.0.0 23346 - optional: true 23347 - 23348 getenv@1.0.0: {} 23349 23350 getenv@2.0.0: {} ··· 23593 has-flag@3.0.0: {} 23594 23595 has-flag@4.0.0: {} 23596 23597 has-property-descriptors@1.0.2: 23598 dependencies: ··· 24267 ipaddr.js@2.2.0: {} 24268 24269 iron-webcrypto@1.2.1: {} 24270 24271 is-alphabetical@2.0.1: {} 24272 ··· 24483 24484 istanbul-lib-instrument@5.2.1: 24485 dependencies: 24486 - '@babel/core': 7.28.6 24487 - '@babel/parser': 7.28.6 24488 '@istanbuljs/schema': 0.1.3 24489 istanbul-lib-coverage: 3.2.2 24490 semver: 6.3.1 ··· 24542 24543 jest-message-util@29.7.0: 24544 dependencies: 24545 - '@babel/code-frame': 7.28.6 24546 '@jest/types': 29.6.3 24547 '@types/stack-utils': 2.0.3 24548 chalk: 4.1.2 ··· 24908 transitivePeerDependencies: 24909 - supports-color 24910 24911 - lightningcss-android-arm64@1.30.2: 24912 - optional: true 24913 - 24914 lightningcss-darwin-arm64@1.27.0: 24915 optional: true 24916 24917 - lightningcss-darwin-arm64@1.30.2: 24918 optional: true 24919 24920 lightningcss-darwin-x64@1.27.0: 24921 optional: true 24922 24923 - lightningcss-darwin-x64@1.30.2: 24924 optional: true 24925 24926 lightningcss-freebsd-x64@1.27.0: 24927 optional: true 24928 24929 - lightningcss-freebsd-x64@1.30.2: 24930 optional: true 24931 24932 lightningcss-linux-arm-gnueabihf@1.27.0: 24933 optional: true 24934 24935 - lightningcss-linux-arm-gnueabihf@1.30.2: 24936 optional: true 24937 24938 lightningcss-linux-arm64-gnu@1.27.0: 24939 optional: true 24940 24941 - lightningcss-linux-arm64-gnu@1.30.2: 24942 optional: true 24943 24944 lightningcss-linux-arm64-musl@1.27.0: 24945 optional: true 24946 24947 - lightningcss-linux-arm64-musl@1.30.2: 24948 optional: true 24949 24950 lightningcss-linux-x64-gnu@1.27.0: 24951 optional: true 24952 24953 - lightningcss-linux-x64-gnu@1.30.2: 24954 optional: true 24955 24956 lightningcss-linux-x64-musl@1.27.0: 24957 optional: true 24958 24959 - lightningcss-linux-x64-musl@1.30.2: 24960 optional: true 24961 24962 lightningcss-win32-arm64-msvc@1.27.0: 24963 optional: true 24964 24965 - lightningcss-win32-arm64-msvc@1.30.2: 24966 optional: true 24967 24968 lightningcss-win32-x64-msvc@1.27.0: 24969 optional: true 24970 24971 - lightningcss-win32-x64-msvc@1.30.2: 24972 optional: true 24973 24974 lightningcss@1.27.0: ··· 24986 lightningcss-win32-arm64-msvc: 1.27.0 24987 lightningcss-win32-x64-msvc: 1.27.0 24988 24989 - lightningcss@1.30.2: 24990 dependencies: 24991 - detect-libc: 2.0.4 24992 optionalDependencies: 24993 - lightningcss-android-arm64: 1.30.2 24994 - lightningcss-darwin-arm64: 1.30.2 24995 - lightningcss-darwin-x64: 1.30.2 24996 - lightningcss-freebsd-x64: 1.30.2 24997 - lightningcss-linux-arm-gnueabihf: 1.30.2 24998 - lightningcss-linux-arm64-gnu: 1.30.2 24999 - lightningcss-linux-arm64-musl: 1.30.2 25000 - lightningcss-linux-x64-gnu: 1.30.2 25001 - lightningcss-linux-x64-musl: 1.30.2 25002 - lightningcss-win32-arm64-msvc: 1.30.2 25003 - lightningcss-win32-x64-msvc: 1.30.2 25004 optional: true 25005 25006 lilconfig@3.1.2: {} ··· 25193 lodash.clonedeep: 4.5.0 25194 lru-cache: 6.0.0 25195 25196 - lucide-react-native@0.514.0(react-native-svg@15.12.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 25197 dependencies: 25198 react: 19.0.0 25199 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 25200 - react-native-svg: 15.12.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 25201 25202 macos-alias@0.2.11: 25203 dependencies: ··· 25211 magicast@0.3.5: 25212 dependencies: 25213 '@babel/parser': 7.26.2 25214 - '@babel/types': 7.27.3 25215 source-map-js: 1.2.1 25216 25217 make-dir@2.1.0: ··· 25533 25534 metro-babel-transformer@0.82.4: 25535 dependencies: 25536 - '@babel/core': 7.28.6 25537 flow-enums-runtime: 0.0.6 25538 hermes-parser: 0.28.1 25539 nullthrows: 1.1.1 ··· 25605 metro-source-map@0.82.4: 25606 dependencies: 25607 '@babel/traverse': 7.27.3 25608 - '@babel/traverse--for-generate-function-map': '@babel/traverse@7.28.6' 25609 '@babel/types': 7.27.3 25610 flow-enums-runtime: 0.0.6 25611 invariant: 2.2.4 ··· 25630 25631 metro-transform-plugins@0.82.4: 25632 dependencies: 25633 - '@babel/core': 7.28.6 25634 - '@babel/generator': 7.28.6 25635 - '@babel/template': 7.28.6 25636 - '@babel/traverse': 7.28.6 25637 flow-enums-runtime: 0.0.6 25638 nullthrows: 1.1.1 25639 transitivePeerDependencies: ··· 25641 25642 metro-transform-worker@0.82.4(bufferutil@4.0.8)(utf-8-validate@5.0.10): 25643 dependencies: 25644 - '@babel/core': 7.28.6 25645 - '@babel/generator': 7.28.6 25646 - '@babel/parser': 7.28.6 25647 - '@babel/types': 7.28.6 25648 flow-enums-runtime: 0.0.6 25649 metro: 0.82.4(bufferutil@4.0.8)(utf-8-validate@5.0.10) 25650 metro-babel-transformer: 0.82.4 ··· 25661 25662 metro@0.82.4(bufferutil@4.0.8)(utf-8-validate@5.0.10): 25663 dependencies: 25664 - '@babel/code-frame': 7.28.6 25665 - '@babel/core': 7.28.6 25666 - '@babel/generator': 7.28.6 25667 - '@babel/parser': 7.28.6 25668 - '@babel/template': 7.28.6 25669 - '@babel/traverse': 7.28.6 25670 - '@babel/types': 7.28.6 25671 accepts: 1.3.8 25672 chalk: 4.1.2 25673 ci-info: 2.0.0 ··· 26279 26280 node-mock-http@1.0.0: {} 26281 26282 - node-releases@2.0.19: {} 26283 26284 - node-releases@2.0.27: {} 26285 26286 nodemailer-html-to-text@3.2.0: 26287 dependencies: ··· 27069 27070 possible-typed-array-names@1.0.0: {} 27071 27072 - postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.3)(tsx@4.21.0)(yaml@2.8.2): 27073 dependencies: 27074 lilconfig: 3.1.3 27075 optionalDependencies: 27076 jiti: 2.6.1 27077 postcss: 8.5.3 27078 - tsx: 4.21.0 27079 yaml: 2.8.2 27080 27081 postcss-modules-extract-imports@3.1.0(postcss@8.5.3): ··· 27111 27112 postcss-value-parser@4.2.0: {} 27113 27114 - postcss@8.4.49: 27115 dependencies: 27116 nanoid: 3.3.11 27117 picocolors: 1.1.1 ··· 27421 dependencies: 27422 react: 19.0.0 27423 27424 - react-i18next@15.7.4(i18next@25.5.2(typescript@5.3.3))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(typescript@5.3.3): 27425 dependencies: 27426 '@babel/runtime': 7.28.4 27427 html-parse-stringify: 3.0.1 ··· 27429 react: 19.0.0 27430 optionalDependencies: 27431 react-dom: 19.0.0(react@19.0.0) 27432 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27433 typescript: 5.3.3 27434 27435 - react-i18next@15.7.4(i18next@25.5.2(typescript@5.8.3))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(typescript@5.8.3): 27436 dependencies: 27437 '@babel/runtime': 7.28.4 27438 html-parse-stringify: 3.0.1 ··· 27440 react: 19.0.0 27441 optionalDependencies: 27442 react-dom: 19.0.0(react@19.0.0) 27443 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27444 typescript: 5.8.3 27445 27446 react-is@16.13.1: {} 27447 27448 react-is@18.3.1: {} 27449 27450 - react-native-draggable-flatlist@4.0.3(@babel/core@7.28.6)(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 27451 dependencies: 27452 - '@babel/preset-typescript': 7.24.7(@babel/core@7.28.6) 27453 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27454 - react-native-gesture-handler: 2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27455 - react-native-reanimated: 3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27456 transitivePeerDependencies: 27457 - '@babel/core' 27458 - supports-color 27459 27460 - react-native-edge-to-edge@1.6.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27461 dependencies: 27462 react: 19.0.0 27463 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27464 27465 - react-native-edge-to-edge@1.6.2(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27466 dependencies: 27467 react: 19.0.0 27468 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27469 27470 react-native-fit-image@1.5.5: 27471 dependencies: 27472 prop-types: 15.8.1 27473 27474 - react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27475 dependencies: 27476 '@egjs/hammerjs': 2.0.17 27477 hoist-non-react-statics: 3.3.2 27478 invariant: 2.2.4 27479 react: 19.0.0 27480 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27481 27482 - react-native-haptic-feedback@2.3.3(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 27483 dependencies: 27484 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27485 optional: true 27486 27487 - react-native-is-edge-to-edge@1.1.7(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27488 dependencies: 27489 react: 19.0.0 27490 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27491 27492 - react-native-localize@3.5.2(@expo/config-plugins@10.0.2)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27493 dependencies: 27494 react: 19.0.0 27495 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27496 optionalDependencies: 27497 '@expo/config-plugins': 10.0.2 27498 27499 - react-native-markdown-display@7.0.2(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27500 dependencies: 27501 css-to-react-native: 3.2.0 27502 markdown-it: 10.0.0 27503 prop-types: 15.8.1 27504 react: 19.0.0 27505 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27506 react-native-fit-image: 1.5.5 27507 27508 - react-native-quick-base64@2.1.2(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27509 dependencies: 27510 base64-js: 1.5.1 27511 react: 19.0.0 27512 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27513 27514 - react-native-quick-crypto@0.7.14(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27515 dependencies: 27516 - '@craftzdog/react-native-buffer': 6.0.5(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27517 events: 3.3.0 27518 readable-stream: 4.5.2 27519 string_decoder: 1.3.0 ··· 27522 - react 27523 - react-native 27524 27525 - react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27526 dependencies: 27527 - '@babel/core': 7.28.6 27528 - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.6) 27529 - '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.6) 27530 - '@babel/plugin-transform-classes': 7.27.1(@babel/core@7.28.6) 27531 - '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.6) 27532 - '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.6) 27533 - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.6) 27534 - '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.6) 27535 - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.6) 27536 - '@babel/preset-typescript': 7.24.7(@babel/core@7.28.6) 27537 convert-source-map: 2.0.0 27538 invariant: 2.2.4 27539 react: 19.0.0 27540 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27541 - react-native-is-edge-to-edge: 1.1.7(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27542 transitivePeerDependencies: 27543 - supports-color 27544 27545 - react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27546 dependencies: 27547 react: 19.0.0 27548 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27549 27550 - react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27551 dependencies: 27552 react: 19.0.0 27553 react-freeze: 1.0.4(react@19.0.0) 27554 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27555 - react-native-is-edge-to-edge: 1.1.7(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27556 warn-once: 0.1.1 27557 27558 - react-native-sortables@1.9.4(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27559 dependencies: 27560 react: 19.0.0 27561 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27562 - react-native-gesture-handler: 2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27563 - react-native-reanimated: 3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27564 optionalDependencies: 27565 - react-native-haptic-feedback: 2.3.3(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 27566 27567 - react-native-svg@15.12.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27568 dependencies: 27569 css-select: 5.1.0 27570 css-tree: 1.1.3 27571 react: 19.0.0 27572 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27573 warn-once: 0.1.1 27574 27575 react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): ··· 27587 transitivePeerDependencies: 27588 - encoding 27589 27590 - react-native-webrtc@https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 27591 dependencies: 27592 base64-js: 1.5.1 27593 debug: 4.3.4 27594 event-target-shim: 6.0.2 27595 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27596 transitivePeerDependencies: 27597 - supports-color 27598 27599 - react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27600 dependencies: 27601 escape-string-regexp: 4.0.0 27602 invariant: 2.2.4 27603 react: 19.0.0 27604 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27605 27606 - react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10): 27607 dependencies: 27608 '@jest/create-cache-key-function': 29.7.0 27609 '@react-native/assets-registry': 0.79.3 27610 - '@react-native/codegen': 0.79.3(@babel/core@7.28.6) 27611 '@react-native/community-cli-plugin': 0.79.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) 27612 '@react-native/gradle-plugin': 0.79.3 27613 '@react-native/js-polyfills': 0.79.3 27614 '@react-native/normalize-colors': 0.79.3 27615 - '@react-native/virtualized-lists': 0.79.3(@types/react@19.0.0)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27616 abort-controller: 3.0.0 27617 anser: 1.4.10 27618 ansi-regex: 5.0.1 27619 - babel-jest: 29.7.0(@babel/core@7.28.6) 27620 babel-plugin-syntax-hermes-parser: 0.25.1 27621 base64-js: 1.5.1 27622 chalk: 4.1.2 ··· 27643 ws: 6.2.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) 27644 yargs: 17.7.2 27645 optionalDependencies: 27646 - '@types/react': 19.0.0 27647 transitivePeerDependencies: 27648 - '@babel/core' 27649 - '@react-native-community/cli' ··· 27653 27654 react-refresh@0.14.2: {} 27655 27656 - react-remove-scroll-bar@2.3.8(@types/react@19.0.0)(react@19.0.0): 27657 dependencies: 27658 react: 19.0.0 27659 - react-style-singleton: 2.2.3(@types/react@19.0.0)(react@19.0.0) 27660 tslib: 2.8.1 27661 optionalDependencies: 27662 - '@types/react': 19.0.0 27663 27664 - react-remove-scroll@2.7.1(@types/react@19.0.0)(react@19.0.0): 27665 dependencies: 27666 react: 19.0.0 27667 - react-remove-scroll-bar: 2.3.8(@types/react@19.0.0)(react@19.0.0) 27668 - react-style-singleton: 2.2.3(@types/react@19.0.0)(react@19.0.0) 27669 tslib: 2.8.1 27670 - use-callback-ref: 1.3.3(@types/react@19.0.0)(react@19.0.0) 27671 - use-sidecar: 1.1.3(@types/react@19.0.0)(react@19.0.0) 27672 optionalDependencies: 27673 - '@types/react': 19.0.0 27674 27675 - react-style-singleton@2.2.3(@types/react@19.0.0)(react@19.0.0): 27676 dependencies: 27677 get-nonce: 1.0.1 27678 react: 19.0.0 27679 tslib: 2.8.1 27680 optionalDependencies: 27681 - '@types/react': 19.0.0 27682 27683 react-use-websocket@4.13.0: {} 27684 ··· 27782 27783 real-require@0.2.0: {} 27784 27785 - reanimated-color-picker@4.0.0(expo@53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27786 - dependencies: 27787 react: 19.0.0 27788 - react-native: 0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27789 - react-native-gesture-handler: 2.26.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27790 - react-native-reanimated: 3.18.0(@babel/core@7.28.6)(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27791 optionalDependencies: 27792 - expo: 53.0.11(@babel/core@7.28.6)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.28.6)(@types/react@19.0.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 27793 27794 rechoir@0.8.0: 27795 dependencies: ··· 28036 resolve-package@1.0.1: 28037 dependencies: 28038 get-installed-path: 2.1.1 28039 - 28040 - resolve-pkg-maps@1.0.0: 28041 - optional: true 28042 28043 resolve-workspace-root@2.0.0: {} 28044 ··· 28623 28624 standard-as-callback@2.1.0: {} 28625 28626 - starlight-openapi-rapidoc@0.8.1-beta(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2)))(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2))(openapi-types@12.1.3): 28627 dependencies: 28628 - '@astrojs/starlight': 0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2)) 28629 '@astropub/md': 0.4.0 28630 '@readme/openapi-parser': 2.5.0(openapi-types@12.1.3) 28631 - astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2) 28632 github-slugger: 2.0.0 28633 transitivePeerDependencies: 28634 - '@astrojs/markdown-remark' 28635 - openapi-types 28636 28637 - starlight-openapi@0.17.0(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2)))(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2))(openapi-types@12.1.3): 28638 dependencies: 28639 - '@astrojs/starlight': 0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2)) 28640 '@readme/openapi-parser': 2.7.0(openapi-types@12.1.3) 28641 - astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.40.1)(terser@5.32.0)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2) 28642 github-slugger: 2.0.0 28643 url-template: 3.1.1 28644 transitivePeerDependencies: 28645 - openapi-types 28646 28647 statuses@1.5.0: {} 28648 ··· 28839 28840 sucrase@3.35.0: 28841 dependencies: 28842 - '@jridgewell/gen-mapping': 0.3.13 28843 commander: 4.1.1 28844 glob: 10.4.5 28845 lines-and-columns: 1.2.4 ··· 28857 transitivePeerDependencies: 28858 - supports-color 28859 28860 supports-color@5.5.0: 28861 dependencies: 28862 has-flag: 3.0.0 ··· 28873 dependencies: 28874 has-flag: 4.0.0 28875 supports-color: 7.2.0 28876 28877 supports-preserve-symlinks-flag@1.0.0: {} 28878 ··· 28969 ansi-escapes: 4.3.2 28970 supports-hyperlinks: 2.3.0 28971 28972 terser-webpack-plugin@5.3.10(@swc/core@1.15.4(@swc/helpers@0.5.17))(webpack@5.94.0(@swc/core@1.15.4(@swc/helpers@0.5.17))): 28973 dependencies: 28974 '@jridgewell/trace-mapping': 0.3.25 ··· 29178 29179 tslib@2.8.1: {} 29180 29181 - tsup@8.5.0(@swc/core@1.15.4(@swc/helpers@0.5.17))(jiti@2.6.1)(postcss@8.5.3)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2): 29182 dependencies: 29183 bundle-require: 5.1.0(esbuild@0.25.3) 29184 cac: 6.7.14 ··· 29189 fix-dts-default-cjs-exports: 1.0.1 29190 joycon: 3.1.1 29191 picocolors: 1.1.1 29192 - postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.3)(tsx@4.21.0)(yaml@2.8.2) 29193 resolve-from: 5.0.0 29194 rollup: 4.40.1 29195 source-map: 0.8.0-beta.0 ··· 29207 - tsx 29208 - yaml 29209 29210 - tsx@4.21.0: 29211 - dependencies: 29212 - esbuild: 0.27.2 29213 - get-tsconfig: 4.13.0 29214 - optionalDependencies: 29215 - fsevents: 2.3.3 29216 - optional: true 29217 - 29218 tuf-js@2.2.1: 29219 dependencies: 29220 '@tufjs/models': 2.0.1 ··· 29488 29489 upath@2.0.1: {} 29490 29491 - update-browserslist-db@1.1.3(browserslist@4.24.5): 29492 dependencies: 29493 - browserslist: 4.24.5 29494 escalade: 3.2.0 29495 picocolors: 1.1.1 29496 29497 - update-browserslist-db@1.2.3(browserslist@4.28.1): 29498 dependencies: 29499 - browserslist: 4.28.1 29500 escalade: 3.2.0 29501 picocolors: 1.1.1 29502 ··· 29514 29515 url-template@3.1.1: {} 29516 29517 - use-callback-ref@1.3.3(@types/react@19.0.0)(react@19.0.0): 29518 dependencies: 29519 react: 19.0.0 29520 tslib: 2.8.1 29521 optionalDependencies: 29522 - '@types/react': 19.0.0 29523 29524 use-latest-callback@0.2.1(react@19.0.0): 29525 dependencies: 29526 react: 19.0.0 29527 29528 - use-sidecar@1.1.3(@types/react@19.0.0)(react@19.0.0): 29529 dependencies: 29530 detect-node-es: 1.1.0 29531 react: 19.0.0 29532 tslib: 2.8.1 29533 optionalDependencies: 29534 - '@types/react': 19.0.0 29535 29536 - use-sync-external-store@1.6.0(react@19.0.0): 29537 dependencies: 29538 react: 19.0.0 29539 optional: true ··· 29694 replace-ext: 2.0.0 29695 teex: 1.0.1 29696 29697 - vite@6.3.4(@types/node@22.15.17)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.32.0)(tsx@4.21.0)(yaml@2.8.2): 29698 dependencies: 29699 esbuild: 0.25.3 29700 fdir: 6.4.4(picomatch@4.0.2) ··· 29706 '@types/node': 22.15.17 29707 fsevents: 2.3.3 29708 jiti: 2.6.1 29709 - lightningcss: 1.30.2 29710 terser: 5.32.0 29711 - tsx: 4.21.0 29712 yaml: 2.8.2 29713 29714 - vitefu@1.0.6(vite@6.3.4(@types/node@22.15.17)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.32.0)(tsx@4.21.0)(yaml@2.8.2)): 29715 optionalDependencies: 29716 - vite: 6.3.4(@types/node@22.15.17)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.32.0)(tsx@4.21.0)(yaml@2.8.2) 29717 29718 vlq@1.0.1: {} 29719 ··· 29829 '@webassemblyjs/wasm-parser': 1.12.1 29830 acorn: 8.14.1 29831 acorn-import-attributes: 1.9.5(acorn@8.14.1) 29832 - browserslist: 4.24.5 29833 chrome-trace-event: 1.0.4 29834 enhanced-resolve: 5.17.1 29835 es-module-lexer: 1.7.0 ··· 30140 30141 zod@3.24.4: {} 30142 30143 - zustand@5.0.5(@types/react@19.0.0)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.6.0(react@19.0.0)): 30144 optionalDependencies: 30145 - '@types/react': 19.0.0 30146 immer: 10.1.1 30147 react: 19.0.0 30148 - use-sync-external-store: 1.6.0(react@19.0.0) 30149 30150 zwitch@2.0.4: {}
··· 4 autoInstallPeers: true 5 excludeLinksFromLockfile: false 6 7 importers: 8 9 .: ··· 71 version: 0.3.31 72 '@bacons/text-decoder': 73 specifier: ^0.0.0 74 + version: 0.0.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 75 '@emoji-mart/react': 76 specifier: ^1.1.1 77 version: 1.1.1(emoji-mart@5.6.0)(react@19.0.0) ··· 86 version: 0.15.2(@fluent/bundle@0.19.1)(react@19.0.0) 87 '@react-native-firebase/app': 88 specifier: ^22.2.1 89 + version: 22.2.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 90 '@react-native-firebase/messaging': 91 specifier: ^22.2.1 92 + version: 22.2.1(d55f93459f56060c343a0d66dd2a08a1) 93 '@react-navigation/bottom-tabs': 94 specifier: ^6.6.1 95 + version: 6.6.1(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 96 '@react-navigation/drawer': 97 specifier: ^6.7.2 98 + version: 6.7.2(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 99 '@react-navigation/native': 100 specifier: ^6.1.18 101 + version: 6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 102 '@react-navigation/native-stack': 103 specifier: ^6.11.0 104 + version: 6.11.0(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 105 '@sentry/react-native': 106 specifier: ^6.14.0 107 + version: 6.14.0(encoding@0.1.13)(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 108 '@streamplace/atproto-oauth-client-react-native': 109 specifier: workspace:* 110 version: link:../atproto-oauth-client-react-native ··· 125 version: 1.7.6 126 babel-preset-expo: 127 specifier: ~13.0.0 128 + version: 13.0.0(@babel/core@7.26.0) 129 buffer: 130 specifier: ^6.0.3 131 version: 6.0.3 132 burnt: 133 specifier: ^0.12.2 134 + version: 0.12.2(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 135 chrono-node: 136 specifier: 2.7.7 137 version: 2.7.7 ··· 146 version: 6.0.2 147 expo: 148 specifier: ~53.0.11 149 + version: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 150 expo-build-properties: 151 specifier: ~0.14.6 152 + version: 0.14.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 153 expo-dev-client: 154 specifier: ~5.2.0 155 + version: 5.2.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 156 expo-file-system: 157 specifier: ~18.1.10 158 + version: 18.1.10(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 159 expo-font: 160 specifier: ~13.3.1 161 + version: 13.3.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 162 expo-keep-awake: 163 specifier: ~14.1.4 164 + version: 14.1.4(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 165 expo-linking: 166 specifier: ~7.1.5 167 + version: 7.1.5(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 168 expo-localization: 169 specifier: ^17.0.7 170 + version: 17.0.7(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 171 expo-notifications: 172 specifier: ~0.31.3 173 + version: 0.31.3(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 174 expo-screen-orientation: 175 specifier: ^9.0.7 176 + version: 9.0.7(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 177 expo-splash-screen: 178 specifier: ~0.30.9 179 + version: 0.30.9(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 180 expo-sqlite: 181 specifier: ~15.2.12 182 + version: 15.2.12(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 183 expo-system-ui: 184 specifier: ~5.0.8 185 + version: 5.0.8(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 186 expo-updates: 187 specifier: ~0.28.14 188 + version: 0.28.14(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 189 expo-video: 190 specifier: ~2.2.1 191 + version: 2.2.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 192 expo-web-browser: 193 specifier: ^14.1.6 194 + version: 14.1.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 195 hls.js: 196 specifier: ^1.5.17 197 version: 1.5.17 ··· 218 version: 5.9.6 219 lucide-react-native: 220 specifier: ^0.514.0 221 + version: 0.514.0(react-native-svg@15.12.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 222 multiformats: 223 specifier: ^13.3.1 224 version: 13.3.1 ··· 236 version: 19.0.0(react@19.0.0) 237 react-i18next: 238 specifier: ^15.7.3 239 + version: 15.7.4(i18next@25.5.2(typescript@5.3.3))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(typescript@5.3.3) 240 react-native: 241 specifier: 0.79.3 242 + version: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 243 react-native-draggable-flatlist: 244 specifier: ^4.0.3 245 + version: 4.0.3(@babel/core@7.26.0)(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 246 react-native-edge-to-edge: 247 specifier: ^1.6.2 248 + version: 1.6.2(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 249 react-native-gesture-handler: 250 specifier: ~2.26.0 251 + version: 2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 252 react-native-localize: 253 specifier: ^3.5.2 254 + version: 3.5.2(@expo/config-plugins@10.0.2)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 255 react-native-markdown-display: 256 specifier: ^7.0.2 257 + version: 7.0.2(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 258 react-native-quick-crypto: 259 specifier: ^0.7.14 260 + version: 0.7.14(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 261 react-native-reanimated: 262 specifier: ~3.18.0 263 + version: 3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 264 react-native-safe-area-context: 265 specifier: 5.4.1 266 + version: 5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 267 react-native-screens: 268 specifier: ~4.11.1 269 + version: 4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 270 react-native-sortables: 271 specifier: ^1.9.4 272 + version: 1.9.4(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 273 react-native-svg: 274 specifier: 15.12.0 275 + version: 15.12.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 276 react-native-web: 277 specifier: ^0.20.0 278 version: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 279 react-native-webrtc: 280 specifier: git+https://github.com/streamplace/react-native-webrtc.git#6b8472a771ac47f89217d327058a8a4124a6ae56 281 + version: https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 282 react-native-webview: 283 specifier: 13.15.0 284 + version: 13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 285 react-use-websocket: 286 specifier: ^4.13.0 287 version: 4.13.0 288 reanimated-color-picker: 289 specifier: ^4.0.0 290 + version: 4.0.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 291 rtcaudiodevice: 292 specifier: git+https://github.com/streamplace/RTCAudioDevice.git#918e08a0f6f0818fb495a0db0b696b44d11d1336 293 version: https://codeload.github.com/streamplace/RTCAudioDevice/tar.gz/918e08a0f6f0818fb495a0db0b696b44d11d1336 ··· 311 version: 2.21.44(bufferutil@4.0.8)(typescript@5.3.3)(utf-8-validate@5.0.10)(zod@3.24.4) 312 zustand: 313 specifier: ^5.0.5 314 + version: 5.0.5(@types/react@18.3.12)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.2.2(react@19.0.0)) 315 devDependencies: 316 '@babel/core': 317 specifier: ^7.26.0 318 + version: 7.26.0 319 '@babel/plugin-proposal-export-default-from': 320 specifier: ^7.25.9 321 + version: 7.25.9(@babel/core@7.26.0) 322 '@babel/plugin-syntax-export-default-from': 323 specifier: ^7.25.9 324 + version: 7.25.9(@babel/core@7.26.0) 325 '@babel/plugin-transform-flow-strip-types': 326 specifier: ^7.25.9 327 + version: 7.25.9(@babel/core@7.26.0) 328 '@babel/plugin-transform-private-methods': 329 specifier: ^7.25.9 330 + version: 7.27.1(@babel/core@7.26.0) 331 '@babel/plugin-transform-private-property-in-object': 332 specifier: ^7.25.9 333 + version: 7.27.1(@babel/core@7.26.0) 334 '@babel/plugin-transform-runtime': 335 specifier: ^7.25.9 336 + version: 7.25.9(@babel/core@7.26.0) 337 '@config-plugins/react-native-webrtc': 338 specifier: ^10.0.0 339 + version: 10.0.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 340 '@expo/metro-config': 341 specifier: ~0.19.0 342 version: 0.19.4 343 '@expo/metro-runtime': 344 specifier: ~5.0.4 345 + version: 5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 346 '@types/babel__plugin-transform-runtime': 347 specifier: ^7 348 version: 7.9.5 ··· 350 specifier: ^1 351 version: 1.5.5 352 '@types/react': 353 + specifier: ~18.3.12 354 + version: 18.3.12 355 '@types/sdp-transform': 356 specifier: ^2.15.0 357 version: 2.15.0 ··· 408 version: 6.0.2 409 expo-sqlite: 410 specifier: ^15.0.3 411 + version: 15.2.12(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 412 jose: 413 specifier: ^5.2.0 414 version: 5.9.6 415 react-native-quick-crypto: 416 specifier: ^0.7.7 417 + version: 0.7.14(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 418 devDependencies: 419 '@types/node': 420 specifier: ^22.10.1 ··· 445 version: 0.15.2(@fluent/bundle@0.19.1)(react@19.0.0) 446 '@gorhom/bottom-sheet': 447 specifier: ^5.1.6 448 + version: 5.1.6(@types/react@18.3.12)(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 449 '@radix-ui/react-dropdown-menu': 450 specifier: ^2.1.16 451 + version: 2.1.16(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 452 '@rn-primitives/dropdown-menu': 453 specifier: ^1.2.0 454 + version: 1.2.0(@rn-primitives/portal@1.3.0(@types/react@18.3.12)(immer@10.1.1)(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(use-sync-external-store@1.2.2(react@19.0.0)))(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 455 '@rn-primitives/portal': 456 specifier: ^1.3.0 457 + version: 1.3.0(@types/react@18.3.12)(immer@10.1.1)(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(use-sync-external-store@1.2.2(react@19.0.0)) 458 '@rn-primitives/slider': 459 specifier: ^1.2.0 460 + version: 1.2.0(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 461 class-variance-authority: 462 specifier: ^0.6.1 463 version: 0.6.1 464 expo-keep-awake: 465 specifier: ^14.0.0 466 + version: 14.1.4(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 467 expo-localization: 468 specifier: '*' 469 + version: 17.0.7(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 470 expo-screen-orientation: 471 specifier: ^9.0.7 472 + version: 9.0.7(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 473 expo-sensors: 474 specifier: ^15.0.7 475 + version: 15.0.7(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 476 expo-sqlite: 477 specifier: ~15.2.12 478 + version: 15.2.12(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 479 expo-video: 480 specifier: ^2.0.0 481 + version: 2.2.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 482 + graphemer: 483 + specifier: ^1.4.0 484 + version: 1.4.0 485 hls.js: 486 specifier: ^1.5.17 487 version: 1.5.17 ··· 505 version: 2.0.1 506 lucide-react-native: 507 specifier: ^0.514.0 508 + version: 0.514.0(react-native-svg@15.12.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 509 react: 510 + specifier: '*' 511 version: 19.0.0 512 react-i18next: 513 specifier: ^15.7.3 514 + version: 15.7.4(i18next@25.5.2(typescript@5.8.3))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(typescript@5.8.3) 515 react-native: 516 specifier: ^0.79.0 517 + version: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 518 react-native-edge-to-edge: 519 specifier: ^1.6.2 520 + version: 1.6.2(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 521 react-native-gesture-handler: 522 specifier: ^2.20.0 523 + version: 2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 524 react-native-reanimated: 525 specifier: ^3.0.0 526 + version: 3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 527 react-native-safe-area-context: 528 specifier: ^5.0.0 529 + version: 5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 530 react-native-svg: 531 specifier: ^15.0.0 532 + version: 15.12.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 533 react-native-webrtc: 534 specifier: git+https://github.com/streamplace/react-native-webrtc.git#6b8472a771ac47f89217d327058a8a4124a6ae56 535 + version: https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 536 react-use-websocket: 537 specifier: ^4.13.0 538 version: 4.13.0 ··· 544 version: 2.21.44(bufferutil@4.0.8)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.4) 545 zustand: 546 specifier: ^5.0.5 547 + version: 5.0.5(@types/react@18.3.12)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.2.2(react@19.0.0)) 548 devDependencies: 549 '@fluent/syntax': 550 specifier: ^0.19.0 551 version: 0.19.0 552 '@types/react-dom': 553 + specifier: ^19.2.3 554 + version: 19.2.3(@types/react@18.3.12) 555 '@types/sdp-transform': 556 specifier: ^2.15.0 557 version: 2.15.0 ··· 563 version: 3.1.10 564 tsup: 565 specifier: ^8.5.0 566 + version: 8.5.0(@swc/core@1.15.4(@swc/helpers@0.5.17))(jiti@2.6.1)(postcss@8.5.3)(typescript@5.8.3)(yaml@2.8.2) 567 568 js/config-react-native-webrtc: 569 dependencies: 570 '@config-plugins/react-native-webrtc': 571 specifier: 10.0.0 572 + version: 10.0.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 573 react-native-webrtc: 574 specifier: git+https://github.com/streamplace/react-native-webrtc.git#6b8472a771ac47f89217d327058a8a4124a6ae56 575 + version: https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 576 rtcaudiodevice: 577 specifier: git+https://github.com/streamplace/RTCAudioDevice.git#918e08a0f6f0818fb495a0db0b696b44d11d1336 578 version: https://codeload.github.com/streamplace/RTCAudioDevice/tar.gz/918e08a0f6f0818fb495a0db0b696b44d11d1336 ··· 715 dependencies: 716 '@astrojs/starlight': 717 specifier: ^0.34.1 718 + version: 0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)) 719 '@fontsource/atkinson-hyperlegible-next': 720 specifier: ^5.2.2 721 version: 5.2.2 ··· 724 version: link:../app 725 astro: 726 specifier: ^5.6.1 727 + version: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2) 728 sharp: 729 specifier: ^0.32.5 730 version: 0.32.6 731 + starlight-links-validator: 732 + specifier: ^0.19.2 733 + version: 0.19.2(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)))(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)) 734 starlight-openapi: 735 specifier: ^0.17.0 736 + version: 0.17.0(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)))(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2))(openapi-types@12.1.3) 737 starlight-openapi-rapidoc: 738 specifier: ^0.8.1-beta 739 + version: 0.8.1-beta(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)))(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2))(openapi-types@12.1.3) 740 + starlight-sidebar-swipe: 741 + specifier: ^0.1.1 742 + version: 0.1.1(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2))) 743 streamplace: 744 specifier: workspace:* 745 version: link:../streamplace 746 + devDependencies: 747 + starlight-sidebar-topics: 748 + specifier: ^0.6.2 749 + version: 0.6.2(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2))) 750 751 js/streamplace: 752 dependencies: ··· 783 '@adraffy/ens-normalize@1.11.0': 784 resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==} 785 786 + '@ampproject/remapping@2.3.0': 787 + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} 788 + engines: {node: '>=6.0.0'} 789 + 790 '@apidevtools/openapi-schemas@2.1.0': 791 resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==} 792 engines: {node: '>=10'} ··· 1240 resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} 1241 engines: {node: '>=6.9.0'} 1242 1243 '@babel/compat-data@7.26.2': 1244 resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} 1245 engines: {node: '>=6.9.0'} ··· 1248 resolution: {integrity: sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==} 1249 engines: {node: '>=6.9.0'} 1250 1251 + '@babel/core@7.26.0': 1252 + resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} 1253 engines: {node: '>=6.9.0'} 1254 1255 '@babel/generator@7.26.2': ··· 1260 resolution: {integrity: sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==} 1261 engines: {node: '>=6.9.0'} 1262 1263 + '@babel/helper-annotate-as-pure@7.27.3': 1264 + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} 1265 engines: {node: '>=6.9.0'} 1266 1267 + '@babel/helper-compilation-targets@7.25.9': 1268 + resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} 1269 engines: {node: '>=6.9.0'} 1270 1271 '@babel/helper-compilation-targets@7.27.2': 1272 resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} 1273 engines: {node: '>=6.9.0'} 1274 1275 '@babel/helper-create-class-features-plugin@7.27.1': 1276 resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==} 1277 engines: {node: '>=6.9.0'} ··· 1289 peerDependencies: 1290 '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 1291 1292 '@babel/helper-member-expression-to-functions@7.27.1': 1293 resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} 1294 engines: {node: '>=6.9.0'} ··· 1301 resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} 1302 engines: {node: '>=6.9.0'} 1303 1304 + '@babel/helper-module-transforms@7.26.0': 1305 + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} 1306 engines: {node: '>=6.9.0'} 1307 peerDependencies: 1308 '@babel/core': ^7.0.0 1309 1310 + '@babel/helper-module-transforms@7.27.3': 1311 + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} 1312 engines: {node: '>=6.9.0'} 1313 peerDependencies: 1314 '@babel/core': ^7.0.0 ··· 1357 resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} 1358 engines: {node: '>=6.9.0'} 1359 1360 + '@babel/helper-validator-option@7.25.9': 1361 + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} 1362 engines: {node: '>=6.9.0'} 1363 1364 '@babel/helper-validator-option@7.27.1': ··· 1369 resolution: {integrity: sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==} 1370 engines: {node: '>=6.9.0'} 1371 1372 + '@babel/helpers@7.26.0': 1373 + resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} 1374 engines: {node: '>=6.9.0'} 1375 1376 '@babel/highlight@7.24.7': ··· 1384 1385 '@babel/parser@7.27.3': 1386 resolution: {integrity: sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==} 1387 engines: {node: '>=6.0.0'} 1388 hasBin: true 1389 ··· 1761 resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} 1762 engines: {node: '>=6.9.0'} 1763 1764 + '@babel/template@7.25.9': 1765 + resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} 1766 + engines: {node: '>=6.9.0'} 1767 + 1768 '@babel/template@7.27.2': 1769 resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} 1770 engines: {node: '>=6.9.0'} 1771 1772 + '@babel/traverse@7.25.9': 1773 + resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} 1774 engines: {node: '>=6.9.0'} 1775 1776 '@babel/traverse@7.27.3': 1777 resolution: {integrity: sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==} 1778 engines: {node: '>=6.9.0'} 1779 1780 '@babel/types@7.26.0': 1781 resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} 1782 engines: {node: '>=6.9.0'} 1783 1784 '@babel/types@7.27.3': 1785 resolution: {integrity: sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==} 1786 engines: {node: '>=6.9.0'} 1787 1788 '@bacons/text-decoder@0.0.0': ··· 2012 resolution: {integrity: sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==} 2013 peerDependencies: 2014 emoji-mart: ^5.2 2015 + react: ^16.8 || ^17 || ^18 2016 2017 '@esbuild/aix-ppc64@0.25.3': 2018 resolution: {integrity: sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==} ··· 2020 cpu: [ppc64] 2021 os: [aix] 2022 2023 '@esbuild/android-arm64@0.25.3': 2024 resolution: {integrity: sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==} 2025 engines: {node: '>=18'} 2026 cpu: [arm64] 2027 os: [android] 2028 2029 '@esbuild/android-arm@0.25.3': 2030 resolution: {integrity: sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==} 2031 engines: {node: '>=18'} 2032 cpu: [arm] 2033 os: [android] 2034 2035 '@esbuild/android-x64@0.25.3': 2036 resolution: {integrity: sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==} 2037 engines: {node: '>=18'} 2038 cpu: [x64] 2039 os: [android] 2040 2041 '@esbuild/darwin-arm64@0.25.3': 2042 resolution: {integrity: sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==} 2043 engines: {node: '>=18'} 2044 cpu: [arm64] 2045 os: [darwin] 2046 2047 '@esbuild/darwin-x64@0.25.3': 2048 resolution: {integrity: sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==} 2049 engines: {node: '>=18'} 2050 cpu: [x64] 2051 os: [darwin] ··· 2056 cpu: [arm64] 2057 os: [freebsd] 2058 2059 '@esbuild/freebsd-x64@0.25.3': 2060 resolution: {integrity: sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==} 2061 engines: {node: '>=18'} 2062 cpu: [x64] 2063 os: [freebsd] ··· 2068 cpu: [arm64] 2069 os: [linux] 2070 2071 '@esbuild/linux-arm@0.25.3': 2072 resolution: {integrity: sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==} 2073 engines: {node: '>=18'} 2074 cpu: [arm] 2075 os: [linux] ··· 2080 cpu: [ia32] 2081 os: [linux] 2082 2083 '@esbuild/linux-loong64@0.25.3': 2084 resolution: {integrity: sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==} 2085 engines: {node: '>=18'} 2086 cpu: [loong64] 2087 os: [linux] ··· 2092 cpu: [mips64el] 2093 os: [linux] 2094 2095 '@esbuild/linux-ppc64@0.25.3': 2096 resolution: {integrity: sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==} 2097 engines: {node: '>=18'} 2098 cpu: [ppc64] 2099 os: [linux] ··· 2104 cpu: [riscv64] 2105 os: [linux] 2106 2107 '@esbuild/linux-s390x@0.25.3': 2108 resolution: {integrity: sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==} 2109 engines: {node: '>=18'} 2110 cpu: [s390x] 2111 os: [linux] ··· 2116 cpu: [x64] 2117 os: [linux] 2118 2119 '@esbuild/netbsd-arm64@0.25.3': 2120 resolution: {integrity: sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==} 2121 engines: {node: '>=18'} 2122 cpu: [arm64] 2123 os: [netbsd] ··· 2128 cpu: [x64] 2129 os: [netbsd] 2130 2131 '@esbuild/openbsd-arm64@0.25.3': 2132 resolution: {integrity: sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==} 2133 engines: {node: '>=18'} 2134 cpu: [arm64] 2135 os: [openbsd] ··· 2140 cpu: [x64] 2141 os: [openbsd] 2142 2143 '@esbuild/sunos-x64@0.25.3': 2144 resolution: {integrity: sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==} 2145 engines: {node: '>=18'} 2146 cpu: [x64] 2147 os: [sunos] 2148 2149 '@esbuild/win32-arm64@0.25.3': 2150 resolution: {integrity: sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==} 2151 engines: {node: '>=18'} 2152 cpu: [arm64] 2153 os: [win32] 2154 2155 '@esbuild/win32-ia32@0.25.3': 2156 resolution: {integrity: sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==} 2157 engines: {node: '>=18'} 2158 cpu: [ia32] 2159 os: [win32] 2160 2161 '@esbuild/win32-x64@0.25.3': 2162 resolution: {integrity: sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==} 2163 engines: {node: '>=18'} 2164 cpu: [x64] 2165 os: [win32] ··· 2550 '@floating-ui/react-dom@2.1.3': 2551 resolution: {integrity: sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==} 2552 peerDependencies: 2553 + react: '>=16.8.0' 2554 + react-dom: '>=16.8.0' 2555 2556 '@floating-ui/utils@0.2.9': 2557 resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} ··· 2573 engines: {node: '>=14.0.0', npm: '>=7.0.0'} 2574 peerDependencies: 2575 '@fluent/bundle': '>=0.16.0' 2576 + react: '>=16.8.0' 2577 2578 '@fluent/sequence@0.8.0': 2579 resolution: {integrity: sha512-eV5QlEEVV/wR3AFQLXO67x4yPRPQXyqke0c8yucyMSeW36B3ecZyVFlY1UprzrfFV8iPJB4TAehDy/dLGbvQ1Q==} ··· 2620 '@gorhom/bottom-sheet@5.1.6': 2621 resolution: {integrity: sha512-0b5tQj4fTaZAjST1PnkCp0p7d8iRqMezibTcqc8Kkn3N23Vn6upORNTD1fH0bLfwRt6e0WnZ7DjAmq315lrcKQ==} 2622 peerDependencies: 2623 + '@types/react': '*' 2624 '@types/react-native': '*' 2625 + react: '*' 2626 react-native: '*' 2627 react-native-gesture-handler: '>=2.16.1' 2628 react-native-reanimated: '>=3.16.0' ··· 2635 '@gorhom/portal@1.0.14': 2636 resolution: {integrity: sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A==} 2637 peerDependencies: 2638 + react: '*' 2639 react-native: '*' 2640 2641 '@grpc/grpc-js@1.10.10': ··· 3005 resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} 3006 engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} 3007 3008 '@jridgewell/gen-mapping@0.3.5': 3009 resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} 3010 engines: {node: '>=6.0.0'} 3011 3012 '@jridgewell/resolve-uri@3.1.2': 3013 resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} ··· 3025 3026 '@jridgewell/trace-mapping@0.3.25': 3027 resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 3028 3029 '@jridgewell/trace-mapping@0.3.9': 3030 resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} ··· 3423 '@radix-ui/react-arrow@1.1.7': 3424 resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} 3425 peerDependencies: 3426 + '@types/react': '*' 3427 + '@types/react-dom': '*' 3428 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3429 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3430 peerDependenciesMeta: 3431 '@types/react': 3432 optional: true ··· 3436 '@radix-ui/react-collection@1.1.7': 3437 resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} 3438 peerDependencies: 3439 + '@types/react': '*' 3440 + '@types/react-dom': '*' 3441 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3442 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3443 peerDependenciesMeta: 3444 '@types/react': 3445 optional: true ··· 3449 '@radix-ui/react-compose-refs@1.1.2': 3450 resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} 3451 peerDependencies: 3452 + '@types/react': '*' 3453 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3454 peerDependenciesMeta: 3455 '@types/react': 3456 optional: true ··· 3458 '@radix-ui/react-context@1.1.2': 3459 resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} 3460 peerDependencies: 3461 + '@types/react': '*' 3462 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3463 peerDependenciesMeta: 3464 '@types/react': 3465 optional: true ··· 3467 '@radix-ui/react-direction@1.1.1': 3468 resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} 3469 peerDependencies: 3470 + '@types/react': '*' 3471 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3472 peerDependenciesMeta: 3473 '@types/react': 3474 optional: true ··· 3476 '@radix-ui/react-dismissable-layer@1.1.11': 3477 resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} 3478 peerDependencies: 3479 + '@types/react': '*' 3480 + '@types/react-dom': '*' 3481 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3482 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3483 peerDependenciesMeta: 3484 '@types/react': 3485 optional: true ··· 3489 '@radix-ui/react-dropdown-menu@2.1.16': 3490 resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} 3491 peerDependencies: 3492 + '@types/react': '*' 3493 + '@types/react-dom': '*' 3494 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3495 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3496 peerDependenciesMeta: 3497 '@types/react': 3498 optional: true ··· 3502 '@radix-ui/react-focus-guards@1.1.3': 3503 resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} 3504 peerDependencies: 3505 + '@types/react': '*' 3506 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3507 peerDependenciesMeta: 3508 '@types/react': 3509 optional: true ··· 3511 '@radix-ui/react-focus-scope@1.1.7': 3512 resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} 3513 peerDependencies: 3514 + '@types/react': '*' 3515 + '@types/react-dom': '*' 3516 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3517 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3518 peerDependenciesMeta: 3519 '@types/react': 3520 optional: true ··· 3524 '@radix-ui/react-id@1.1.1': 3525 resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} 3526 peerDependencies: 3527 + '@types/react': '*' 3528 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3529 peerDependenciesMeta: 3530 '@types/react': 3531 optional: true ··· 3533 '@radix-ui/react-menu@2.1.16': 3534 resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} 3535 peerDependencies: 3536 + '@types/react': '*' 3537 + '@types/react-dom': '*' 3538 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3539 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3540 peerDependenciesMeta: 3541 '@types/react': 3542 optional: true ··· 3546 '@radix-ui/react-popper@1.2.8': 3547 resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} 3548 peerDependencies: 3549 + '@types/react': '*' 3550 + '@types/react-dom': '*' 3551 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3552 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3553 peerDependenciesMeta: 3554 '@types/react': 3555 optional: true ··· 3559 '@radix-ui/react-portal@1.1.9': 3560 resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} 3561 peerDependencies: 3562 + '@types/react': '*' 3563 + '@types/react-dom': '*' 3564 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3565 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3566 peerDependenciesMeta: 3567 '@types/react': 3568 optional: true ··· 3572 '@radix-ui/react-presence@1.1.5': 3573 resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} 3574 peerDependencies: 3575 + '@types/react': '*' 3576 + '@types/react-dom': '*' 3577 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3578 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3579 peerDependenciesMeta: 3580 '@types/react': 3581 optional: true ··· 3585 '@radix-ui/react-primitive@2.1.3': 3586 resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} 3587 peerDependencies: 3588 + '@types/react': '*' 3589 + '@types/react-dom': '*' 3590 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3591 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3592 peerDependenciesMeta: 3593 '@types/react': 3594 optional: true ··· 3598 '@radix-ui/react-roving-focus@1.1.11': 3599 resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} 3600 peerDependencies: 3601 + '@types/react': '*' 3602 + '@types/react-dom': '*' 3603 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3604 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3605 peerDependenciesMeta: 3606 '@types/react': 3607 optional: true ··· 3611 '@radix-ui/react-slider@1.3.5': 3612 resolution: {integrity: sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw==} 3613 peerDependencies: 3614 + '@types/react': '*' 3615 + '@types/react-dom': '*' 3616 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3617 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3618 peerDependenciesMeta: 3619 '@types/react': 3620 optional: true ··· 3624 '@radix-ui/react-slot@1.2.3': 3625 resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} 3626 peerDependencies: 3627 + '@types/react': '*' 3628 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3629 peerDependenciesMeta: 3630 '@types/react': 3631 optional: true ··· 3633 '@radix-ui/react-use-callback-ref@1.1.1': 3634 resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} 3635 peerDependencies: 3636 + '@types/react': '*' 3637 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3638 peerDependenciesMeta: 3639 '@types/react': 3640 optional: true ··· 3642 '@radix-ui/react-use-controllable-state@1.2.2': 3643 resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} 3644 peerDependencies: 3645 + '@types/react': '*' 3646 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3647 peerDependenciesMeta: 3648 '@types/react': 3649 optional: true ··· 3651 '@radix-ui/react-use-effect-event@0.0.2': 3652 resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} 3653 peerDependencies: 3654 + '@types/react': '*' 3655 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3656 peerDependenciesMeta: 3657 '@types/react': 3658 optional: true ··· 3660 '@radix-ui/react-use-escape-keydown@1.1.1': 3661 resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} 3662 peerDependencies: 3663 + '@types/react': '*' 3664 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3665 peerDependenciesMeta: 3666 '@types/react': 3667 optional: true ··· 3669 '@radix-ui/react-use-layout-effect@1.1.1': 3670 resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} 3671 peerDependencies: 3672 + '@types/react': '*' 3673 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3674 peerDependenciesMeta: 3675 '@types/react': 3676 optional: true ··· 3678 '@radix-ui/react-use-previous@1.1.1': 3679 resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} 3680 peerDependencies: 3681 + '@types/react': '*' 3682 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3683 peerDependenciesMeta: 3684 '@types/react': 3685 optional: true ··· 3687 '@radix-ui/react-use-rect@1.1.1': 3688 resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} 3689 peerDependencies: 3690 + '@types/react': '*' 3691 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3692 peerDependenciesMeta: 3693 '@types/react': 3694 optional: true ··· 3696 '@radix-ui/react-use-size@1.1.1': 3697 resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} 3698 peerDependencies: 3699 + '@types/react': '*' 3700 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 3701 peerDependenciesMeta: 3702 '@types/react': 3703 optional: true ··· 3709 resolution: {integrity: sha512-FNekjZgvLLBWLNMGKfKUHR4TTu8OY1YnvlQV9HaNboF5U5+CvTcK8IKycXKdhVP8YfcILTaM3AFraoQsQsy3/w==} 3710 peerDependencies: 3711 expo: '>=47.0.0' 3712 + react: '*' 3713 react-native: '*' 3714 peerDependenciesMeta: 3715 expo: ··· 3798 resolution: {integrity: sha512-/0rRozkn+iIHya2vnnvprDgT7QkfI54FLrACAN3BLP7MRlfOIGOrZsXpRLndnLBVnjNzkcre84i1RecjoXnwIA==} 3799 engines: {node: '>=18'} 3800 peerDependencies: 3801 + '@types/react': ^19.0.0 3802 + react: '*' 3803 react-native: '*' 3804 peerDependenciesMeta: 3805 '@types/react': ··· 3809 resolution: {integrity: sha512-9oD4cypEBjPuaMiu9tevWGiQ4w/d6l3HNhcJ1IjXZ24xvYDSs0mqjUcdt8SWUolCvRrYc/DmNBLlT83bk0bHTw==} 3810 peerDependencies: 3811 '@react-navigation/native': ^6.0.0 3812 + react: '*' 3813 react-native: '*' 3814 react-native-safe-area-context: '>= 3.0.0' 3815 react-native-screens: '>= 3.0.0' ··· 3817 '@react-navigation/core@6.4.17': 3818 resolution: {integrity: sha512-Nd76EpomzChWAosGqWOYE3ItayhDzIEzzZsT7PfGcRFDgW5miHV2t4MZcq9YIK4tzxZjVVpYbIynOOQQd1e0Cg==} 3819 peerDependencies: 3820 + react: '*' 3821 3822 '@react-navigation/drawer@6.7.2': 3823 resolution: {integrity: sha512-o4g2zgTZa2+oLd+8V33etrSM38KIqu8S/zCBTsdsHUoQyVE7JNRiv3Qgq/jMvEb8PZCqWmm7jHItcgzrBuwyOQ==} 3824 peerDependencies: 3825 '@react-navigation/native': ^6.0.0 3826 + react: '*' 3827 react-native: '*' 3828 react-native-gesture-handler: '>= 1.0.0' 3829 react-native-reanimated: '>= 1.0.0' ··· 3834 resolution: {integrity: sha512-bUzP4Awlljx5RKEExw8WYtif8EuQni2glDaieYROKTnaxsu9kEIA515sXQgUDZU4Ob12VoL7+z70uO3qrlfXcQ==} 3835 peerDependencies: 3836 '@react-navigation/native': ^6.0.0 3837 + react: '*' 3838 react-native: '*' 3839 react-native-safe-area-context: '>= 3.0.0' 3840 ··· 3842 resolution: {integrity: sha512-U5EcUB9Q2NQspCFwYGGNJm0h6wBCOv7T30QjndmvlawLkNt7S7KWbpWyxS9XBHSIKF57RgWjfxuJNTgTstpXxw==} 3843 peerDependencies: 3844 '@react-navigation/native': ^6.0.0 3845 + react: '*' 3846 react-native: '*' 3847 react-native-safe-area-context: '>= 3.0.0' 3848 react-native-screens: '>= 3.0.0' ··· 3850 '@react-navigation/native@6.1.18': 3851 resolution: {integrity: sha512-mIT9MiL/vMm4eirLcmw2h6h/Nm5FICtnYSdohq4vTLA2FF/6PNhByM7s8ffqoVfE5L0uAa6Xda1B7oddolUiGg==} 3852 peerDependencies: 3853 + react: '*' 3854 react-native: '*' 3855 3856 '@react-navigation/routers@6.1.9': ··· 3899 resolution: {integrity: sha512-TJDDr8VQfw9CRZ7xZ6kBYLVMqL1xFVC5ZZ4sfRmWP6PCT0lNks4XqGuTFLeVVlNLPSmzt9GKC2DZqzDXui8/NQ==} 3900 peerDependencies: 3901 '@rn-primitives/portal': '*' 3902 + react: '*' 3903 react-native: '*' 3904 react-native-web: '*' 3905 peerDependenciesMeta: ··· 3911 '@rn-primitives/hooks@1.3.0': 3912 resolution: {integrity: sha512-BR97reSu7uVDpyMeQdRJHT0w8KdS6jdYnOL6xQtqS2q3H6N7vXBlX4LFERqJZphD+aziJFIAJ3HJF1vtt6XlpQ==} 3913 peerDependencies: 3914 + react: '*' 3915 react-native: '*' 3916 react-native-web: '*' 3917 peerDependenciesMeta: ··· 3923 '@rn-primitives/portal@1.3.0': 3924 resolution: {integrity: sha512-a2DSce7TcSfcs0cCngLadAJOvx/+mdH9NRu+GxkX8NPRsGGhJvDEOqouMgDqLwx7z9mjXoUaZcwaVcemUSW9/A==} 3925 peerDependencies: 3926 + react: '*' 3927 react-native: '*' 3928 react-native-web: '*' 3929 peerDependenciesMeta: ··· 3935 '@rn-primitives/slider@1.2.0': 3936 resolution: {integrity: sha512-JRxTQelfEdG7tWA+7v5YY/9hUeZXe99BrfRH4b/kUbdMdzMp+MEEvJ6y1iqUlNIys5B6uuTWLnFjI8IhG/MkXw==} 3937 peerDependencies: 3938 + react: '*' 3939 react-native: '*' 3940 react-native-web: '*' 3941 peerDependenciesMeta: ··· 3947 '@rn-primitives/slot@1.2.0': 3948 resolution: {integrity: sha512-cpbn+JLjSeq3wcA4uqgFsUimMrWYWx2Ks7r5rkwd1ds1utxynsGkLOKpYVQkATwWrYhtcoF1raxIKEqXuMN+/w==} 3949 peerDependencies: 3950 + react: '*' 3951 react-native: '*' 3952 react-native-web: '*' 3953 peerDependenciesMeta: ··· 3959 '@rn-primitives/types@1.2.0': 3960 resolution: {integrity: sha512-b+6zKgdKVqAfaFPSfhwlQL0dnPQXPpW890m3eguC0VDI1eOsoEvUfVb6lmgH4bum9MmI0xymq4tOUI/fsKLoCQ==} 3961 peerDependencies: 3962 + react: '*' 3963 react-native: '*' 3964 react-native-web: '*' 3965 peerDependenciesMeta: ··· 3971 '@rn-primitives/utils@1.2.0': 3972 resolution: {integrity: sha512-vLXV5NuxIHDeb4Bw57FzdUh89/g8gz6GERm8TsbJaSUPsDXfnC/ffeYiZJb0LxNteKE3Nr8na4Jy2n26tFil7w==} 3973 peerDependencies: 3974 + react: '*' 3975 react-native: '*' 3976 react-native-web: '*' 3977 peerDependenciesMeta: ··· 4189 hasBin: true 4190 peerDependencies: 4191 expo: '>=49.0.0' 4192 + react: '>=17.0.0' 4193 react-native: '>=0.65.0' 4194 peerDependenciesMeta: 4195 expo: ··· 4199 resolution: {integrity: sha512-42T/fp8snYN19Fy/2P0Mwotu4gcdy+1Lx+uYCNcYP1o7wNGigJ7qb27sW7W34GyCCHjoCCfQgeOqDQsyY8LC9w==} 4200 engines: {node: '>=14.18'} 4201 peerDependencies: 4202 + react: ^16.14.0 || 17.x || 18.x || 19.x 4203 4204 '@sentry/types@8.54.0': 4205 resolution: {integrity: sha512-wztdtr7dOXQKi0iRvKc8XJhJ7HaAfOv8lGu0yqFOFwBZucO/SHnu87GOPi8mvrTiy1bentQO5l+zXWAaMvG4uw==} ··· 4728 '@tanstack/react-query@5.59.19': 4729 resolution: {integrity: sha512-xLRfyFyQOFcLltKCds0LijfC6/HQJrrTTnZB8ciyn74LIkVAm++vZJ6eUVG20RmJtdP8REdy7vSOYW4M3//XLA==} 4730 peerDependencies: 4731 + react: ^18 || ^19 4732 4733 '@tokenizer/token@0.3.0': 4734 resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} ··· 4916 '@types/normalize-package-data@2.4.4': 4917 resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} 4918 4919 + '@types/picomatch@3.0.2': 4920 + resolution: {integrity: sha512-n0i8TD3UDB7paoMMxA3Y65vUncFJXjcUf7lQY7YyKGl6031FNjfsLs6pdLFCy2GNFxItPJG8GvvpbZc2skH7WA==} 4921 + 4922 + '@types/prop-types@15.7.12': 4923 + resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} 4924 + 4925 '@types/qrcode@1.5.5': 4926 resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==} 4927 ··· 4931 '@types/range-parser@1.2.7': 4932 resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} 4933 4934 + '@types/react-dom@19.2.3': 4935 + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} 4936 + peerDependencies: 4937 + '@types/react': ^19.2.0 4938 4939 + '@types/react@18.3.12': 4940 + resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} 4941 4942 '@types/request@2.48.12': 4943 resolution: {integrity: sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==} ··· 5614 base64-js@1.5.1: 5615 resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 5616 5617 batch@0.6.1: 5618 resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} 5619 ··· 5737 browser-or-node@3.0.0: 5738 resolution: {integrity: sha512-iczIdVJzGEYhP5DqQxYM9Hh7Ztpqqi+CXZpSmX8ALFs9ecXkQIeqRyM6TfxEfMVpwhl3dSuDvxdzzo9sUOIVBQ==} 5739 5740 + browserslist@4.24.2: 5741 + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} 5742 engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 5743 hasBin: true 5744 5745 + browserslist@4.24.5: 5746 + resolution: {integrity: sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==} 5747 engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 5748 hasBin: true 5749 ··· 5785 resolution: {integrity: sha512-bbZjGN4Om7dykr8ZcLb0tTO5L2becMR+HIez1ySUGgG/rvK+ePgBEuBA6lMOZqOTsUXhIKFUBH0sCXQ25fq5SA==} 5786 peerDependencies: 5787 expo: '*' 5788 + react: '*' 5789 react-native: '*' 5790 5791 byte-size@8.1.1: ··· 5872 5873 camelize@1.0.1: 5874 resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} 5875 + 5876 + caniuse-lite@1.0.30001677: 5877 + resolution: {integrity: sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog==} 5878 5879 caniuse-lite@1.0.30001718: 5880 resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==} 5881 5882 cbor-extract@2.2.0: 5883 resolution: {integrity: sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==} 5884 hasBin: true ··· 6423 engines: {node: '>=4'} 6424 hasBin: true 6425 6426 + csstype@3.1.3: 6427 + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 6428 6429 dargs@7.0.0: 6430 resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} ··· 6769 electron-to-chromium@1.5.159: 6770 resolution: {integrity: sha512-CEvHptWAMV5p6GJ0Lq8aheyvVbfzVrv5mmidu1D3pidoVNkB3tTBsTMVtPJ+rzRK5oV229mCLz9Zj/hNvU8GBA==} 6771 6772 + electron-to-chromium@1.5.51: 6773 + resolution: {integrity: sha512-kKeWV57KSS8jH4alKt/jKnvHPmJgBxXzGUSbMd4eQF+iOsVPl7bz2KUmu6eo80eMP8wVioTfTyTzdMgM15WXNg==} 6774 6775 electron-winstaller@5.4.0: 6776 resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==} ··· 6930 engines: {node: '>=18'} 6931 hasBin: true 6932 6933 escalade@3.2.0: 6934 resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 6935 engines: {node: '>=6'} ··· 7128 resolution: {integrity: sha512-GEQDCqC25uDBoXHEnXeBuwpeXvI+3fRGvtzwwt0ZKKzWaN+TgeF8H7c76p3Zi4DfBMFDcduM0CmOvJX+yCCLUQ==} 7129 peerDependencies: 7130 expo: '*' 7131 + react: '*' 7132 react-native: '*' 7133 7134 expo-build-properties@0.14.6: ··· 7175 resolution: {integrity: sha512-d+xrHYvSM9WB42wj8vP9OOFWyxed5R1evphfDb6zYBmC1dA9Hf89FpT7TNFtj2Bk3clTnpmVqQTCYbbA2P3CLg==} 7176 peerDependencies: 7177 expo: '*' 7178 + react: '*' 7179 7180 expo-json-utils@0.15.0: 7181 resolution: {integrity: sha512-duRT6oGl80IDzH2LD2yEFWNwGIC2WkozsB6HF3cDYNoNNdUvFk6uN3YiwsTsqVM/D0z6LEAQ01/SlYvN+Fw0JQ==} ··· 7184 resolution: {integrity: sha512-wU9qOnosy4+U4z/o4h8W9PjPvcFMfZXrlUoKTMBW7F4pLqhkkP/5G4EviPZixv4XWFMjn1ExQ5rV6BX8GwJsWA==} 7185 peerDependencies: 7186 expo: '*' 7187 + react: '*' 7188 7189 expo-linking@7.1.5: 7190 resolution: {integrity: sha512-8g20zOpROW78bF+bLI4a3ZWj4ntLgM0rCewKycPL0jk9WGvBrBtFtwwADJgOiV1EurNp3lcquerXGlWS+SOQyA==} 7191 peerDependencies: 7192 + react: '*' 7193 react-native: '*' 7194 7195 expo-localization@17.0.7: 7196 resolution: {integrity: sha512-ACg1B0tJLNa+f8mZfAaNrMyNzrrzHAARVH1sHHvh+LolKdQpgSKX69Uroz1Llv4C71furpwBklVStbNcEwVVVA==} 7197 peerDependencies: 7198 expo: '*' 7199 + react: '*' 7200 7201 expo-manifests@0.16.5: 7202 resolution: {integrity: sha512-zLUeJogn2C7qOE75Zz7jcmJorMfIbSRR35ctspN0OK/Hq/+PAAptA8p9jNVC8xp/91uP9uI8f3xPhh+A11eR2A==} ··· 7214 resolution: {integrity: sha512-AATxKoav5ZvwcRel2SKYNZc+EvOAKvAjxyBezC8y3J5fMNe/uKIhMzh3FN4fKdOi9ao/UBHkvLiUO2MqVnvBNg==} 7215 peerDependencies: 7216 expo: '*' 7217 + react: '*' 7218 react-native: '*' 7219 7220 expo-screen-orientation@9.0.7: ··· 7238 resolution: {integrity: sha512-J2Y7tChIFEcpgiVxxAXWaArOSIaHxct6keNZPs/6aHrSzUWmAlQS5vzGQueB1II65rl47ZtZcQEIl0NpiRhxxQ==} 7239 peerDependencies: 7240 expo: '*' 7241 + react: '*' 7242 react-native: '*' 7243 7244 expo-structured-headers@4.1.0: ··· 7264 hasBin: true 7265 peerDependencies: 7266 expo: '*' 7267 + react: '*' 7268 7269 expo-video@2.2.1: 7270 resolution: {integrity: sha512-dw3h0eMLK8WpY1Tnwsgrxx3sFqXiOujmurjGdr+RFG63ZurAze/H9uuKMVl3ps/ZNuK4q/2ifIiJudoFJfwKwA==} 7271 peerDependencies: 7272 expo: '*' 7273 + react: '*' 7274 react-native: '*' 7275 7276 expo-web-browser@14.1.6: ··· 7285 peerDependencies: 7286 '@expo/dom-webview': '*' 7287 '@expo/metro-runtime': '*' 7288 + react: '*' 7289 react-native: '*' 7290 react-native-webview: '*' 7291 peerDependenciesMeta: ··· 7749 resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} 7750 engines: {node: '>= 0.4'} 7751 7752 getenv@1.0.0: 7753 resolution: {integrity: sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==} 7754 engines: {node: '>=6'} ··· 7917 has-flag@4.0.0: 7918 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 7919 engines: {node: '>=8'} 7920 + 7921 + has-flag@5.0.1: 7922 + resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==} 7923 + engines: {node: '>=12'} 7924 7925 has-property-descriptors@1.0.2: 7926 resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} ··· 8372 iron-webcrypto@1.2.1: 8373 resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} 8374 8375 + is-absolute-url@4.0.1: 8376 + resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==} 8377 + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 8378 + 8379 is-alphabetical@2.0.1: 8380 resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} 8381 ··· 8923 lighthouse-logger@1.4.2: 8924 resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==} 8925 8926 lightningcss-darwin-arm64@1.27.0: 8927 resolution: {integrity: sha512-Gl/lqIXY+d+ySmMbgDf0pgaWSqrWYxVHoc88q+Vhf2YNzZ8DwoRzGt5NZDVqqIW5ScpSnmmjcgXP87Dn2ylSSQ==} 8928 engines: {node: '>= 12.0.0'} 8929 cpu: [arm64] 8930 os: [darwin] 8931 8932 + lightningcss-darwin-arm64@1.29.1: 8933 + resolution: {integrity: sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==} 8934 engines: {node: '>= 12.0.0'} 8935 cpu: [arm64] 8936 os: [darwin] ··· 8941 cpu: [x64] 8942 os: [darwin] 8943 8944 + lightningcss-darwin-x64@1.29.1: 8945 + resolution: {integrity: sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA==} 8946 engines: {node: '>= 12.0.0'} 8947 cpu: [x64] 8948 os: [darwin] ··· 8953 cpu: [x64] 8954 os: [freebsd] 8955 8956 + lightningcss-freebsd-x64@1.29.1: 8957 + resolution: {integrity: sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ==} 8958 engines: {node: '>= 12.0.0'} 8959 cpu: [x64] 8960 os: [freebsd] ··· 8965 cpu: [arm] 8966 os: [linux] 8967 8968 + lightningcss-linux-arm-gnueabihf@1.29.1: 8969 + resolution: {integrity: sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg==} 8970 engines: {node: '>= 12.0.0'} 8971 cpu: [arm] 8972 os: [linux] ··· 8977 cpu: [arm64] 8978 os: [linux] 8979 8980 + lightningcss-linux-arm64-gnu@1.29.1: 8981 + resolution: {integrity: sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ==} 8982 engines: {node: '>= 12.0.0'} 8983 cpu: [arm64] 8984 os: [linux] ··· 8989 cpu: [arm64] 8990 os: [linux] 8991 8992 + lightningcss-linux-arm64-musl@1.29.1: 8993 + resolution: {integrity: sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==} 8994 engines: {node: '>= 12.0.0'} 8995 cpu: [arm64] 8996 os: [linux] ··· 9001 cpu: [x64] 9002 os: [linux] 9003 9004 + lightningcss-linux-x64-gnu@1.29.1: 9005 + resolution: {integrity: sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==} 9006 engines: {node: '>= 12.0.0'} 9007 cpu: [x64] 9008 os: [linux] ··· 9013 cpu: [x64] 9014 os: [linux] 9015 9016 + lightningcss-linux-x64-musl@1.29.1: 9017 + resolution: {integrity: sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==} 9018 engines: {node: '>= 12.0.0'} 9019 cpu: [x64] 9020 os: [linux] ··· 9025 cpu: [arm64] 9026 os: [win32] 9027 9028 + lightningcss-win32-arm64-msvc@1.29.1: 9029 + resolution: {integrity: sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==} 9030 engines: {node: '>= 12.0.0'} 9031 cpu: [arm64] 9032 os: [win32] ··· 9037 cpu: [x64] 9038 os: [win32] 9039 9040 + lightningcss-win32-x64-msvc@1.29.1: 9041 + resolution: {integrity: sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q==} 9042 engines: {node: '>= 12.0.0'} 9043 cpu: [x64] 9044 os: [win32] ··· 9047 resolution: {integrity: sha512-8f7aNmS1+etYSLHht0fQApPc2kNO8qGRutifN5rVIc6Xo6ABsEbqOr758UwI7ALVbTt4x1fllKt0PYgzD9S3yQ==} 9048 engines: {node: '>= 12.0.0'} 9049 9050 + lightningcss@1.29.1: 9051 + resolution: {integrity: sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==} 9052 engines: {node: '>= 12.0.0'} 9053 9054 lilconfig@3.1.2: ··· 9237 lucide-react-native@0.514.0: 9238 resolution: {integrity: sha512-IaW5ItnJ9TDv9lZJOtjBRc2r217BRO4xNhd9g1hmW5GKvOtFzFYYfkogktUihiniXThwo1NBmNMa82mbWKMJVQ==} 9239 peerDependencies: 9240 + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 9241 react-native: '*' 9242 react-native-svg: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 9243 ··· 9904 node-mock-http@1.0.0: 9905 resolution: {integrity: sha512-0uGYQ1WQL1M5kKvGRXWQ3uZCHtLTO8hln3oBjIusM75WoesZ909uQJs/Hb946i2SS+Gsrhkaa6iAO17jRIv6DQ==} 9906 9907 + node-releases@2.0.18: 9908 + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} 9909 + 9910 node-releases@2.0.19: 9911 resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} 9912 9913 nodemailer-html-to-text@3.2.0: 9914 resolution: {integrity: sha512-RJUC6640QV1PzTHHapOrc6IzrAJUZtk2BdVdINZ9VTLm+mcQNyBO9LYyhrnufkzqiD9l8hPLJ97rSyK4WanPNg==} ··· 10604 postcss-value-parser@4.2.0: 10605 resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} 10606 10607 + postcss@8.4.47: 10608 + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} 10609 engines: {node: ^10 || ^12 || >=14} 10610 10611 postcss@8.5.3: ··· 10855 react-dom@19.0.0: 10856 resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} 10857 peerDependencies: 10858 + react: ^19.0.0 10859 10860 react-freeze@1.0.4: 10861 resolution: {integrity: sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==} 10862 engines: {node: '>=10'} 10863 peerDependencies: 10864 + react: '>=17.0.0' 10865 10866 react-i18next@15.7.4: 10867 resolution: {integrity: sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw==} 10868 peerDependencies: 10869 i18next: '>= 23.4.0' 10870 + react: '>= 16.8.0' 10871 react-dom: '*' 10872 react-native: '*' 10873 typescript: ^5 ··· 10895 react-native-edge-to-edge@1.6.0: 10896 resolution: {integrity: sha512-2WCNdE3Qd6Fwg9+4BpbATUxCLcouF6YRY7K+J36KJ4l3y+tWN6XCqAC4DuoGblAAbb2sLkhEDp4FOlbOIot2Og==} 10897 peerDependencies: 10898 + react: '*' 10899 react-native: '*' 10900 10901 react-native-edge-to-edge@1.6.2: 10902 resolution: {integrity: sha512-koEF6WRAfdGNelXlP7NtHrQhFGtplwciYNWLHOCTCk0Thc7dlxtqxHRYSA5vPJgWOEkVBFqxcoOqKwAtqOmLNw==} 10903 peerDependencies: 10904 + react: '*' 10905 react-native: '*' 10906 10907 react-native-fit-image@1.5.5: ··· 10910 react-native-gesture-handler@2.26.0: 10911 resolution: {integrity: sha512-pfE1j9Vzu0qpWj/Aq1IK+cYnougN69mCKvWuq1rdNjH2zs1WIszF0Mum9/oGQTemgjyc/JgiqOOTgwcleAMAGg==} 10912 peerDependencies: 10913 + react: '*' 10914 react-native: '*' 10915 10916 react-native-haptic-feedback@2.3.3: ··· 10921 react-native-is-edge-to-edge@1.1.7: 10922 resolution: {integrity: sha512-EH6i7E8epJGIcu7KpfXYXiV2JFIYITtq+rVS8uEb+92naMRBdxhTuS8Wn2Q7j9sqyO0B+Xbaaf9VdipIAmGW4w==} 10923 peerDependencies: 10924 + react: '*' 10925 react-native: '*' 10926 10927 react-native-localize@3.5.2: 10928 resolution: {integrity: sha512-HfQdwv5sRjh4AQ8a97OTjXYcxPNRlBxiQb861c7Ob6mRuNYCPtaJ45QTcZxZr31vAM3THvtOBp1soqWlQFxjnA==} 10929 peerDependencies: 10930 '@expo/config-plugins': ^9.0.0 || ^10.0.0 10931 + react: '*' 10932 react-native: '*' 10933 react-native-macos: '*' 10934 peerDependenciesMeta: ··· 10940 react-native-markdown-display@7.0.2: 10941 resolution: {integrity: sha512-Mn4wotMvMfLAwbX/huMLt202W5DsdpMO/kblk+6eUs55S57VVNni1gzZCh5qpznYLjIQELNh50VIozEfY6fvaQ==} 10942 peerDependencies: 10943 + react: '>=16.2.0' 10944 react-native: '>=0.50.4' 10945 10946 react-native-quick-base64@2.1.2: 10947 resolution: {integrity: sha512-xghaXpWdB0ji8OwYyo0fWezRroNxiNFCNFpGUIyE7+qc4gA/IGWnysIG5L0MbdoORv8FkTKUvfd6yCUN5R2VFA==} 10948 peerDependencies: 10949 + react: '*' 10950 react-native: '*' 10951 10952 react-native-quick-crypto@0.7.14: ··· 10956 resolution: {integrity: sha512-eVcNcqeOkMW+BUWAHdtvN3FKgC8J8wiEJkX6bNGGQaLS7m7e4amTfjIcqf/Ta+lerZLurmDaQ0lICI1CKPrb1Q==} 10957 peerDependencies: 10958 '@babel/core': ^7.0.0-0 10959 + react: '*' 10960 react-native: '*' 10961 10962 react-native-safe-area-context@5.4.1: 10963 resolution: {integrity: sha512-x+g3NblZ9jof8y+XkVvaGlpMrSlixhrJJ33BRzhTAKUKctQVecO1heSXmzxc5UdjvGYBKS6kPZVUw2b8NxHcPg==} 10964 peerDependencies: 10965 + react: '*' 10966 react-native: '*' 10967 10968 react-native-screens@4.11.1: 10969 resolution: {integrity: sha512-F0zOzRVa3ptZfLpD0J8ROdo+y1fEPw+VBFq1MTY/iyDu08al7qFUO5hLMd+EYMda5VXGaTFCa8q7bOppUszhJw==} 10970 peerDependencies: 10971 + react: '*' 10972 react-native: '*' 10973 10974 react-native-sortables@1.9.4: 10975 resolution: {integrity: sha512-a6hxT+gl14HA5Sm8UiLXJqF8KMEQVa+mUJd75OnzoVsmrxUDtjAatlMdV0kI9qTQDT/ZSFLPRmdUhOR762IA4g==} 10976 peerDependencies: 10977 + react: '*' 10978 react-native: '*' 10979 react-native-gesture-handler: '>=2.0.0' 10980 react-native-reanimated: '>=3.0.0' ··· 10982 react-native-svg@15.12.0: 10983 resolution: {integrity: sha512-iE25PxIJ6V0C6krReLquVw6R0QTsRTmEQc4K2Co3P6zsimU/jltcDBKYDy1h/5j9S/fqmMeXnpM+9LEWKJKI6A==} 10984 peerDependencies: 10985 + react: '*' 10986 react-native: '*' 10987 10988 react-native-web@0.20.0: 10989 resolution: {integrity: sha512-OOSgrw+aON6R3hRosCau/xVxdLzbjEcsLysYedka0ZON4ZZe6n9xgeN9ZkoejhARM36oTlUgHIQqxGutEJ9Wxg==} 10990 peerDependencies: 10991 + react: ^18.0.0 || ^19.0.0 10992 + react-dom: ^18.0.0 || ^19.0.0 10993 10994 react-native-webrtc@https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56: 10995 resolution: {tarball: https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56} ··· 11000 react-native-webview@13.15.0: 11001 resolution: {integrity: sha512-Vzjgy8mmxa/JO6l5KZrsTC7YemSdq+qB01diA0FqjUTaWGAGwuykpJ73MDj3+mzBSlaDxAEugHzTtkUQkQEQeQ==} 11002 peerDependencies: 11003 + react: '*' 11004 react-native: '*' 11005 11006 react-native@0.79.3: ··· 11008 engines: {node: '>=18'} 11009 hasBin: true 11010 peerDependencies: 11011 + '@types/react': ^19.0.0 11012 + react: ^19.0.0 11013 peerDependenciesMeta: 11014 '@types/react': 11015 optional: true ··· 11022 resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} 11023 engines: {node: '>=10'} 11024 peerDependencies: 11025 + '@types/react': '*' 11026 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 11027 peerDependenciesMeta: 11028 '@types/react': 11029 optional: true ··· 11032 resolution: {integrity: sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==} 11033 engines: {node: '>=10'} 11034 peerDependencies: 11035 + '@types/react': '*' 11036 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc 11037 peerDependenciesMeta: 11038 '@types/react': 11039 optional: true ··· 11042 resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} 11043 engines: {node: '>=10'} 11044 peerDependencies: 11045 + '@types/react': '*' 11046 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc 11047 peerDependenciesMeta: 11048 '@types/react': 11049 optional: true ··· 11134 resolution: {integrity: sha512-AA9iIVcrFiE70oyGuOvh2Vy7D5R2MVPig8dxzHuFyCnbO+AmMzn3JYNERp/PHsI2G0/aPeCuPZu6vOL1jZAeRg==} 11135 peerDependencies: 11136 expo: '>=44.0.0' 11137 + react: '*' 11138 react-native: '*' 11139 react-native-gesture-handler: '>=2.0.0' 11140 react-native-reanimated: ^2.0.0 || ^3.0.0 ··· 11321 resolution: {integrity: sha512-rzB7NnQpOkPHBWFPP3prUMqOP6yg3HkRGgcvR+lDyvyHoY3fZLFLYDkPXh78SPVBAE6VTCk/V+j8we4djg6o4g==} 11322 engines: {node: '>=4', npm: '>=2'} 11323 11324 resolve-workspace-root@2.0.0: 11325 resolution: {integrity: sha512-IsaBUZETJD5WsI11Wt8PKHwaIe45or6pwNc8yflvLJ4DWtImK9kuLoH5kUva/2Mmx/RdIyr4aONNSa2v9LTJsw==} 11326 ··· 11679 sonner@0.3.5: 11680 resolution: {integrity: sha512-yIwaQ4dftMvFApuruto2t7wGyyaPRpj5qYBWYJIz4Z7uGcVn0IfqI/hWN0JyJN4izNbZFuCYZISf3fOGnvSlNQ==} 11681 peerDependencies: 11682 + react: ^18.0.0 11683 + react-dom: ^18.0.0 11684 11685 sort-keys@2.0.0: 11686 resolution: {integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==} ··· 11778 standard-as-callback@2.1.0: 11779 resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} 11780 11781 + starlight-links-validator@0.19.2: 11782 + resolution: {integrity: sha512-IHeK3R78fsmv53VfRkGbXkwK1CQEUBHM9QPzBEyoAxjZ/ssi5gjV+F4oNNUppTR48iPp+lEY0MTAmvkX7yNnkw==} 11783 + engines: {node: '>=18.17.1'} 11784 + peerDependencies: 11785 + '@astrojs/starlight': '>=0.32.0' 11786 + astro: '>=5.1.5' 11787 + 11788 starlight-openapi-rapidoc@0.8.1-beta: 11789 resolution: {integrity: sha512-CicjuydKZsO8jZvhrtzz+GGWyfHnOZCZY/ww562H58CP/zSnskWcmcgVnCuD7DkKfi0ofvqumyyee1KgfkVipQ==} 11790 engines: {node: '>=18.14.1'} ··· 11800 '@astrojs/starlight': '>=0.34.0' 11801 astro: '>=5.5.0' 11802 11803 + starlight-sidebar-swipe@0.1.1: 11804 + resolution: {integrity: sha512-Q+xv7LSpSLCG3yQaEmZX4Qpks9dcIEc+FBA0Ql+LbLMO9IMBXt8S2zK5wJDhjJn5lbI0i0ipyP375T1GrVS8ig==} 11805 + engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} 11806 + peerDependencies: 11807 + '@astrojs/starlight': '>=0.30' 11808 + 11809 + starlight-sidebar-topics@0.6.2: 11810 + resolution: {integrity: sha512-SNCTUZS/hcVor0ZcaXbaSVU37+V+qtvzNirkvnOg3Mqu/awuGpthkH5+uKpiZqWxLffp6TrOlsv5E5QsxrndNg==} 11811 + engines: {node: '>=18'} 11812 + peerDependencies: 11813 + '@astrojs/starlight': '>=0.32.0' 11814 + 11815 statuses@1.5.0: 11816 resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} 11817 engines: {node: '>= 0.6'} ··· 12019 resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} 12020 engines: {node: '>= 8.0'} 12021 12022 + supports-color@10.2.2: 12023 + resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} 12024 + engines: {node: '>=18'} 12025 + 12026 supports-color@5.5.0: 12027 resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} 12028 engines: {node: '>=4'} ··· 12039 resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} 12040 engines: {node: '>=8'} 12041 12042 + supports-hyperlinks@4.4.0: 12043 + resolution: {integrity: sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg==} 12044 + engines: {node: '>=20'} 12045 + 12046 supports-preserve-symlinks-flag@1.0.0: 12047 resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 12048 engines: {node: '>= 0.4'} ··· 12105 terminal-link@2.1.1: 12106 resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} 12107 engines: {node: '>=8'} 12108 + 12109 + terminal-link@5.0.0: 12110 + resolution: {integrity: sha512-qFAy10MTMwjzjU8U16YS4YoZD+NQLHzLssFMNqgravjbvIPNiqkGFR4yjhJfmY9R5OFU7+yHxc6y+uGHkKwLRA==} 12111 + engines: {node: '>=20'} 12112 12113 terser-webpack-plugin@5.3.10: 12114 resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} ··· 12328 optional: true 12329 typescript: 12330 optional: true 12331 12332 tuf-js@2.2.1: 12333 resolution: {integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==} ··· 12661 resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} 12662 engines: {node: '>=4'} 12663 12664 + update-browserslist-db@1.1.1: 12665 + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} 12666 hasBin: true 12667 peerDependencies: 12668 browserslist: '>= 4.21.0' 12669 12670 + update-browserslist-db@1.1.3: 12671 + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} 12672 hasBin: true 12673 peerDependencies: 12674 browserslist: '>= 4.21.0' ··· 12690 resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} 12691 engines: {node: '>=10'} 12692 peerDependencies: 12693 + '@types/react': '*' 12694 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc 12695 peerDependenciesMeta: 12696 '@types/react': 12697 optional: true ··· 12699 use-latest-callback@0.2.1: 12700 resolution: {integrity: sha512-QWlq8Is8BGWBf883QOEQP5HWYX/kMI+JTbJ5rdtvJLmXTIh9XoHIO3PQcmQl8BU44VKxow1kbQUHa6mQSMALDQ==} 12701 peerDependencies: 12702 + react: '>=16.8' 12703 12704 use-sidecar@1.1.3: 12705 resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} 12706 engines: {node: '>=10'} 12707 peerDependencies: 12708 + '@types/react': '*' 12709 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc 12710 peerDependenciesMeta: 12711 '@types/react': 12712 optional: true 12713 12714 + use-sync-external-store@1.2.2: 12715 + resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} 12716 peerDependencies: 12717 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 12718 12719 username@5.1.0: 12720 resolution: {integrity: sha512-PCKbdWw85JsYMvmCv5GH3kXmM66rCd9m1hBEDutPNv94b/pqCMT4NtcKyeWYvLFiE8b+ha1Jdl8XAaUdPn5QTg==} ··· 13257 resolution: {integrity: sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==} 13258 engines: {node: '>=12.20.0'} 13259 peerDependencies: 13260 + '@types/react': '>=18.0.0' 13261 immer: '>=9.0.6' 13262 + react: '>=18.0.0' 13263 use-sync-external-store: '>=1.2.0' 13264 peerDependenciesMeta: 13265 '@types/react': ··· 13279 '@0no-co/graphql.web@1.0.11': {} 13280 13281 '@adraffy/ens-normalize@1.11.0': {} 13282 + 13283 + '@ampproject/remapping@2.3.0': 13284 + dependencies: 13285 + '@jridgewell/gen-mapping': 0.3.5 13286 + '@jridgewell/trace-mapping': 0.3.25 13287 13288 '@apidevtools/openapi-schemas@2.1.0': {} 13289 ··· 13319 transitivePeerDependencies: 13320 - supports-color 13321 13322 + '@astrojs/mdx@4.2.6(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2))': 13323 dependencies: 13324 '@astrojs/markdown-remark': 6.3.1 13325 '@mdx-js/mdx': 3.1.0(acorn@8.14.1) 13326 acorn: 8.14.1 13327 + astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2) 13328 es-module-lexer: 1.7.0 13329 estree-util-visit: 2.0.0 13330 hast-util-to-html: 9.0.5 ··· 13348 stream-replace-string: 2.0.0 13349 zod: 3.24.4 13350 13351 + '@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2))': 13352 dependencies: 13353 '@astrojs/markdown-remark': 6.3.1 13354 + '@astrojs/mdx': 4.2.6(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)) 13355 '@astrojs/sitemap': 3.3.1 13356 '@pagefind/default-ui': 1.3.0 13357 '@types/hast': 3.0.4 13358 '@types/js-yaml': 4.0.9 13359 '@types/mdast': 4.0.4 13360 + astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2) 13361 + astro-expressive-code: 0.41.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)) 13362 bcp-47: 2.1.0 13363 hast-util-from-html: 2.0.3 13364 hast-util-select: 6.0.4 ··· 14651 js-tokens: 4.0.0 14652 picocolors: 1.1.1 14653 14654 '@babel/compat-data@7.26.2': {} 14655 14656 '@babel/compat-data@7.27.3': {} 14657 14658 + '@babel/core@7.26.0': 14659 dependencies: 14660 + '@ampproject/remapping': 2.3.0 14661 + '@babel/code-frame': 7.26.2 14662 + '@babel/generator': 7.26.2 14663 + '@babel/helper-compilation-targets': 7.25.9 14664 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) 14665 + '@babel/helpers': 7.26.0 14666 + '@babel/parser': 7.26.2 14667 + '@babel/template': 7.25.9 14668 + '@babel/traverse': 7.25.9 14669 + '@babel/types': 7.26.0 14670 convert-source-map: 2.0.0 14671 debug: 4.4.0(supports-color@5.5.0) 14672 gensync: 1.0.0-beta.2 ··· 14678 '@babel/generator@7.26.2': 14679 dependencies: 14680 '@babel/parser': 7.26.2 14681 + '@babel/types': 7.26.0 14682 '@jridgewell/gen-mapping': 0.3.5 14683 '@jridgewell/trace-mapping': 0.3.25 14684 jsesc: 3.0.2 14685 14686 '@babel/generator@7.27.3': 14687 dependencies: 14688 + '@babel/parser': 7.27.3 14689 + '@babel/types': 7.27.3 14690 '@jridgewell/gen-mapping': 0.3.5 14691 '@jridgewell/trace-mapping': 0.3.25 14692 jsesc: 3.0.2 14693 14694 '@babel/helper-annotate-as-pure@7.27.3': 14695 dependencies: 14696 '@babel/types': 7.27.3 14697 14698 + '@babel/helper-compilation-targets@7.25.9': 14699 dependencies: 14700 + '@babel/compat-data': 7.26.2 14701 + '@babel/helper-validator-option': 7.25.9 14702 + browserslist: 4.24.2 14703 lru-cache: 5.1.1 14704 semver: 6.3.1 14705 14706 + '@babel/helper-compilation-targets@7.27.2': 14707 dependencies: 14708 + '@babel/compat-data': 7.27.3 14709 '@babel/helper-validator-option': 7.27.1 14710 + browserslist: 4.24.5 14711 lru-cache: 5.1.1 14712 semver: 6.3.1 14713 14714 + '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.26.0)': 14715 dependencies: 14716 + '@babel/core': 7.26.0 14717 '@babel/helper-annotate-as-pure': 7.27.3 14718 '@babel/helper-member-expression-to-functions': 7.27.1 14719 '@babel/helper-optimise-call-expression': 7.27.1 14720 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.26.0) 14721 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 14722 '@babel/traverse': 7.27.3 14723 semver: 6.3.1 14724 transitivePeerDependencies: 14725 - supports-color 14726 14727 + '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.26.0)': 14728 dependencies: 14729 + '@babel/core': 7.26.0 14730 '@babel/helper-annotate-as-pure': 7.27.3 14731 regexpu-core: 6.2.0 14732 semver: 6.3.1 14733 14734 + '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.26.0)': 14735 dependencies: 14736 + '@babel/core': 7.26.0 14737 + '@babel/helper-compilation-targets': 7.27.2 14738 '@babel/helper-plugin-utils': 7.27.1 14739 debug: 4.4.0(supports-color@5.5.0) 14740 lodash.debounce: 4.0.8 ··· 14742 transitivePeerDependencies: 14743 - supports-color 14744 14745 '@babel/helper-member-expression-to-functions@7.27.1': 14746 dependencies: 14747 + '@babel/traverse': 7.27.3 14748 + '@babel/types': 7.27.3 14749 transitivePeerDependencies: 14750 - supports-color 14751 14752 '@babel/helper-module-imports@7.25.9': 14753 dependencies: 14754 + '@babel/traverse': 7.25.9 14755 + '@babel/types': 7.26.0 14756 transitivePeerDependencies: 14757 - supports-color 14758 ··· 14763 transitivePeerDependencies: 14764 - supports-color 14765 14766 + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': 14767 dependencies: 14768 + '@babel/core': 7.26.0 14769 + '@babel/helper-module-imports': 7.27.1 14770 + '@babel/helper-validator-identifier': 7.25.9 14771 + '@babel/traverse': 7.25.9 14772 transitivePeerDependencies: 14773 - supports-color 14774 14775 + '@babel/helper-module-transforms@7.27.3(@babel/core@7.26.0)': 14776 dependencies: 14777 + '@babel/core': 7.26.0 14778 '@babel/helper-module-imports': 7.27.1 14779 '@babel/helper-validator-identifier': 7.27.1 14780 + '@babel/traverse': 7.27.3 14781 transitivePeerDependencies: 14782 - supports-color 14783 14784 '@babel/helper-optimise-call-expression@7.27.1': 14785 dependencies: 14786 + '@babel/types': 7.27.3 14787 14788 '@babel/helper-plugin-utils@7.25.9': {} 14789 14790 '@babel/helper-plugin-utils@7.27.1': {} 14791 14792 + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.26.0)': 14793 dependencies: 14794 + '@babel/core': 7.26.0 14795 '@babel/helper-annotate-as-pure': 7.27.3 14796 '@babel/helper-wrap-function': 7.27.1 14797 + '@babel/traverse': 7.27.3 14798 transitivePeerDependencies: 14799 - supports-color 14800 14801 + '@babel/helper-replace-supers@7.27.1(@babel/core@7.26.0)': 14802 dependencies: 14803 + '@babel/core': 7.26.0 14804 '@babel/helper-member-expression-to-functions': 7.27.1 14805 '@babel/helper-optimise-call-expression': 7.27.1 14806 + '@babel/traverse': 7.27.3 14807 transitivePeerDependencies: 14808 - supports-color 14809 14810 '@babel/helper-skip-transparent-expression-wrappers@7.27.1': 14811 dependencies: 14812 + '@babel/traverse': 7.27.3 14813 + '@babel/types': 7.27.3 14814 transitivePeerDependencies: 14815 - supports-color 14816 ··· 14822 14823 '@babel/helper-validator-identifier@7.27.1': {} 14824 14825 + '@babel/helper-validator-option@7.25.9': {} 14826 14827 '@babel/helper-validator-option@7.27.1': {} 14828 14829 '@babel/helper-wrap-function@7.27.1': 14830 dependencies: 14831 + '@babel/template': 7.27.2 14832 + '@babel/traverse': 7.27.3 14833 + '@babel/types': 7.27.3 14834 transitivePeerDependencies: 14835 - supports-color 14836 14837 + '@babel/helpers@7.26.0': 14838 dependencies: 14839 + '@babel/template': 7.25.9 14840 + '@babel/types': 7.26.0 14841 14842 '@babel/highlight@7.24.7': 14843 dependencies: 14844 + '@babel/helper-validator-identifier': 7.25.9 14845 chalk: 2.4.2 14846 js-tokens: 4.0.0 14847 picocolors: 1.1.1 14848 14849 '@babel/parser@7.26.2': 14850 dependencies: 14851 + '@babel/types': 7.26.0 14852 14853 '@babel/parser@7.27.3': 14854 dependencies: 14855 + '@babel/types': 7.27.3 14856 14857 + '@babel/plugin-proposal-decorators@7.24.7(@babel/core@7.26.0)': 14858 dependencies: 14859 + '@babel/core': 7.26.0 14860 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.26.0) 14861 '@babel/helper-plugin-utils': 7.27.1 14862 + '@babel/plugin-syntax-decorators': 7.24.7(@babel/core@7.26.0) 14863 transitivePeerDependencies: 14864 - supports-color 14865 14866 + '@babel/plugin-proposal-export-default-from@7.25.9(@babel/core@7.26.0)': 14867 dependencies: 14868 + '@babel/core': 7.26.0 14869 '@babel/helper-plugin-utils': 7.25.9 14870 14871 + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.0)': 14872 dependencies: 14873 + '@babel/core': 7.26.0 14874 '@babel/helper-plugin-utils': 7.27.1 14875 14876 + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.0)': 14877 dependencies: 14878 + '@babel/core': 7.26.0 14879 '@babel/helper-plugin-utils': 7.27.1 14880 14881 + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.0)': 14882 dependencies: 14883 + '@babel/core': 7.26.0 14884 '@babel/helper-plugin-utils': 7.27.1 14885 14886 + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.0)': 14887 dependencies: 14888 + '@babel/core': 7.26.0 14889 '@babel/helper-plugin-utils': 7.27.1 14890 14891 + '@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.26.0)': 14892 dependencies: 14893 + '@babel/core': 7.26.0 14894 '@babel/helper-plugin-utils': 7.27.1 14895 14896 + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.26.0)': 14897 dependencies: 14898 + '@babel/core': 7.26.0 14899 '@babel/helper-plugin-utils': 7.27.1 14900 14901 + '@babel/plugin-syntax-export-default-from@7.25.9(@babel/core@7.26.0)': 14902 dependencies: 14903 + '@babel/core': 7.26.0 14904 '@babel/helper-plugin-utils': 7.25.9 14905 14906 + '@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.0)': 14907 dependencies: 14908 + '@babel/core': 7.26.0 14909 '@babel/helper-plugin-utils': 7.25.9 14910 14911 + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.26.0)': 14912 dependencies: 14913 + '@babel/core': 7.26.0 14914 '@babel/helper-plugin-utils': 7.27.1 14915 14916 + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.0)': 14917 dependencies: 14918 + '@babel/core': 7.26.0 14919 '@babel/helper-plugin-utils': 7.27.1 14920 14921 + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.0)': 14922 dependencies: 14923 + '@babel/core': 7.26.0 14924 '@babel/helper-plugin-utils': 7.27.1 14925 14926 + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0)': 14927 dependencies: 14928 + '@babel/core': 7.26.0 14929 '@babel/helper-plugin-utils': 7.27.1 14930 14931 + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.0)': 14932 dependencies: 14933 + '@babel/core': 7.26.0 14934 '@babel/helper-plugin-utils': 7.27.1 14935 14936 + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.0)': 14937 dependencies: 14938 + '@babel/core': 7.26.0 14939 '@babel/helper-plugin-utils': 7.27.1 14940 14941 + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.0)': 14942 dependencies: 14943 + '@babel/core': 7.26.0 14944 '@babel/helper-plugin-utils': 7.27.1 14945 14946 + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.0)': 14947 dependencies: 14948 + '@babel/core': 7.26.0 14949 '@babel/helper-plugin-utils': 7.27.1 14950 14951 + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.0)': 14952 dependencies: 14953 + '@babel/core': 7.26.0 14954 '@babel/helper-plugin-utils': 7.27.1 14955 14956 + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.0)': 14957 dependencies: 14958 + '@babel/core': 7.26.0 14959 '@babel/helper-plugin-utils': 7.27.1 14960 14961 + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.0)': 14962 dependencies: 14963 + '@babel/core': 7.26.0 14964 '@babel/helper-plugin-utils': 7.27.1 14965 14966 + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.0)': 14967 dependencies: 14968 + '@babel/core': 7.26.0 14969 '@babel/helper-plugin-utils': 7.27.1 14970 14971 + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.0)': 14972 dependencies: 14973 + '@babel/core': 7.26.0 14974 '@babel/helper-plugin-utils': 7.27.1 14975 14976 + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.26.0)': 14977 dependencies: 14978 + '@babel/core': 7.26.0 14979 '@babel/helper-plugin-utils': 7.27.1 14980 14981 + '@babel/plugin-transform-async-generator-functions@7.27.1(@babel/core@7.26.0)': 14982 dependencies: 14983 + '@babel/core': 7.26.0 14984 '@babel/helper-plugin-utils': 7.27.1 14985 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.26.0) 14986 + '@babel/traverse': 7.27.3 14987 transitivePeerDependencies: 14988 - supports-color 14989 14990 + '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.26.0)': 14991 dependencies: 14992 + '@babel/core': 7.26.0 14993 '@babel/helper-module-imports': 7.27.1 14994 '@babel/helper-plugin-utils': 7.27.1 14995 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.26.0) 14996 transitivePeerDependencies: 14997 - supports-color 14998 14999 + '@babel/plugin-transform-block-scoping@7.27.3(@babel/core@7.26.0)': 15000 dependencies: 15001 + '@babel/core': 7.26.0 15002 '@babel/helper-plugin-utils': 7.27.1 15003 15004 + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.26.0)': 15005 dependencies: 15006 + '@babel/core': 7.26.0 15007 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.26.0) 15008 '@babel/helper-plugin-utils': 7.27.1 15009 transitivePeerDependencies: 15010 - supports-color 15011 15012 + '@babel/plugin-transform-classes@7.27.1(@babel/core@7.26.0)': 15013 dependencies: 15014 + '@babel/core': 7.26.0 15015 '@babel/helper-annotate-as-pure': 7.27.3 15016 '@babel/helper-compilation-targets': 7.27.2 15017 '@babel/helper-plugin-utils': 7.27.1 15018 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.26.0) 15019 '@babel/traverse': 7.27.3 15020 globals: 11.12.0 15021 transitivePeerDependencies: 15022 - supports-color 15023 15024 + '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.26.0)': 15025 dependencies: 15026 + '@babel/core': 7.26.0 15027 '@babel/helper-plugin-utils': 7.27.1 15028 + '@babel/template': 7.27.2 15029 15030 + '@babel/plugin-transform-destructuring@7.27.3(@babel/core@7.26.0)': 15031 dependencies: 15032 + '@babel/core': 7.26.0 15033 '@babel/helper-plugin-utils': 7.27.1 15034 15035 + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.26.0)': 15036 dependencies: 15037 + '@babel/core': 7.26.0 15038 '@babel/helper-plugin-utils': 7.27.1 15039 15040 + '@babel/plugin-transform-flow-strip-types@7.25.9(@babel/core@7.26.0)': 15041 dependencies: 15042 + '@babel/core': 7.26.0 15043 '@babel/helper-plugin-utils': 7.25.9 15044 + '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.26.0) 15045 15046 + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.26.0)': 15047 dependencies: 15048 + '@babel/core': 7.26.0 15049 '@babel/helper-plugin-utils': 7.27.1 15050 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 15051 transitivePeerDependencies: 15052 - supports-color 15053 15054 + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.26.0)': 15055 dependencies: 15056 + '@babel/core': 7.26.0 15057 + '@babel/helper-compilation-targets': 7.27.2 15058 '@babel/helper-plugin-utils': 7.27.1 15059 + '@babel/traverse': 7.27.3 15060 transitivePeerDependencies: 15061 - supports-color 15062 15063 + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.26.0)': 15064 dependencies: 15065 + '@babel/core': 7.26.0 15066 '@babel/helper-plugin-utils': 7.27.1 15067 15068 + '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.26.0)': 15069 dependencies: 15070 + '@babel/core': 7.26.0 15071 '@babel/helper-plugin-utils': 7.27.1 15072 15073 + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.26.0)': 15074 dependencies: 15075 + '@babel/core': 7.26.0 15076 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.26.0) 15077 '@babel/helper-plugin-utils': 7.27.1 15078 transitivePeerDependencies: 15079 - supports-color 15080 15081 + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.26.0)': 15082 dependencies: 15083 + '@babel/core': 7.26.0 15084 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.0) 15085 '@babel/helper-plugin-utils': 7.27.1 15086 15087 + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.26.0)': 15088 dependencies: 15089 + '@babel/core': 7.26.0 15090 '@babel/helper-plugin-utils': 7.27.1 15091 15092 + '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.26.0)': 15093 dependencies: 15094 + '@babel/core': 7.26.0 15095 '@babel/helper-plugin-utils': 7.27.1 15096 15097 + '@babel/plugin-transform-object-rest-spread@7.27.3(@babel/core@7.26.0)': 15098 dependencies: 15099 + '@babel/core': 7.26.0 15100 '@babel/helper-compilation-targets': 7.27.2 15101 '@babel/helper-plugin-utils': 7.27.1 15102 + '@babel/plugin-transform-destructuring': 7.27.3(@babel/core@7.26.0) 15103 + '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.26.0) 15104 15105 + '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.26.0)': 15106 dependencies: 15107 + '@babel/core': 7.26.0 15108 '@babel/helper-plugin-utils': 7.27.1 15109 15110 + '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.26.0)': 15111 dependencies: 15112 + '@babel/core': 7.26.0 15113 '@babel/helper-plugin-utils': 7.27.1 15114 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 15115 transitivePeerDependencies: 15116 - supports-color 15117 15118 + '@babel/plugin-transform-parameters@7.27.1(@babel/core@7.26.0)': 15119 dependencies: 15120 + '@babel/core': 7.26.0 15121 '@babel/helper-plugin-utils': 7.27.1 15122 15123 + '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.26.0)': 15124 dependencies: 15125 + '@babel/core': 7.26.0 15126 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.26.0) 15127 '@babel/helper-plugin-utils': 7.27.1 15128 transitivePeerDependencies: 15129 - supports-color 15130 15131 + '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.26.0)': 15132 dependencies: 15133 + '@babel/core': 7.26.0 15134 '@babel/helper-annotate-as-pure': 7.27.3 15135 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.26.0) 15136 '@babel/helper-plugin-utils': 7.27.1 15137 transitivePeerDependencies: 15138 - supports-color 15139 15140 + '@babel/plugin-transform-react-display-name@7.24.7(@babel/core@7.26.0)': 15141 dependencies: 15142 + '@babel/core': 7.26.0 15143 '@babel/helper-plugin-utils': 7.27.1 15144 15145 + '@babel/plugin-transform-react-jsx-development@7.24.7(@babel/core@7.26.0)': 15146 dependencies: 15147 + '@babel/core': 7.26.0 15148 + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) 15149 transitivePeerDependencies: 15150 - supports-color 15151 15152 + '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0)': 15153 dependencies: 15154 + '@babel/core': 7.26.0 15155 '@babel/helper-plugin-utils': 7.27.1 15156 15157 + '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0)': 15158 dependencies: 15159 + '@babel/core': 7.26.0 15160 '@babel/helper-plugin-utils': 7.27.1 15161 15162 + '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.0)': 15163 dependencies: 15164 + '@babel/core': 7.26.0 15165 '@babel/helper-annotate-as-pure': 7.27.3 15166 '@babel/helper-module-imports': 7.27.1 15167 '@babel/helper-plugin-utils': 7.27.1 15168 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) 15169 + '@babel/types': 7.27.3 15170 transitivePeerDependencies: 15171 - supports-color 15172 15173 + '@babel/plugin-transform-react-pure-annotations@7.24.7(@babel/core@7.26.0)': 15174 dependencies: 15175 + '@babel/core': 7.26.0 15176 '@babel/helper-annotate-as-pure': 7.27.3 15177 '@babel/helper-plugin-utils': 7.27.1 15178 15179 + '@babel/plugin-transform-regenerator@7.27.1(@babel/core@7.26.0)': 15180 dependencies: 15181 + '@babel/core': 7.26.0 15182 '@babel/helper-plugin-utils': 7.27.1 15183 15184 + '@babel/plugin-transform-runtime@7.25.9(@babel/core@7.26.0)': 15185 dependencies: 15186 + '@babel/core': 7.26.0 15187 '@babel/helper-module-imports': 7.25.9 15188 '@babel/helper-plugin-utils': 7.25.9 15189 + babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.26.0) 15190 + babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.26.0) 15191 + babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.26.0) 15192 semver: 6.3.1 15193 transitivePeerDependencies: 15194 - supports-color 15195 15196 + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.26.0)': 15197 dependencies: 15198 + '@babel/core': 7.26.0 15199 '@babel/helper-plugin-utils': 7.27.1 15200 15201 + '@babel/plugin-transform-spread@7.27.1(@babel/core@7.26.0)': 15202 dependencies: 15203 + '@babel/core': 7.26.0 15204 '@babel/helper-plugin-utils': 7.27.1 15205 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 15206 transitivePeerDependencies: 15207 - supports-color 15208 15209 + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.26.0)': 15210 dependencies: 15211 + '@babel/core': 7.26.0 15212 '@babel/helper-plugin-utils': 7.27.1 15213 15214 + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.26.0)': 15215 dependencies: 15216 + '@babel/core': 7.26.0 15217 '@babel/helper-plugin-utils': 7.27.1 15218 15219 + '@babel/plugin-transform-typescript@7.25.9(@babel/core@7.26.0)': 15220 dependencies: 15221 + '@babel/core': 7.26.0 15222 '@babel/helper-annotate-as-pure': 7.27.3 15223 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.26.0) 15224 '@babel/helper-plugin-utils': 7.27.1 15225 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 15226 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0) 15227 transitivePeerDependencies: 15228 - supports-color 15229 15230 + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.26.0)': 15231 dependencies: 15232 + '@babel/core': 7.26.0 15233 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.0) 15234 '@babel/helper-plugin-utils': 7.27.1 15235 15236 + '@babel/preset-react@7.24.7(@babel/core@7.26.0)': 15237 dependencies: 15238 + '@babel/core': 7.26.0 15239 '@babel/helper-plugin-utils': 7.27.1 15240 '@babel/helper-validator-option': 7.27.1 15241 + '@babel/plugin-transform-react-display-name': 7.24.7(@babel/core@7.26.0) 15242 + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) 15243 + '@babel/plugin-transform-react-jsx-development': 7.24.7(@babel/core@7.26.0) 15244 + '@babel/plugin-transform-react-pure-annotations': 7.24.7(@babel/core@7.26.0) 15245 transitivePeerDependencies: 15246 - supports-color 15247 15248 + '@babel/preset-typescript@7.24.7(@babel/core@7.26.0)': 15249 dependencies: 15250 + '@babel/core': 7.26.0 15251 '@babel/helper-plugin-utils': 7.27.1 15252 '@babel/helper-validator-option': 7.27.1 15253 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) 15254 + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.26.0) 15255 + '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0) 15256 transitivePeerDependencies: 15257 - supports-color 15258 ··· 15262 15263 '@babel/runtime@7.28.4': {} 15264 15265 + '@babel/template@7.25.9': 15266 + dependencies: 15267 + '@babel/code-frame': 7.26.2 15268 + '@babel/parser': 7.26.2 15269 + '@babel/types': 7.26.0 15270 + 15271 '@babel/template@7.27.2': 15272 dependencies: 15273 '@babel/code-frame': 7.27.1 15274 '@babel/parser': 7.27.3 15275 + '@babel/types': 7.27.3 15276 15277 + '@babel/traverse@7.25.9': 15278 dependencies: 15279 + '@babel/code-frame': 7.26.2 15280 + '@babel/generator': 7.26.2 15281 + '@babel/parser': 7.26.2 15282 + '@babel/template': 7.25.9 15283 + '@babel/types': 7.26.0 15284 debug: 4.4.0(supports-color@5.5.0) 15285 globals: 11.12.0 15286 transitivePeerDependencies: 15287 - supports-color 15288 15289 + '@babel/traverse@7.27.3': 15290 dependencies: 15291 + '@babel/code-frame': 7.27.1 15292 + '@babel/generator': 7.27.3 15293 + '@babel/parser': 7.27.3 15294 + '@babel/template': 7.27.2 15295 + '@babel/types': 7.27.3 15296 debug: 4.4.0(supports-color@5.5.0) 15297 + globals: 11.12.0 15298 transitivePeerDependencies: 15299 - supports-color 15300 ··· 15308 '@babel/helper-string-parser': 7.27.1 15309 '@babel/helper-validator-identifier': 7.27.1 15310 15311 + '@bacons/text-decoder@0.0.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))': 15312 dependencies: 15313 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 15314 15315 '@capsizecss/unpack@2.4.0(encoding@0.1.13)': 15316 dependencies: ··· 15338 '@cbor-extract/cbor-extract-win32-x64@2.2.0': 15339 optional: true 15340 15341 + '@config-plugins/react-native-webrtc@10.0.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))': 15342 dependencies: 15343 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 15344 15345 + '@config-plugins/react-native-webrtc@10.0.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))': 15346 + dependencies: 15347 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 15348 + 15349 + '@craftzdog/react-native-buffer@6.0.5(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 15350 dependencies: 15351 ieee754: 1.2.1 15352 + react-native-quick-base64: 2.1.2(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 15353 + transitivePeerDependencies: 15354 + - react 15355 + - react-native 15356 + 15357 + '@craftzdog/react-native-buffer@6.0.5(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 15358 + dependencies: 15359 + ieee754: 1.2.1 15360 + react-native-quick-base64: 2.1.2(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 15361 transitivePeerDependencies: 15362 - react 15363 - react-native ··· 15461 '@malept/cross-spawn-promise': 2.0.0 15462 chalk: 4.1.2 15463 debug: 4.4.0(supports-color@5.5.0) 15464 + fast-glob: 3.3.2 15465 filenamify: 4.3.0 15466 find-up: 5.0.0 15467 fs-extra: 10.1.0 ··· 15844 '@esbuild/aix-ppc64@0.25.3': 15845 optional: true 15846 15847 '@esbuild/android-arm64@0.25.3': 15848 optional: true 15849 15850 '@esbuild/android-arm@0.25.3': 15851 optional: true 15852 15853 '@esbuild/android-x64@0.25.3': 15854 optional: true 15855 15856 '@esbuild/darwin-arm64@0.25.3': 15857 optional: true 15858 15859 '@esbuild/darwin-x64@0.25.3': 15860 optional: true 15861 15862 '@esbuild/freebsd-arm64@0.25.3': 15863 optional: true 15864 15865 '@esbuild/freebsd-x64@0.25.3': 15866 optional: true 15867 15868 '@esbuild/linux-arm64@0.25.3': 15869 optional: true 15870 15871 '@esbuild/linux-arm@0.25.3': 15872 optional: true 15873 15874 '@esbuild/linux-ia32@0.25.3': 15875 optional: true 15876 15877 '@esbuild/linux-loong64@0.25.3': 15878 optional: true 15879 15880 '@esbuild/linux-mips64el@0.25.3': 15881 optional: true 15882 15883 '@esbuild/linux-ppc64@0.25.3': 15884 optional: true 15885 15886 '@esbuild/linux-riscv64@0.25.3': 15887 optional: true 15888 15889 '@esbuild/linux-s390x@0.25.3': 15890 optional: true 15891 15892 '@esbuild/linux-x64@0.25.3': 15893 optional: true 15894 15895 '@esbuild/netbsd-arm64@0.25.3': 15896 optional: true 15897 15898 '@esbuild/netbsd-x64@0.25.3': 15899 optional: true 15900 15901 '@esbuild/openbsd-arm64@0.25.3': 15902 optional: true 15903 15904 '@esbuild/openbsd-x64@0.25.3': 15905 optional: true 15906 15907 '@esbuild/sunos-x64@0.25.3': 15908 optional: true 15909 15910 '@esbuild/win32-arm64@0.25.3': 15911 optional: true 15912 15913 '@esbuild/win32-ia32@0.25.3': 15914 optional: true 15915 15916 '@esbuild/win32-x64@0.25.3': 15917 optional: true 15918 15919 '@eslint-community/eslint-utils@4.4.1(eslint@9.14.0(jiti@2.6.1))': ··· 16185 16186 '@expo/metro-config@0.19.4': 16187 dependencies: 16188 + '@babel/core': 7.26.0 16189 '@babel/generator': 7.26.2 16190 '@babel/parser': 7.26.2 16191 '@babel/types': 7.26.0 ··· 16201 jsc-safe-url: 0.2.4 16202 lightningcss: 1.27.0 16203 minimatch: 3.1.2 16204 + postcss: 8.4.47 16205 resolve-from: 5.0.0 16206 transitivePeerDependencies: 16207 - supports-color 16208 16209 '@expo/metro-config@0.20.14': 16210 dependencies: 16211 + '@babel/core': 7.26.0 16212 '@babel/generator': 7.27.3 16213 '@babel/parser': 7.27.3 16214 '@babel/types': 7.27.3 ··· 16225 jsc-safe-url: 0.2.4 16226 lightningcss: 1.27.0 16227 minimatch: 9.0.5 16228 + postcss: 8.4.47 16229 resolve-from: 5.0.0 16230 transitivePeerDependencies: 16231 - supports-color 16232 16233 + '@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))': 16234 dependencies: 16235 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 16236 + 16237 + '@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))': 16238 + dependencies: 16239 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 16240 + optional: true 16241 16242 '@expo/osascript@2.2.4': 16243 dependencies: ··· 16776 - supports-color 16777 optional: true 16778 16779 + '@gorhom/bottom-sheet@5.1.6(@types/react@18.3.12)(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 16780 dependencies: 16781 + '@gorhom/portal': 1.0.14(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 16782 invariant: 2.2.4 16783 react: 19.0.0 16784 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 16785 + react-native-gesture-handler: 2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 16786 + react-native-reanimated: 3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 16787 optionalDependencies: 16788 + '@types/react': 18.3.12 16789 16790 + '@gorhom/portal@1.0.14(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 16791 dependencies: 16792 nanoid: 3.3.11 16793 react: 19.0.0 16794 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 16795 16796 '@grpc/grpc-js@1.10.10': 16797 dependencies: ··· 17115 17116 '@jest/transform@29.7.0': 17117 dependencies: 17118 + '@babel/core': 7.26.0 17119 '@jest/types': 29.6.3 17120 '@jridgewell/trace-mapping': 0.3.25 17121 babel-plugin-istanbul: 6.1.1 ··· 17142 '@types/yargs': 17.0.32 17143 chalk: 4.1.2 17144 17145 '@jridgewell/gen-mapping@0.3.5': 17146 dependencies: 17147 '@jridgewell/set-array': 1.2.1 17148 '@jridgewell/sourcemap-codec': 1.5.0 17149 '@jridgewell/trace-mapping': 0.3.25 17150 17151 '@jridgewell/resolve-uri@3.1.2': {} 17152 17153 '@jridgewell/set-array@1.2.1': {} 17154 17155 '@jridgewell/source-map@0.3.6': 17156 dependencies: 17157 + '@jridgewell/gen-mapping': 0.3.5 17158 + '@jridgewell/trace-mapping': 0.3.25 17159 17160 '@jridgewell/sourcemap-codec@1.5.0': {} 17161 17162 '@jridgewell/trace-mapping@0.3.25': 17163 dependencies: 17164 '@jridgewell/resolve-uri': 3.1.2 17165 '@jridgewell/sourcemap-codec': 1.5.0 ··· 17689 17690 '@radix-ui/primitive@1.1.3': {} 17691 17692 + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17693 dependencies: 17694 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17695 react: 19.0.0 17696 react-dom: 19.0.0(react@19.0.0) 17697 optionalDependencies: 17698 + '@types/react': 18.3.12 17699 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17700 17701 + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17702 dependencies: 17703 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17704 + '@radix-ui/react-context': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17705 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17706 + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.12)(react@19.0.0) 17707 react: 19.0.0 17708 react-dom: 19.0.0(react@19.0.0) 17709 optionalDependencies: 17710 + '@types/react': 18.3.12 17711 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17712 17713 + '@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.12)(react@19.0.0)': 17714 dependencies: 17715 react: 19.0.0 17716 optionalDependencies: 17717 + '@types/react': 18.3.12 17718 17719 + '@radix-ui/react-context@1.1.2(@types/react@18.3.12)(react@19.0.0)': 17720 dependencies: 17721 react: 19.0.0 17722 optionalDependencies: 17723 + '@types/react': 18.3.12 17724 17725 + '@radix-ui/react-direction@1.1.1(@types/react@18.3.12)(react@19.0.0)': 17726 dependencies: 17727 react: 19.0.0 17728 optionalDependencies: 17729 + '@types/react': 18.3.12 17730 17731 + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17732 dependencies: 17733 '@radix-ui/primitive': 1.1.3 17734 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17735 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17736 + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17737 + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17738 react: 19.0.0 17739 react-dom: 19.0.0(react@19.0.0) 17740 optionalDependencies: 17741 + '@types/react': 18.3.12 17742 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17743 17744 + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17745 dependencies: 17746 '@radix-ui/primitive': 1.1.3 17747 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17748 + '@radix-ui/react-context': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17749 + '@radix-ui/react-id': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17750 + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17751 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17752 + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.12)(react@19.0.0) 17753 react: 19.0.0 17754 react-dom: 19.0.0(react@19.0.0) 17755 optionalDependencies: 17756 + '@types/react': 18.3.12 17757 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17758 17759 + '@radix-ui/react-focus-guards@1.1.3(@types/react@18.3.12)(react@19.0.0)': 17760 dependencies: 17761 react: 19.0.0 17762 optionalDependencies: 17763 + '@types/react': 18.3.12 17764 17765 + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17766 dependencies: 17767 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17768 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17769 + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17770 react: 19.0.0 17771 react-dom: 19.0.0(react@19.0.0) 17772 optionalDependencies: 17773 + '@types/react': 18.3.12 17774 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17775 17776 + '@radix-ui/react-id@1.1.1(@types/react@18.3.12)(react@19.0.0)': 17777 dependencies: 17778 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17779 react: 19.0.0 17780 optionalDependencies: 17781 + '@types/react': 18.3.12 17782 17783 + '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17784 dependencies: 17785 '@radix-ui/primitive': 1.1.3 17786 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17787 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17788 + '@radix-ui/react-context': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17789 + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17790 + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17791 + '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.12)(react@19.0.0) 17792 + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17793 + '@radix-ui/react-id': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17794 + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17795 + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17796 + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17797 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17798 + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17799 + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.12)(react@19.0.0) 17800 + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17801 aria-hidden: 1.2.4 17802 react: 19.0.0 17803 react-dom: 19.0.0(react@19.0.0) 17804 + react-remove-scroll: 2.7.1(@types/react@18.3.12)(react@19.0.0) 17805 optionalDependencies: 17806 + '@types/react': 18.3.12 17807 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17808 17809 + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17810 dependencies: 17811 '@floating-ui/react-dom': 2.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17812 + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17813 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17814 + '@radix-ui/react-context': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17815 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17816 + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17817 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17818 + '@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17819 + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17820 '@radix-ui/rect': 1.1.1 17821 react: 19.0.0 17822 react-dom: 19.0.0(react@19.0.0) 17823 optionalDependencies: 17824 + '@types/react': 18.3.12 17825 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17826 17827 + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17828 dependencies: 17829 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17830 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17831 react: 19.0.0 17832 react-dom: 19.0.0(react@19.0.0) 17833 optionalDependencies: 17834 + '@types/react': 18.3.12 17835 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17836 17837 + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17838 dependencies: 17839 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17840 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17841 react: 19.0.0 17842 react-dom: 19.0.0(react@19.0.0) 17843 optionalDependencies: 17844 + '@types/react': 18.3.12 17845 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17846 17847 + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17848 dependencies: 17849 + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.12)(react@19.0.0) 17850 react: 19.0.0 17851 react-dom: 19.0.0(react@19.0.0) 17852 optionalDependencies: 17853 + '@types/react': 18.3.12 17854 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17855 17856 + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17857 dependencies: 17858 '@radix-ui/primitive': 1.1.3 17859 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17860 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17861 + '@radix-ui/react-context': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17862 + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17863 + '@radix-ui/react-id': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17864 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17865 + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17866 + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.12)(react@19.0.0) 17867 react: 19.0.0 17868 react-dom: 19.0.0(react@19.0.0) 17869 optionalDependencies: 17870 + '@types/react': 18.3.12 17871 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17872 17873 + '@radix-ui/react-slider@1.3.5(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 17874 dependencies: 17875 '@radix-ui/number': 1.1.1 17876 '@radix-ui/primitive': 1.1.2 17877 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17878 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17879 + '@radix-ui/react-context': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17880 + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17881 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 17882 + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.12)(react@19.0.0) 17883 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17884 + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17885 + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17886 react: 19.0.0 17887 react-dom: 19.0.0(react@19.0.0) 17888 optionalDependencies: 17889 + '@types/react': 18.3.12 17890 + '@types/react-dom': 19.2.3(@types/react@18.3.12) 17891 17892 + '@radix-ui/react-slot@1.2.3(@types/react@18.3.12)(react@19.0.0)': 17893 dependencies: 17894 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@19.0.0) 17895 react: 19.0.0 17896 optionalDependencies: 17897 + '@types/react': 18.3.12 17898 17899 + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.3.12)(react@19.0.0)': 17900 dependencies: 17901 react: 19.0.0 17902 optionalDependencies: 17903 + '@types/react': 18.3.12 17904 17905 + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.12)(react@19.0.0)': 17906 dependencies: 17907 + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.12)(react@19.0.0) 17908 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17909 react: 19.0.0 17910 optionalDependencies: 17911 + '@types/react': 18.3.12 17912 17913 + '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.3.12)(react@19.0.0)': 17914 dependencies: 17915 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17916 react: 19.0.0 17917 optionalDependencies: 17918 + '@types/react': 18.3.12 17919 17920 + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.12)(react@19.0.0)': 17921 dependencies: 17922 + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17923 react: 19.0.0 17924 optionalDependencies: 17925 + '@types/react': 18.3.12 17926 17927 + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.12)(react@19.0.0)': 17928 dependencies: 17929 react: 19.0.0 17930 optionalDependencies: 17931 + '@types/react': 18.3.12 17932 17933 + '@radix-ui/react-use-previous@1.1.1(@types/react@18.3.12)(react@19.0.0)': 17934 dependencies: 17935 react: 19.0.0 17936 optionalDependencies: 17937 + '@types/react': 18.3.12 17938 17939 + '@radix-ui/react-use-rect@1.1.1(@types/react@18.3.12)(react@19.0.0)': 17940 dependencies: 17941 '@radix-ui/rect': 1.1.1 17942 react: 19.0.0 17943 optionalDependencies: 17944 + '@types/react': 18.3.12 17945 17946 + '@radix-ui/react-use-size@1.1.1(@types/react@18.3.12)(react@19.0.0)': 17947 dependencies: 17948 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.12)(react@19.0.0) 17949 react: 19.0.0 17950 optionalDependencies: 17951 + '@types/react': 18.3.12 17952 17953 '@radix-ui/rect@1.1.1': {} 17954 17955 + '@react-native-firebase/app@22.2.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 17956 dependencies: 17957 firebase: 11.3.1 17958 react: 19.0.0 17959 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 17960 optionalDependencies: 17961 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 17962 transitivePeerDependencies: 17963 - '@react-native-async-storage/async-storage' 17964 17965 + '@react-native-firebase/messaging@22.2.1(d55f93459f56060c343a0d66dd2a08a1)': 17966 dependencies: 17967 + '@react-native-firebase/app': 22.2.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 17968 optionalDependencies: 17969 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 17970 17971 '@react-native/assets-registry@0.79.3': {} 17972 17973 + '@react-native/babel-plugin-codegen@0.79.0-rc.4(@babel/core@7.26.0)': 17974 dependencies: 17975 + '@babel/traverse': 7.27.3 17976 + '@react-native/codegen': 0.79.0-rc.4(@babel/core@7.26.0) 17977 transitivePeerDependencies: 17978 - '@babel/core' 17979 - supports-color 17980 17981 + '@react-native/babel-plugin-codegen@0.79.3(@babel/core@7.26.0)': 17982 dependencies: 17983 + '@babel/traverse': 7.27.3 17984 + '@react-native/codegen': 0.79.3(@babel/core@7.26.0) 17985 transitivePeerDependencies: 17986 - '@babel/core' 17987 - supports-color 17988 17989 + '@react-native/babel-preset@0.79.0-rc.4(@babel/core@7.26.0)': 17990 dependencies: 17991 + '@babel/core': 7.26.0 17992 + '@babel/plugin-proposal-export-default-from': 7.25.9(@babel/core@7.26.0) 17993 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.26.0) 17994 + '@babel/plugin-syntax-export-default-from': 7.25.9(@babel/core@7.26.0) 17995 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) 17996 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) 17997 + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.26.0) 17998 + '@babel/plugin-transform-async-generator-functions': 7.27.1(@babel/core@7.26.0) 17999 + '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.26.0) 18000 + '@babel/plugin-transform-block-scoping': 7.27.3(@babel/core@7.26.0) 18001 + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.26.0) 18002 + '@babel/plugin-transform-classes': 7.27.1(@babel/core@7.26.0) 18003 + '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.26.0) 18004 + '@babel/plugin-transform-destructuring': 7.27.3(@babel/core@7.26.0) 18005 + '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.26.0) 18006 + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.26.0) 18007 + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.26.0) 18008 + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.26.0) 18009 + '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.26.0) 18010 + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.26.0) 18011 + '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.26.0) 18012 + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.26.0) 18013 + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.26.0) 18014 + '@babel/plugin-transform-object-rest-spread': 7.27.3(@babel/core@7.26.0) 18015 + '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.26.0) 18016 + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.26.0) 18017 + '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.26.0) 18018 + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.26.0) 18019 + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.26.0) 18020 + '@babel/plugin-transform-react-display-name': 7.24.7(@babel/core@7.26.0) 18021 + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) 18022 + '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) 18023 + '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) 18024 + '@babel/plugin-transform-regenerator': 7.27.1(@babel/core@7.26.0) 18025 + '@babel/plugin-transform-runtime': 7.25.9(@babel/core@7.26.0) 18026 + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.26.0) 18027 + '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.26.0) 18028 + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.26.0) 18029 + '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0) 18030 + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.26.0) 18031 '@babel/template': 7.27.2 18032 + '@react-native/babel-plugin-codegen': 0.79.0-rc.4(@babel/core@7.26.0) 18033 babel-plugin-syntax-hermes-parser: 0.25.1 18034 + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.26.0) 18035 react-refresh: 0.14.2 18036 transitivePeerDependencies: 18037 - supports-color 18038 18039 + '@react-native/babel-preset@0.79.3(@babel/core@7.26.0)': 18040 dependencies: 18041 + '@babel/core': 7.26.0 18042 + '@babel/plugin-proposal-export-default-from': 7.25.9(@babel/core@7.26.0) 18043 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.26.0) 18044 + '@babel/plugin-syntax-export-default-from': 7.25.9(@babel/core@7.26.0) 18045 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) 18046 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) 18047 + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.26.0) 18048 + '@babel/plugin-transform-async-generator-functions': 7.27.1(@babel/core@7.26.0) 18049 + '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.26.0) 18050 + '@babel/plugin-transform-block-scoping': 7.27.3(@babel/core@7.26.0) 18051 + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.26.0) 18052 + '@babel/plugin-transform-classes': 7.27.1(@babel/core@7.26.0) 18053 + '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.26.0) 18054 + '@babel/plugin-transform-destructuring': 7.27.3(@babel/core@7.26.0) 18055 + '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.26.0) 18056 + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.26.0) 18057 + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.26.0) 18058 + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.26.0) 18059 + '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.26.0) 18060 + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.26.0) 18061 + '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.26.0) 18062 + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.26.0) 18063 + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.26.0) 18064 + '@babel/plugin-transform-object-rest-spread': 7.27.3(@babel/core@7.26.0) 18065 + '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.26.0) 18066 + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.26.0) 18067 + '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.26.0) 18068 + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.26.0) 18069 + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.26.0) 18070 + '@babel/plugin-transform-react-display-name': 7.24.7(@babel/core@7.26.0) 18071 + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) 18072 + '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) 18073 + '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) 18074 + '@babel/plugin-transform-regenerator': 7.27.1(@babel/core@7.26.0) 18075 + '@babel/plugin-transform-runtime': 7.25.9(@babel/core@7.26.0) 18076 + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.26.0) 18077 + '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.26.0) 18078 + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.26.0) 18079 + '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0) 18080 + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.26.0) 18081 + '@babel/template': 7.27.2 18082 + '@react-native/babel-plugin-codegen': 0.79.3(@babel/core@7.26.0) 18083 babel-plugin-syntax-hermes-parser: 0.25.1 18084 + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.26.0) 18085 react-refresh: 0.14.2 18086 transitivePeerDependencies: 18087 - supports-color 18088 18089 + '@react-native/codegen@0.79.0-rc.4(@babel/core@7.26.0)': 18090 dependencies: 18091 + '@babel/core': 7.26.0 18092 glob: 7.2.3 18093 hermes-parser: 0.25.1 18094 invariant: 2.2.4 18095 nullthrows: 1.1.1 18096 yargs: 17.7.2 18097 18098 + '@react-native/codegen@0.79.3(@babel/core@7.26.0)': 18099 dependencies: 18100 + '@babel/core': 7.26.0 18101 glob: 7.2.3 18102 hermes-parser: 0.25.1 18103 invariant: 2.2.4 ··· 18149 18150 '@react-native/normalize-colors@0.79.3': {} 18151 18152 + '@react-native/virtualized-lists@0.79.3(@types/react@18.3.12)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18153 dependencies: 18154 invariant: 2.2.4 18155 nullthrows: 1.1.1 18156 react: 19.0.0 18157 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18158 optionalDependencies: 18159 + '@types/react': 18.3.12 18160 18161 + '@react-native/virtualized-lists@0.79.3(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18162 dependencies: 18163 + invariant: 2.2.4 18164 + nullthrows: 1.1.1 18165 + react: 19.0.0 18166 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18167 + 18168 + '@react-navigation/bottom-tabs@6.6.1(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18169 + dependencies: 18170 + '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18171 + '@react-navigation/native': 6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18172 color: 4.2.3 18173 react: 19.0.0 18174 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18175 + react-native-safe-area-context: 5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18176 + react-native-screens: 4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18177 warn-once: 0.1.1 18178 18179 '@react-navigation/core@6.4.17(react@19.0.0)': ··· 18186 react-is: 16.13.1 18187 use-latest-callback: 0.2.1(react@19.0.0) 18188 18189 + '@react-navigation/drawer@6.7.2(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18190 dependencies: 18191 + '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18192 + '@react-navigation/native': 6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18193 color: 4.2.3 18194 react: 19.0.0 18195 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18196 + react-native-gesture-handler: 2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18197 + react-native-reanimated: 3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18198 + react-native-safe-area-context: 5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18199 + react-native-screens: 4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18200 warn-once: 0.1.1 18201 18202 + '@react-navigation/elements@1.3.31(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18203 dependencies: 18204 + '@react-navigation/native': 6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18205 react: 19.0.0 18206 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18207 + react-native-safe-area-context: 5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18208 18209 + '@react-navigation/native-stack@6.11.0(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18210 dependencies: 18211 + '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18212 + '@react-navigation/native': 6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18213 react: 19.0.0 18214 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18215 + react-native-safe-area-context: 5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18216 + react-native-screens: 4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18217 warn-once: 0.1.1 18218 18219 + '@react-navigation/native@6.1.18(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18220 dependencies: 18221 '@react-navigation/core': 6.4.17(react@19.0.0) 18222 escape-string-regexp: 4.0.0 18223 fast-deep-equal: 3.1.3 18224 nanoid: 3.3.11 18225 react: 19.0.0 18226 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18227 18228 '@react-navigation/routers@6.1.9': 18229 dependencies: ··· 18231 18232 '@readme/better-ajv-errors@1.6.0(ajv@8.16.0)': 18233 dependencies: 18234 + '@babel/code-frame': 7.27.1 18235 '@babel/runtime': 7.26.0 18236 '@humanwhocodes/momoa': 2.0.4 18237 ajv: 8.16.0 ··· 18242 18243 '@readme/better-ajv-errors@2.3.2(ajv@8.16.0)': 18244 dependencies: 18245 + '@babel/code-frame': 7.27.1 18246 '@babel/runtime': 7.26.0 18247 '@humanwhocodes/momoa': 2.0.4 18248 ajv: 8.16.0 ··· 18295 18296 '@reforged/maker-types@1.0.1': {} 18297 18298 + '@rn-primitives/dropdown-menu@1.2.0(@rn-primitives/portal@1.3.0(@types/react@18.3.12)(immer@10.1.1)(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(use-sync-external-store@1.2.2(react@19.0.0)))(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18299 dependencies: 18300 + '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18301 + '@rn-primitives/hooks': 1.3.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18302 + '@rn-primitives/portal': 1.3.0(@types/react@18.3.12)(immer@10.1.1)(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(use-sync-external-store@1.2.2(react@19.0.0)) 18303 + '@rn-primitives/slot': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18304 + '@rn-primitives/types': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18305 + '@rn-primitives/utils': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18306 react: 19.0.0 18307 optionalDependencies: 18308 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18309 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18310 transitivePeerDependencies: 18311 - '@types/react' 18312 - '@types/react-dom' 18313 - react-dom 18314 18315 + '@rn-primitives/hooks@1.3.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18316 dependencies: 18317 + '@rn-primitives/types': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18318 react: 19.0.0 18319 optionalDependencies: 18320 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18321 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18322 18323 + '@rn-primitives/portal@1.3.0(@types/react@18.3.12)(immer@10.1.1)(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(use-sync-external-store@1.2.2(react@19.0.0))': 18324 dependencies: 18325 react: 19.0.0 18326 + zustand: 5.0.5(@types/react@18.3.12)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.2.2(react@19.0.0)) 18327 optionalDependencies: 18328 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18329 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18330 transitivePeerDependencies: 18331 - '@types/react' 18332 - immer 18333 - use-sync-external-store 18334 18335 + '@rn-primitives/slider@1.2.0(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18336 dependencies: 18337 + '@radix-ui/react-slider': 1.3.5(@types/react-dom@19.2.3(@types/react@18.3.12))(@types/react@18.3.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18338 + '@rn-primitives/slot': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18339 + '@rn-primitives/types': 1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 18340 react: 19.0.0 18341 optionalDependencies: 18342 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18343 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18344 transitivePeerDependencies: 18345 - '@types/react' 18346 - '@types/react-dom' 18347 - react-dom 18348 18349 + '@rn-primitives/slot@1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18350 dependencies: 18351 react: 19.0.0 18352 optionalDependencies: 18353 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18354 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18355 18356 + '@rn-primitives/types@1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18357 dependencies: 18358 react: 19.0.0 18359 optionalDependencies: 18360 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18361 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18362 18363 + '@rn-primitives/utils@1.2.0(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18364 dependencies: 18365 react: 19.0.0 18366 optionalDependencies: 18367 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18368 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 18369 18370 '@rollup/pluginutils@5.1.4(rollup@4.40.1)': ··· 18526 18527 '@sentry/core@8.54.0': {} 18528 18529 + '@sentry/react-native@6.14.0(encoding@0.1.13)(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': 18530 dependencies: 18531 '@sentry/babel-plugin-component-annotate': 3.4.0 18532 '@sentry/browser': 8.54.0 ··· 18536 '@sentry/types': 8.54.0 18537 '@sentry/utils': 8.54.0 18538 react: 19.0.0 18539 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 18540 optionalDependencies: 18541 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 18542 transitivePeerDependencies: 18543 - encoding 18544 - supports-color ··· 19522 19523 '@types/normalize-package-data@2.4.4': {} 19524 19525 + '@types/picomatch@3.0.2': {} 19526 + 19527 + '@types/prop-types@15.7.12': {} 19528 + 19529 '@types/qrcode@1.5.5': 19530 dependencies: 19531 '@types/node': 22.15.17 ··· 19534 19535 '@types/range-parser@1.2.7': {} 19536 19537 + '@types/react-dom@19.2.3(@types/react@18.3.12)': 19538 dependencies: 19539 + '@types/react': 18.3.12 19540 19541 + '@types/react@18.3.12': 19542 dependencies: 19543 + '@types/prop-types': 15.7.12 19544 + csstype: 3.1.3 19545 19546 '@types/request@2.48.12': 19547 dependencies: ··· 19671 '@typescript-eslint/types': 8.13.0 19672 '@typescript-eslint/visitor-keys': 8.13.0 19673 debug: 4.4.0(supports-color@5.5.0) 19674 + fast-glob: 3.3.2 19675 is-glob: 4.0.3 19676 minimatch: 9.0.5 19677 semver: 7.7.1 ··· 20119 20120 astring@1.9.0: {} 20121 20122 + astro-expressive-code@0.41.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)): 20123 dependencies: 20124 + astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2) 20125 rehype-expressive-code: 0.41.2 20126 20127 + astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2): 20128 dependencies: 20129 '@astrojs/compiler': 2.12.0 20130 '@astrojs/internal-helpers': 0.6.1 ··· 20177 unist-util-visit: 5.0.0 20178 unstorage: 1.16.0(idb-keyval@6.2.1)(ioredis@5.7.0) 20179 vfile: 6.0.3 20180 + vite: 6.3.4(@types/node@22.15.17)(jiti@2.6.1)(lightningcss@1.29.1)(terser@5.32.0)(yaml@2.8.2) 20181 + vitefu: 1.0.6(vite@6.3.4(@types/node@22.15.17)(jiti@2.6.1)(lightningcss@1.29.1)(terser@5.32.0)(yaml@2.8.2)) 20182 xxhash-wasm: 1.1.0 20183 yargs-parser: 21.1.1 20184 yocto-spinner: 0.2.2 ··· 20260 20261 b4a@1.6.7: {} 20262 20263 + babel-jest@29.7.0(@babel/core@7.26.0): 20264 dependencies: 20265 + '@babel/core': 7.26.0 20266 '@jest/transform': 29.7.0 20267 '@types/babel__core': 7.20.5 20268 babel-plugin-istanbul: 6.1.1 20269 + babel-preset-jest: 29.6.3(@babel/core@7.26.0) 20270 chalk: 4.1.2 20271 graceful-fs: 4.2.11 20272 slash: 3.0.0 ··· 20285 20286 babel-plugin-jest-hoist@29.6.3: 20287 dependencies: 20288 + '@babel/template': 7.27.2 20289 + '@babel/types': 7.27.3 20290 '@types/babel__core': 7.20.5 20291 '@types/babel__traverse': 7.20.6 20292 20293 + babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.26.0): 20294 dependencies: 20295 '@babel/compat-data': 7.26.2 20296 + '@babel/core': 7.26.0 20297 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0) 20298 semver: 6.3.1 20299 transitivePeerDependencies: 20300 - supports-color 20301 20302 + babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.26.0): 20303 dependencies: 20304 + '@babel/core': 7.26.0 20305 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0) 20306 core-js-compat: 3.39.0 20307 transitivePeerDependencies: 20308 - supports-color 20309 20310 + babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.26.0): 20311 dependencies: 20312 + '@babel/core': 7.26.0 20313 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0) 20314 transitivePeerDependencies: 20315 - supports-color 20316 ··· 20320 dependencies: 20321 hermes-parser: 0.25.1 20322 20323 + babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.26.0): 20324 dependencies: 20325 + '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.26.0) 20326 transitivePeerDependencies: 20327 - '@babel/core' 20328 20329 + babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.0): 20330 dependencies: 20331 + '@babel/core': 7.26.0 20332 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.0) 20333 + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.0) 20334 + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.0) 20335 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.0) 20336 + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.26.0) 20337 + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.0) 20338 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.0) 20339 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.0) 20340 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) 20341 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.0) 20342 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.0) 20343 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.0) 20344 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) 20345 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.0) 20346 + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.0) 20347 20348 + babel-preset-expo@13.0.0(@babel/core@7.26.0): 20349 dependencies: 20350 '@babel/helper-module-imports': 7.27.1 20351 + '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.26.0) 20352 + '@babel/plugin-proposal-export-default-from': 7.25.9(@babel/core@7.26.0) 20353 + '@babel/plugin-syntax-export-default-from': 7.25.9(@babel/core@7.26.0) 20354 + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.26.0) 20355 + '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.26.0) 20356 + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.26.0) 20357 + '@babel/plugin-transform-object-rest-spread': 7.27.3(@babel/core@7.26.0) 20358 + '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.26.0) 20359 + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.26.0) 20360 + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.26.0) 20361 + '@babel/plugin-transform-runtime': 7.25.9(@babel/core@7.26.0) 20362 + '@babel/preset-react': 7.24.7(@babel/core@7.26.0) 20363 + '@babel/preset-typescript': 7.24.7(@babel/core@7.26.0) 20364 + '@react-native/babel-preset': 0.79.0-rc.4(@babel/core@7.26.0) 20365 babel-plugin-react-native-web: 0.19.13 20366 babel-plugin-syntax-hermes-parser: 0.25.1 20367 + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.26.0) 20368 debug: 4.4.0(supports-color@5.5.0) 20369 react-refresh: 0.14.2 20370 resolve-from: 5.0.0 ··· 20372 - '@babel/core' 20373 - supports-color 20374 20375 + babel-preset-expo@13.2.0(@babel/core@7.26.0): 20376 dependencies: 20377 '@babel/helper-module-imports': 7.27.1 20378 + '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.26.0) 20379 + '@babel/plugin-proposal-export-default-from': 7.25.9(@babel/core@7.26.0) 20380 + '@babel/plugin-syntax-export-default-from': 7.25.9(@babel/core@7.26.0) 20381 + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.26.0) 20382 + '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.26.0) 20383 + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.26.0) 20384 + '@babel/plugin-transform-object-rest-spread': 7.27.3(@babel/core@7.26.0) 20385 + '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.26.0) 20386 + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.26.0) 20387 + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.26.0) 20388 + '@babel/plugin-transform-runtime': 7.25.9(@babel/core@7.26.0) 20389 + '@babel/preset-react': 7.24.7(@babel/core@7.26.0) 20390 + '@babel/preset-typescript': 7.24.7(@babel/core@7.26.0) 20391 + '@react-native/babel-preset': 0.79.3(@babel/core@7.26.0) 20392 babel-plugin-react-native-web: 0.19.13 20393 babel-plugin-syntax-hermes-parser: 0.25.1 20394 + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.26.0) 20395 debug: 4.4.0(supports-color@5.5.0) 20396 react-refresh: 0.14.2 20397 resolve-from: 5.0.0 ··· 20399 - '@babel/core' 20400 - supports-color 20401 20402 + babel-preset-jest@29.6.3(@babel/core@7.26.0): 20403 dependencies: 20404 + '@babel/core': 7.26.0 20405 babel-plugin-jest-hoist: 29.6.3 20406 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) 20407 20408 badgin@1.2.3: {} 20409 ··· 20446 base64-arraybuffer@1.0.2: {} 20447 20448 base64-js@1.5.1: {} 20449 20450 batch@0.6.1: {} 20451 ··· 20608 20609 browser-or-node@3.0.0: {} 20610 20611 + browserslist@4.24.2: 20612 + dependencies: 20613 + caniuse-lite: 1.0.30001677 20614 + electron-to-chromium: 1.5.51 20615 + node-releases: 2.0.18 20616 + update-browserslist-db: 1.1.1(browserslist@4.24.2) 20617 + 20618 browserslist@4.24.5: 20619 dependencies: 20620 caniuse-lite: 1.0.30001718 20621 electron-to-chromium: 1.5.159 20622 node-releases: 2.0.19 20623 update-browserslist-db: 1.1.3(browserslist@4.24.5) 20624 20625 bser@2.1.1: 20626 dependencies: ··· 20659 esbuild: 0.25.3 20660 load-tsconfig: 0.2.5 20661 20662 + burnt@0.12.2(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 20663 dependencies: 20664 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 20665 react: 19.0.0 20666 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 20667 sf-symbols-typescript: 1.0.0 20668 sonner: 0.3.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 20669 transitivePeerDependencies: ··· 20775 20776 camelize@1.0.1: {} 20777 20778 + caniuse-lite@1.0.30001677: {} 20779 20780 + caniuse-lite@1.0.30001718: {} 20781 20782 cbor-extract@2.2.0: 20783 dependencies: ··· 21216 21217 core-js-compat@3.39.0: 21218 dependencies: 21219 + browserslist: 4.24.2 21220 21221 core-util-is@1.0.3: {} 21222 ··· 21357 21358 cssesc@3.0.0: {} 21359 21360 + csstype@3.1.3: {} 21361 21362 dargs@7.0.0: {} 21363 ··· 21690 21691 electron-to-chromium@1.5.159: {} 21692 21693 + electron-to-chromium@1.5.51: {} 21694 21695 electron-winstaller@5.4.0: 21696 dependencies: ··· 21928 '@esbuild/win32-ia32': 0.25.3 21929 '@esbuild/win32-x64': 0.25.3 21930 21931 escalade@3.2.0: {} 21932 21933 escape-html@1.0.3: {} ··· 22181 dependencies: 22182 homedir-polyfill: 1.0.3 22183 22184 + expo-application@6.1.4(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22185 dependencies: 22186 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22187 22188 + expo-asset@11.1.5(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22189 dependencies: 22190 '@expo/image-utils': 0.7.4 22191 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22192 + expo-constants: 17.1.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22193 + react: 19.0.0 22194 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22195 + transitivePeerDependencies: 22196 + - supports-color 22197 + 22198 + expo-asset@11.1.5(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22199 + dependencies: 22200 + '@expo/image-utils': 0.7.4 22201 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22202 + expo-constants: 17.1.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22203 react: 19.0.0 22204 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22205 transitivePeerDependencies: 22206 - supports-color 22207 22208 + expo-build-properties@0.14.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22209 dependencies: 22210 ajv: 8.16.0 22211 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22212 semver: 7.7.1 22213 22214 + expo-constants@17.1.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22215 + dependencies: 22216 + '@expo/config': 11.0.10 22217 + '@expo/env': 1.0.5 22218 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22219 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22220 + transitivePeerDependencies: 22221 + - supports-color 22222 + 22223 + expo-constants@17.1.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22224 dependencies: 22225 '@expo/config': 11.0.10 22226 '@expo/env': 1.0.5 22227 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22228 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22229 transitivePeerDependencies: 22230 - supports-color 22231 22232 + expo-dev-client@5.2.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22233 dependencies: 22234 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22235 + expo-dev-launcher: 5.1.12(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22236 + expo-dev-menu: 6.1.11(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22237 + expo-dev-menu-interface: 1.10.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22238 + expo-manifests: 0.16.5(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22239 + expo-updates-interface: 1.1.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22240 transitivePeerDependencies: 22241 - supports-color 22242 22243 + expo-dev-launcher@5.1.12(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22244 dependencies: 22245 ajv: 8.11.0 22246 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22247 + expo-dev-menu: 6.1.11(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22248 + expo-manifests: 0.16.5(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22249 resolve-from: 5.0.0 22250 transitivePeerDependencies: 22251 - supports-color 22252 22253 + expo-dev-menu-interface@1.10.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22254 dependencies: 22255 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22256 22257 + expo-dev-menu@6.1.11(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22258 dependencies: 22259 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22260 + expo-dev-menu-interface: 1.10.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22261 22262 expo-eas-client@0.14.3: {} 22263 22264 + expo-file-system@18.1.10(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22265 dependencies: 22266 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22267 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22268 22269 + expo-file-system@18.1.10(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22270 dependencies: 22271 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22272 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22273 + 22274 + expo-font@13.3.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22275 + dependencies: 22276 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22277 + fontfaceobserver: 2.3.0 22278 + react: 19.0.0 22279 + 22280 + expo-font@13.3.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22281 + dependencies: 22282 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22283 fontfaceobserver: 2.3.0 22284 react: 19.0.0 22285 22286 expo-json-utils@0.15.0: {} 22287 22288 + expo-keep-awake@14.1.4(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22289 dependencies: 22290 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22291 react: 19.0.0 22292 22293 + expo-keep-awake@14.1.4(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22294 dependencies: 22295 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22296 + react: 19.0.0 22297 + 22298 + expo-linking@7.1.5(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22299 + dependencies: 22300 + expo-constants: 17.1.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22301 invariant: 2.2.4 22302 react: 19.0.0 22303 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22304 transitivePeerDependencies: 22305 - expo 22306 - supports-color 22307 22308 + expo-localization@17.0.7(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22309 dependencies: 22310 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22311 react: 19.0.0 22312 rtl-detect: 1.1.2 22313 22314 + expo-manifests@0.16.5(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22315 dependencies: 22316 '@expo/config': 11.0.10 22317 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22318 expo-json-utils: 0.15.0 22319 transitivePeerDependencies: 22320 - supports-color ··· 22333 dependencies: 22334 invariant: 2.2.4 22335 22336 + expo-notifications@0.31.3(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22337 dependencies: 22338 '@expo/image-utils': 0.7.4 22339 '@ide/backoff': 1.0.0 22340 abort-controller: 3.0.0 22341 assert: 2.1.0 22342 badgin: 1.2.3 22343 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22344 + expo-application: 6.1.4(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22345 + expo-constants: 17.1.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22346 react: 19.0.0 22347 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22348 transitivePeerDependencies: 22349 - supports-color 22350 22351 + expo-screen-orientation@9.0.7(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22352 dependencies: 22353 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22354 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22355 22356 + expo-sensors@15.0.7(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22357 dependencies: 22358 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22359 invariant: 2.2.4 22360 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22361 22362 + expo-splash-screen@0.30.9(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22363 dependencies: 22364 '@expo/prebuild-config': 9.0.6 22365 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22366 transitivePeerDependencies: 22367 - supports-color 22368 22369 + expo-sqlite@15.2.12(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22370 dependencies: 22371 await-lock: 2.2.2 22372 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22373 react: 19.0.0 22374 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22375 + 22376 + expo-sqlite@15.2.12(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22377 + dependencies: 22378 + await-lock: 2.2.2 22379 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22380 + react: 19.0.0 22381 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22382 22383 expo-structured-headers@4.1.0: {} 22384 22385 + expo-system-ui@5.0.8(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22386 dependencies: 22387 '@react-native/normalize-colors': 0.79.3 22388 debug: 4.4.0(supports-color@5.5.0) 22389 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22390 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22391 optionalDependencies: 22392 react-native-web: 0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 22393 transitivePeerDependencies: 22394 - supports-color 22395 22396 + expo-updates-interface@1.1.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)): 22397 dependencies: 22398 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22399 22400 + expo-updates@0.28.14(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22401 dependencies: 22402 '@expo/code-signing-certificates': 0.0.5 22403 '@expo/config': 11.0.10 ··· 22405 '@expo/spawn-async': 1.7.2 22406 arg: 4.1.0 22407 chalk: 4.1.2 22408 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22409 expo-eas-client: 0.14.3 22410 + expo-manifests: 0.16.5(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22411 expo-structured-headers: 4.1.0 22412 + expo-updates-interface: 1.1.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)) 22413 glob: 10.4.5 22414 ignore: 5.3.1 22415 react: 19.0.0 ··· 22417 transitivePeerDependencies: 22418 - supports-color 22419 22420 + expo-video@2.2.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 22421 dependencies: 22422 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22423 react: 19.0.0 22424 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22425 22426 + expo-web-browser@14.1.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 22427 dependencies: 22428 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 22429 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22430 22431 + expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10): 22432 dependencies: 22433 '@babel/runtime': 7.26.0 22434 '@expo/cli': 0.24.14(bufferutil@4.0.8)(utf-8-validate@5.0.10) ··· 22437 '@expo/fingerprint': 0.13.0 22438 '@expo/metro-config': 0.20.14 22439 '@expo/vector-icons': 14.0.4 22440 + babel-preset-expo: 13.2.0(@babel/core@7.26.0) 22441 + expo-asset: 11.1.5(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22442 + expo-constants: 17.1.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22443 + expo-file-system: 18.1.10(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22444 + expo-font: 13.3.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22445 + expo-keep-awake: 14.1.4(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22446 expo-modules-autolinking: 2.1.11 22447 expo-modules-core: 2.4.0 22448 react: 19.0.0 22449 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22450 + react-native-edge-to-edge: 1.6.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22451 whatwg-url-without-unicode: 8.0.0-3 22452 optionalDependencies: 22453 + '@expo/metro-runtime': 5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22454 + react-native-webview: 13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22455 + transitivePeerDependencies: 22456 + - '@babel/core' 22457 + - babel-plugin-react-compiler 22458 + - bufferutil 22459 + - graphql 22460 + - supports-color 22461 + - utf-8-validate 22462 + 22463 + expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10): 22464 + dependencies: 22465 + '@babel/runtime': 7.26.0 22466 + '@expo/cli': 0.24.14(bufferutil@4.0.8)(utf-8-validate@5.0.10) 22467 + '@expo/config': 11.0.10 22468 + '@expo/config-plugins': 10.0.2 22469 + '@expo/fingerprint': 0.13.0 22470 + '@expo/metro-config': 0.20.14 22471 + '@expo/vector-icons': 14.0.4 22472 + babel-preset-expo: 13.2.0(@babel/core@7.26.0) 22473 + expo-asset: 11.1.5(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22474 + expo-constants: 17.1.6(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22475 + expo-file-system: 18.1.10(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22476 + expo-font: 13.3.1(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22477 + expo-keep-awake: 14.1.4(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22478 + expo-modules-autolinking: 2.1.11 22479 + expo-modules-core: 2.4.0 22480 + react: 19.0.0 22481 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 22482 + react-native-edge-to-edge: 1.6.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22483 + whatwg-url-without-unicode: 8.0.0-3 22484 + optionalDependencies: 22485 + '@expo/metro-runtime': 5.0.4(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 22486 + react-native-webview: 13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 22487 transitivePeerDependencies: 22488 - '@babel/core' 22489 - babel-plugin-react-compiler ··· 23126 es-errors: 1.3.0 23127 get-intrinsic: 1.2.4 23128 23129 getenv@1.0.0: {} 23130 23131 getenv@2.0.0: {} ··· 23374 has-flag@3.0.0: {} 23375 23376 has-flag@4.0.0: {} 23377 + 23378 + has-flag@5.0.1: {} 23379 23380 has-property-descriptors@1.0.2: 23381 dependencies: ··· 24050 ipaddr.js@2.2.0: {} 24051 24052 iron-webcrypto@1.2.1: {} 24053 + 24054 + is-absolute-url@4.0.1: {} 24055 24056 is-alphabetical@2.0.1: {} 24057 ··· 24268 24269 istanbul-lib-instrument@5.2.1: 24270 dependencies: 24271 + '@babel/core': 7.26.0 24272 + '@babel/parser': 7.27.3 24273 '@istanbuljs/schema': 0.1.3 24274 istanbul-lib-coverage: 3.2.2 24275 semver: 6.3.1 ··· 24327 24328 jest-message-util@29.7.0: 24329 dependencies: 24330 + '@babel/code-frame': 7.27.1 24331 '@jest/types': 29.6.3 24332 '@types/stack-utils': 2.0.3 24333 chalk: 4.1.2 ··· 24693 transitivePeerDependencies: 24694 - supports-color 24695 24696 lightningcss-darwin-arm64@1.27.0: 24697 optional: true 24698 24699 + lightningcss-darwin-arm64@1.29.1: 24700 optional: true 24701 24702 lightningcss-darwin-x64@1.27.0: 24703 optional: true 24704 24705 + lightningcss-darwin-x64@1.29.1: 24706 optional: true 24707 24708 lightningcss-freebsd-x64@1.27.0: 24709 optional: true 24710 24711 + lightningcss-freebsd-x64@1.29.1: 24712 optional: true 24713 24714 lightningcss-linux-arm-gnueabihf@1.27.0: 24715 optional: true 24716 24717 + lightningcss-linux-arm-gnueabihf@1.29.1: 24718 optional: true 24719 24720 lightningcss-linux-arm64-gnu@1.27.0: 24721 optional: true 24722 24723 + lightningcss-linux-arm64-gnu@1.29.1: 24724 optional: true 24725 24726 lightningcss-linux-arm64-musl@1.27.0: 24727 optional: true 24728 24729 + lightningcss-linux-arm64-musl@1.29.1: 24730 optional: true 24731 24732 lightningcss-linux-x64-gnu@1.27.0: 24733 optional: true 24734 24735 + lightningcss-linux-x64-gnu@1.29.1: 24736 optional: true 24737 24738 lightningcss-linux-x64-musl@1.27.0: 24739 optional: true 24740 24741 + lightningcss-linux-x64-musl@1.29.1: 24742 optional: true 24743 24744 lightningcss-win32-arm64-msvc@1.27.0: 24745 optional: true 24746 24747 + lightningcss-win32-arm64-msvc@1.29.1: 24748 optional: true 24749 24750 lightningcss-win32-x64-msvc@1.27.0: 24751 optional: true 24752 24753 + lightningcss-win32-x64-msvc@1.29.1: 24754 optional: true 24755 24756 lightningcss@1.27.0: ··· 24768 lightningcss-win32-arm64-msvc: 1.27.0 24769 lightningcss-win32-x64-msvc: 1.27.0 24770 24771 + lightningcss@1.29.1: 24772 dependencies: 24773 + detect-libc: 1.0.3 24774 optionalDependencies: 24775 + lightningcss-darwin-arm64: 1.29.1 24776 + lightningcss-darwin-x64: 1.29.1 24777 + lightningcss-freebsd-x64: 1.29.1 24778 + lightningcss-linux-arm-gnueabihf: 1.29.1 24779 + lightningcss-linux-arm64-gnu: 1.29.1 24780 + lightningcss-linux-arm64-musl: 1.29.1 24781 + lightningcss-linux-x64-gnu: 1.29.1 24782 + lightningcss-linux-x64-musl: 1.29.1 24783 + lightningcss-win32-arm64-msvc: 1.29.1 24784 + lightningcss-win32-x64-msvc: 1.29.1 24785 optional: true 24786 24787 lilconfig@3.1.2: {} ··· 24974 lodash.clonedeep: 4.5.0 24975 lru-cache: 6.0.0 24976 24977 + lucide-react-native@0.514.0(react-native-svg@15.12.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 24978 dependencies: 24979 react: 19.0.0 24980 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 24981 + react-native-svg: 15.12.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 24982 24983 macos-alias@0.2.11: 24984 dependencies: ··· 24992 magicast@0.3.5: 24993 dependencies: 24994 '@babel/parser': 7.26.2 24995 + '@babel/types': 7.26.0 24996 source-map-js: 1.2.1 24997 24998 make-dir@2.1.0: ··· 25314 25315 metro-babel-transformer@0.82.4: 25316 dependencies: 25317 + '@babel/core': 7.26.0 25318 flow-enums-runtime: 0.0.6 25319 hermes-parser: 0.28.1 25320 nullthrows: 1.1.1 ··· 25386 metro-source-map@0.82.4: 25387 dependencies: 25388 '@babel/traverse': 7.27.3 25389 + '@babel/traverse--for-generate-function-map': '@babel/traverse@7.27.3' 25390 '@babel/types': 7.27.3 25391 flow-enums-runtime: 0.0.6 25392 invariant: 2.2.4 ··· 25411 25412 metro-transform-plugins@0.82.4: 25413 dependencies: 25414 + '@babel/core': 7.26.0 25415 + '@babel/generator': 7.27.3 25416 + '@babel/template': 7.27.2 25417 + '@babel/traverse': 7.27.3 25418 flow-enums-runtime: 0.0.6 25419 nullthrows: 1.1.1 25420 transitivePeerDependencies: ··· 25422 25423 metro-transform-worker@0.82.4(bufferutil@4.0.8)(utf-8-validate@5.0.10): 25424 dependencies: 25425 + '@babel/core': 7.26.0 25426 + '@babel/generator': 7.27.3 25427 + '@babel/parser': 7.27.3 25428 + '@babel/types': 7.27.3 25429 flow-enums-runtime: 0.0.6 25430 metro: 0.82.4(bufferutil@4.0.8)(utf-8-validate@5.0.10) 25431 metro-babel-transformer: 0.82.4 ··· 25442 25443 metro@0.82.4(bufferutil@4.0.8)(utf-8-validate@5.0.10): 25444 dependencies: 25445 + '@babel/code-frame': 7.27.1 25446 + '@babel/core': 7.26.0 25447 + '@babel/generator': 7.27.3 25448 + '@babel/parser': 7.27.3 25449 + '@babel/template': 7.27.2 25450 + '@babel/traverse': 7.27.3 25451 + '@babel/types': 7.27.3 25452 accepts: 1.3.8 25453 chalk: 4.1.2 25454 ci-info: 2.0.0 ··· 26060 26061 node-mock-http@1.0.0: {} 26062 26063 + node-releases@2.0.18: {} 26064 26065 + node-releases@2.0.19: {} 26066 26067 nodemailer-html-to-text@3.2.0: 26068 dependencies: ··· 26850 26851 possible-typed-array-names@1.0.0: {} 26852 26853 + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.3)(yaml@2.8.2): 26854 dependencies: 26855 lilconfig: 3.1.3 26856 optionalDependencies: 26857 jiti: 2.6.1 26858 postcss: 8.5.3 26859 yaml: 2.8.2 26860 26861 postcss-modules-extract-imports@3.1.0(postcss@8.5.3): ··· 26891 26892 postcss-value-parser@4.2.0: {} 26893 26894 + postcss@8.4.47: 26895 dependencies: 26896 nanoid: 3.3.11 26897 picocolors: 1.1.1 ··· 27201 dependencies: 27202 react: 19.0.0 27203 27204 + react-i18next@15.7.4(i18next@25.5.2(typescript@5.3.3))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(typescript@5.3.3): 27205 dependencies: 27206 '@babel/runtime': 7.28.4 27207 html-parse-stringify: 3.0.1 ··· 27209 react: 19.0.0 27210 optionalDependencies: 27211 react-dom: 19.0.0(react@19.0.0) 27212 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27213 typescript: 5.3.3 27214 27215 + react-i18next@15.7.4(i18next@25.5.2(typescript@5.8.3))(react-dom@19.0.0(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(typescript@5.8.3): 27216 dependencies: 27217 '@babel/runtime': 7.28.4 27218 html-parse-stringify: 3.0.1 ··· 27220 react: 19.0.0 27221 optionalDependencies: 27222 react-dom: 19.0.0(react@19.0.0) 27223 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27224 typescript: 5.8.3 27225 27226 react-is@16.13.1: {} 27227 27228 react-is@18.3.1: {} 27229 27230 + react-native-draggable-flatlist@4.0.3(@babel/core@7.26.0)(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 27231 dependencies: 27232 + '@babel/preset-typescript': 7.24.7(@babel/core@7.26.0) 27233 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27234 + react-native-gesture-handler: 2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27235 + react-native-reanimated: 3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27236 transitivePeerDependencies: 27237 - '@babel/core' 27238 - supports-color 27239 27240 + react-native-edge-to-edge@1.6.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27241 dependencies: 27242 react: 19.0.0 27243 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27244 27245 + react-native-edge-to-edge@1.6.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27246 + dependencies: 27247 + react: 19.0.0 27248 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27249 + 27250 + react-native-edge-to-edge@1.6.2(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27251 dependencies: 27252 react: 19.0.0 27253 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27254 27255 react-native-fit-image@1.5.5: 27256 dependencies: 27257 prop-types: 15.8.1 27258 27259 + react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27260 dependencies: 27261 '@egjs/hammerjs': 2.0.17 27262 hoist-non-react-statics: 3.3.2 27263 invariant: 2.2.4 27264 react: 19.0.0 27265 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27266 27267 + react-native-haptic-feedback@2.3.3(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 27268 dependencies: 27269 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27270 optional: true 27271 27272 + react-native-is-edge-to-edge@1.1.7(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27273 dependencies: 27274 react: 19.0.0 27275 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27276 27277 + react-native-localize@3.5.2(@expo/config-plugins@10.0.2)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27278 dependencies: 27279 react: 19.0.0 27280 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27281 optionalDependencies: 27282 '@expo/config-plugins': 10.0.2 27283 27284 + react-native-markdown-display@7.0.2(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27285 dependencies: 27286 css-to-react-native: 3.2.0 27287 markdown-it: 10.0.0 27288 prop-types: 15.8.1 27289 react: 19.0.0 27290 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27291 react-native-fit-image: 1.5.5 27292 27293 + react-native-quick-base64@2.1.2(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27294 + dependencies: 27295 + base64-js: 1.5.1 27296 + react: 19.0.0 27297 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27298 + 27299 + react-native-quick-base64@2.1.2(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27300 dependencies: 27301 base64-js: 1.5.1 27302 react: 19.0.0 27303 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27304 + 27305 + react-native-quick-crypto@0.7.14(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27306 + dependencies: 27307 + '@craftzdog/react-native-buffer': 6.0.5(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27308 + events: 3.3.0 27309 + readable-stream: 4.5.2 27310 + string_decoder: 1.3.0 27311 + util: 0.12.5 27312 + transitivePeerDependencies: 27313 + - react 27314 + - react-native 27315 27316 + react-native-quick-crypto@0.7.14(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27317 dependencies: 27318 + '@craftzdog/react-native-buffer': 6.0.5(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27319 events: 3.3.0 27320 readable-stream: 4.5.2 27321 string_decoder: 1.3.0 ··· 27324 - react 27325 - react-native 27326 27327 + react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27328 dependencies: 27329 + '@babel/core': 7.26.0 27330 + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.26.0) 27331 + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.26.0) 27332 + '@babel/plugin-transform-classes': 7.27.1(@babel/core@7.26.0) 27333 + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.26.0) 27334 + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.26.0) 27335 + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.26.0) 27336 + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.26.0) 27337 + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.26.0) 27338 + '@babel/preset-typescript': 7.24.7(@babel/core@7.26.0) 27339 convert-source-map: 2.0.0 27340 invariant: 2.2.4 27341 react: 19.0.0 27342 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27343 + react-native-is-edge-to-edge: 1.1.7(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27344 transitivePeerDependencies: 27345 - supports-color 27346 27347 + react-native-safe-area-context@5.4.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27348 dependencies: 27349 react: 19.0.0 27350 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27351 27352 + react-native-screens@4.11.1(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27353 dependencies: 27354 react: 19.0.0 27355 react-freeze: 1.0.4(react@19.0.0) 27356 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27357 + react-native-is-edge-to-edge: 1.1.7(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27358 warn-once: 0.1.1 27359 27360 + react-native-sortables@1.9.4(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27361 dependencies: 27362 react: 19.0.0 27363 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27364 + react-native-gesture-handler: 2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27365 + react-native-reanimated: 3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27366 optionalDependencies: 27367 + react-native-haptic-feedback: 2.3.3(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) 27368 27369 + react-native-svg@15.12.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27370 dependencies: 27371 css-select: 5.1.0 27372 css-tree: 1.1.3 27373 react: 19.0.0 27374 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27375 warn-once: 0.1.1 27376 27377 react-native-web@0.20.0(encoding@0.1.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): ··· 27389 transitivePeerDependencies: 27390 - encoding 27391 27392 + react-native-webrtc@https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 27393 dependencies: 27394 base64-js: 1.5.1 27395 debug: 4.3.4 27396 event-target-shim: 6.0.2 27397 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27398 transitivePeerDependencies: 27399 - supports-color 27400 27401 + react-native-webrtc@https://codeload.github.com/streamplace/react-native-webrtc/tar.gz/6b8472a771ac47f89217d327058a8a4124a6ae56(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)): 27402 + dependencies: 27403 + base64-js: 1.5.1 27404 + debug: 4.3.4 27405 + event-target-shim: 6.0.2 27406 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27407 + transitivePeerDependencies: 27408 + - supports-color 27409 + 27410 + react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27411 dependencies: 27412 escape-string-regexp: 4.0.0 27413 invariant: 2.2.4 27414 react: 19.0.0 27415 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27416 + 27417 + react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0): 27418 + dependencies: 27419 + escape-string-regexp: 4.0.0 27420 + invariant: 2.2.4 27421 + react: 19.0.0 27422 + react-native: 0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27423 + optional: true 27424 27425 + react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10): 27426 dependencies: 27427 '@jest/create-cache-key-function': 29.7.0 27428 '@react-native/assets-registry': 0.79.3 27429 + '@react-native/codegen': 0.79.3(@babel/core@7.26.0) 27430 '@react-native/community-cli-plugin': 0.79.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) 27431 '@react-native/gradle-plugin': 0.79.3 27432 '@react-native/js-polyfills': 0.79.3 27433 '@react-native/normalize-colors': 0.79.3 27434 + '@react-native/virtualized-lists': 0.79.3(@types/react@18.3.12)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27435 abort-controller: 3.0.0 27436 anser: 1.4.10 27437 ansi-regex: 5.0.1 27438 + babel-jest: 29.7.0(@babel/core@7.26.0) 27439 babel-plugin-syntax-hermes-parser: 0.25.1 27440 base64-js: 1.5.1 27441 chalk: 4.1.2 ··· 27462 ws: 6.2.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) 27463 yargs: 17.7.2 27464 optionalDependencies: 27465 + '@types/react': 18.3.12 27466 + transitivePeerDependencies: 27467 + - '@babel/core' 27468 + - '@react-native-community/cli' 27469 + - bufferutil 27470 + - supports-color 27471 + - utf-8-validate 27472 + 27473 + react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10): 27474 + dependencies: 27475 + '@jest/create-cache-key-function': 29.7.0 27476 + '@react-native/assets-registry': 0.79.3 27477 + '@react-native/codegen': 0.79.3(@babel/core@7.26.0) 27478 + '@react-native/community-cli-plugin': 0.79.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) 27479 + '@react-native/gradle-plugin': 0.79.3 27480 + '@react-native/js-polyfills': 0.79.3 27481 + '@react-native/normalize-colors': 0.79.3 27482 + '@react-native/virtualized-lists': 0.79.3(react-native@0.79.3(@babel/core@7.26.0)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27483 + abort-controller: 3.0.0 27484 + anser: 1.4.10 27485 + ansi-regex: 5.0.1 27486 + babel-jest: 29.7.0(@babel/core@7.26.0) 27487 + babel-plugin-syntax-hermes-parser: 0.25.1 27488 + base64-js: 1.5.1 27489 + chalk: 4.1.2 27490 + commander: 12.1.0 27491 + event-target-shim: 5.0.1 27492 + flow-enums-runtime: 0.0.6 27493 + glob: 7.2.3 27494 + invariant: 2.2.4 27495 + jest-environment-node: 29.7.0 27496 + memoize-one: 5.2.1 27497 + metro-runtime: 0.82.4 27498 + metro-source-map: 0.82.4 27499 + nullthrows: 1.1.1 27500 + pretty-format: 29.7.0 27501 + promise: 8.3.0 27502 + react: 19.0.0 27503 + react-devtools-core: 6.1.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) 27504 + react-refresh: 0.14.2 27505 + regenerator-runtime: 0.13.11 27506 + scheduler: 0.25.0 27507 + semver: 7.7.1 27508 + stacktrace-parser: 0.1.10 27509 + whatwg-fetch: 3.6.20 27510 + ws: 6.2.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) 27511 + yargs: 17.7.2 27512 transitivePeerDependencies: 27513 - '@babel/core' 27514 - '@react-native-community/cli' ··· 27518 27519 react-refresh@0.14.2: {} 27520 27521 + react-remove-scroll-bar@2.3.8(@types/react@18.3.12)(react@19.0.0): 27522 dependencies: 27523 react: 19.0.0 27524 + react-style-singleton: 2.2.3(@types/react@18.3.12)(react@19.0.0) 27525 tslib: 2.8.1 27526 optionalDependencies: 27527 + '@types/react': 18.3.12 27528 27529 + react-remove-scroll@2.7.1(@types/react@18.3.12)(react@19.0.0): 27530 dependencies: 27531 react: 19.0.0 27532 + react-remove-scroll-bar: 2.3.8(@types/react@18.3.12)(react@19.0.0) 27533 + react-style-singleton: 2.2.3(@types/react@18.3.12)(react@19.0.0) 27534 tslib: 2.8.1 27535 + use-callback-ref: 1.3.3(@types/react@18.3.12)(react@19.0.0) 27536 + use-sidecar: 1.1.3(@types/react@18.3.12)(react@19.0.0) 27537 optionalDependencies: 27538 + '@types/react': 18.3.12 27539 27540 + react-style-singleton@2.2.3(@types/react@18.3.12)(react@19.0.0): 27541 dependencies: 27542 get-nonce: 1.0.1 27543 react: 19.0.0 27544 tslib: 2.8.1 27545 optionalDependencies: 27546 + '@types/react': 18.3.12 27547 27548 react-use-websocket@4.13.0: {} 27549 ··· 27647 27648 real-require@0.2.0: {} 27649 27650 + ? reanimated-color-picker@4.0.0(expo@53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10))(react-native-gesture-handler@2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native-reanimated@3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27651 + : dependencies: 27652 react: 19.0.0 27653 + react-native: 0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) 27654 + react-native-gesture-handler: 2.26.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27655 + react-native-reanimated: 3.18.0(@babel/core@7.26.0)(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) 27656 optionalDependencies: 27657 + expo: 53.0.11(@babel/core@7.26.0)(@expo/metro-runtime@5.0.4(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(react-native-webview@13.15.0(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0))(react-native@0.79.3(@babel/core@7.26.0)(@types/react@18.3.12)(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) 27658 27659 rechoir@0.8.0: 27660 dependencies: ··· 27901 resolve-package@1.0.1: 27902 dependencies: 27903 get-installed-path: 2.1.1 27904 27905 resolve-workspace-root@2.0.0: {} 27906 ··· 28485 28486 standard-as-callback@2.1.0: {} 28487 28488 + starlight-links-validator@0.19.2(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)))(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)): 28489 dependencies: 28490 + '@astrojs/starlight': 0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)) 28491 + '@types/picomatch': 3.0.2 28492 + astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2) 28493 + github-slugger: 2.0.0 28494 + hast-util-from-html: 2.0.3 28495 + hast-util-has-property: 3.0.0 28496 + is-absolute-url: 4.0.1 28497 + kleur: 4.1.5 28498 + mdast-util-mdx-jsx: 3.2.0 28499 + mdast-util-to-string: 4.0.0 28500 + picomatch: 4.0.2 28501 + terminal-link: 5.0.0 28502 + unist-util-visit: 5.0.0 28503 + transitivePeerDependencies: 28504 + - supports-color 28505 + 28506 + starlight-openapi-rapidoc@0.8.1-beta(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)))(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2))(openapi-types@12.1.3): 28507 + dependencies: 28508 + '@astrojs/starlight': 0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)) 28509 '@astropub/md': 0.4.0 28510 '@readme/openapi-parser': 2.5.0(openapi-types@12.1.3) 28511 + astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2) 28512 github-slugger: 2.0.0 28513 transitivePeerDependencies: 28514 - '@astrojs/markdown-remark' 28515 - openapi-types 28516 28517 + starlight-openapi@0.17.0(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)))(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2))(openapi-types@12.1.3): 28518 dependencies: 28519 + '@astrojs/starlight': 0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)) 28520 '@readme/openapi-parser': 2.7.0(openapi-types@12.1.3) 28521 + astro: 5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2) 28522 github-slugger: 2.0.0 28523 url-template: 3.1.1 28524 transitivePeerDependencies: 28525 - openapi-types 28526 + 28527 + starlight-sidebar-swipe@0.1.1(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2))): 28528 + dependencies: 28529 + '@astrojs/starlight': 0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)) 28530 + 28531 + starlight-sidebar-topics@0.6.2(@astrojs/starlight@0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2))): 28532 + dependencies: 28533 + '@astrojs/starlight': 0.34.2(astro@5.7.10(@types/node@22.15.17)(encoding@0.1.13)(idb-keyval@6.2.1)(ioredis@5.7.0)(jiti@2.6.1)(lightningcss@1.29.1)(rollup@4.40.1)(terser@5.32.0)(typescript@5.8.3)(yaml@2.8.2)) 28534 + picomatch: 4.0.2 28535 28536 statuses@1.5.0: {} 28537 ··· 28728 28729 sucrase@3.35.0: 28730 dependencies: 28731 + '@jridgewell/gen-mapping': 0.3.5 28732 commander: 4.1.1 28733 glob: 10.4.5 28734 lines-and-columns: 1.2.4 ··· 28746 transitivePeerDependencies: 28747 - supports-color 28748 28749 + supports-color@10.2.2: {} 28750 + 28751 supports-color@5.5.0: 28752 dependencies: 28753 has-flag: 3.0.0 ··· 28764 dependencies: 28765 has-flag: 4.0.0 28766 supports-color: 7.2.0 28767 + 28768 + supports-hyperlinks@4.4.0: 28769 + dependencies: 28770 + has-flag: 5.0.1 28771 + supports-color: 10.2.2 28772 28773 supports-preserve-symlinks-flag@1.0.0: {} 28774 ··· 28865 ansi-escapes: 4.3.2 28866 supports-hyperlinks: 2.3.0 28867 28868 + terminal-link@5.0.0: 28869 + dependencies: 28870 + ansi-escapes: 7.0.0 28871 + supports-hyperlinks: 4.4.0 28872 + 28873 terser-webpack-plugin@5.3.10(@swc/core@1.15.4(@swc/helpers@0.5.17))(webpack@5.94.0(@swc/core@1.15.4(@swc/helpers@0.5.17))): 28874 dependencies: 28875 '@jridgewell/trace-mapping': 0.3.25 ··· 29079 29080 tslib@2.8.1: {} 29081 29082 + tsup@8.5.0(@swc/core@1.15.4(@swc/helpers@0.5.17))(jiti@2.6.1)(postcss@8.5.3)(typescript@5.8.3)(yaml@2.8.2): 29083 dependencies: 29084 bundle-require: 5.1.0(esbuild@0.25.3) 29085 cac: 6.7.14 ··· 29090 fix-dts-default-cjs-exports: 1.0.1 29091 joycon: 3.1.1 29092 picocolors: 1.1.1 29093 + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.3)(yaml@2.8.2) 29094 resolve-from: 5.0.0 29095 rollup: 4.40.1 29096 source-map: 0.8.0-beta.0 ··· 29108 - tsx 29109 - yaml 29110 29111 tuf-js@2.2.1: 29112 dependencies: 29113 '@tufjs/models': 2.0.1 ··· 29381 29382 upath@2.0.1: {} 29383 29384 + update-browserslist-db@1.1.1(browserslist@4.24.2): 29385 dependencies: 29386 + browserslist: 4.24.2 29387 escalade: 3.2.0 29388 picocolors: 1.1.1 29389 29390 + update-browserslist-db@1.1.3(browserslist@4.24.5): 29391 dependencies: 29392 + browserslist: 4.24.5 29393 escalade: 3.2.0 29394 picocolors: 1.1.1 29395 ··· 29407 29408 url-template@3.1.1: {} 29409 29410 + use-callback-ref@1.3.3(@types/react@18.3.12)(react@19.0.0): 29411 dependencies: 29412 react: 19.0.0 29413 tslib: 2.8.1 29414 optionalDependencies: 29415 + '@types/react': 18.3.12 29416 29417 use-latest-callback@0.2.1(react@19.0.0): 29418 dependencies: 29419 react: 19.0.0 29420 29421 + use-sidecar@1.1.3(@types/react@18.3.12)(react@19.0.0): 29422 dependencies: 29423 detect-node-es: 1.1.0 29424 react: 19.0.0 29425 tslib: 2.8.1 29426 optionalDependencies: 29427 + '@types/react': 18.3.12 29428 29429 + use-sync-external-store@1.2.2(react@19.0.0): 29430 dependencies: 29431 react: 19.0.0 29432 optional: true ··· 29587 replace-ext: 2.0.0 29588 teex: 1.0.1 29589 29590 + vite@6.3.4(@types/node@22.15.17)(jiti@2.6.1)(lightningcss@1.29.1)(terser@5.32.0)(yaml@2.8.2): 29591 dependencies: 29592 esbuild: 0.25.3 29593 fdir: 6.4.4(picomatch@4.0.2) ··· 29599 '@types/node': 22.15.17 29600 fsevents: 2.3.3 29601 jiti: 2.6.1 29602 + lightningcss: 1.29.1 29603 terser: 5.32.0 29604 yaml: 2.8.2 29605 29606 + vitefu@1.0.6(vite@6.3.4(@types/node@22.15.17)(jiti@2.6.1)(lightningcss@1.29.1)(terser@5.32.0)(yaml@2.8.2)): 29607 optionalDependencies: 29608 + vite: 6.3.4(@types/node@22.15.17)(jiti@2.6.1)(lightningcss@1.29.1)(terser@5.32.0)(yaml@2.8.2) 29609 29610 vlq@1.0.1: {} 29611 ··· 29721 '@webassemblyjs/wasm-parser': 1.12.1 29722 acorn: 8.14.1 29723 acorn-import-attributes: 1.9.5(acorn@8.14.1) 29724 + browserslist: 4.24.2 29725 chrome-trace-event: 1.0.4 29726 enhanced-resolve: 5.17.1 29727 es-module-lexer: 1.7.0 ··· 30032 30033 zod@3.24.4: {} 30034 30035 + zustand@5.0.5(@types/react@18.3.12)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.2.2(react@19.0.0)): 30036 optionalDependencies: 30037 + '@types/react': 18.3.12 30038 immer: 10.1.1 30039 react: 19.0.0 30040 + use-sync-external-store: 1.2.2(react@19.0.0) 30041 30042 zwitch@2.0.4: {}
-5
rust/sp-analytics/.gitignore
··· 1 - /target 2 - /data 3 - *.wal 4 - config.local.toml 5 - *.env
···
-39
rust/sp-analytics/Cargo.toml
··· 1 - [package] 2 - name = "sp-analytics" 3 - version = "0.1.0" 4 - edition = "2024" 5 - 6 - [dependencies] 7 - tokio = { version = "1", features = ["full"] } 8 - tonic = "0.12" 9 - prost = "0.13" 10 - prost-types = "0.13" 11 - clickhouse = { version = "0.13", features = ["chrono", "uuid"] } 12 - redb = "2" 13 - serde = { version = "1", features = ["derive"] } 14 - serde_json = "1" 15 - tracing = "0.1" 16 - tracing-subscriber = { version = "0.3", features = ["env-filter"] } 17 - metrics = "0.24" 18 - metrics-exporter-prometheus = "0.16" 19 - figment = { version = "0.10", features = ["env", "toml"] } 20 - uuid = { version = "1", features = ["v4", "serde"] } 21 - chrono = { version = "0.4", features = ["serde"] } 22 - anyhow = "1" 23 - thiserror = "2" 24 - dotenvy = "0.15.7" 25 - 26 - [build-dependencies] 27 - tonic-build = "0.12" 28 - 29 - [dev-dependencies] 30 - testcontainers = "0.23" 31 - tempfile = "3" 32 - 33 - [[bin]] 34 - name = "sp-analytics" 35 - path = "src/main.rs" 36 - 37 - [lib] 38 - name = "sp_analytics" 39 - path = "src/lib.rs"
···
-36
rust/sp-analytics/Dockerfile
··· 1 - FROM rust:1-slim-trixie as builder 2 - 3 - WORKDIR /app 4 - 5 - RUN apt-get update && apt-get install -y \ 6 - ca-certificates protobuf-compiler \ 7 - && rm -rf /var/lib/apt/lists/* 8 - 9 - # copy workspace manifest 10 - COPY Cargo.toml Cargo.lock ./ 11 - 12 - # copy all workspace members (needed for workspace resolution) 13 - COPY rust/export-c2pa-schema rust/export-c2pa-schema 14 - COPY rust/iroh-streamplace rust/iroh-streamplace 15 - COPY rust/sp-analytics rust/sp-analytics 16 - 17 - # build only sp-analytics 18 - RUN cargo build --release -p sp-analytics 19 - 20 - FROM debian:trixie-slim 21 - 22 - RUN apt-get update && apt-get install -y \ 23 - ca-certificates \ 24 - && rm -rf /var/lib/apt/lists/* 25 - 26 - WORKDIR /app 27 - 28 - COPY --from=builder /app/target/release/sp-analytics /usr/local/bin/sp-analytics 29 - 30 - RUN mkdir -p /app/data 31 - 32 - ENV SP_ANALYTICS_WAL__PATH=/app/data/analytics.wal 33 - 34 - EXPOSE 9090 9091 35 - 36 - CMD ["sp-analytics"]
···
-68
rust/sp-analytics/README.md
··· 1 - # sp-analytics 2 - 3 - ## Quick start 4 - 5 - ### Using docker compose 6 - 7 - ```bash 8 - cd rust/sp-analytics 9 - docker-compose up 10 - ``` 11 - 12 - This starts both ClickHouse and builds and serves the analytics service. 13 - 14 - ### Local development 15 - 16 - 1. Start ClickHouse: 17 - 18 - ```bash 19 - # in this folder 20 - docker compose up -d clickhouse 21 - ``` 22 - 23 - 2. Run the service: 24 - 25 - ```bash 26 - cargo run 27 - ``` 28 - 29 - ## Configuration 30 - 31 - Configuration via `config.toml` or environment variables prefixed with 32 - `SP_ANALYTICS_`. For example: 33 - 34 - ```bash 35 - SP_ANALYTICS_CLICKHOUSE_URL=http://localhost:8123 36 - SP_ANALYTICS_CLICKHOUSE_DATABASE=sp_analytics 37 - SP_ANALYTICS_CLICKHOUSE_USERNAME=default 38 - SP_ANALYTICS_CLICKHOUSE_PASSWORD=yourpassword 39 - SP_ANALYTICS_SERVER__GRPC_PORT=9090 40 - SP_ANALYTICS_WAL__PATH=./analytics.wal 41 - SP_ANALYTICS_WAL__ENABLED=true 42 - 43 - ``` 44 - 45 - ## Adding new tables 46 - 47 - Use `ch2rs` to get close-enough results for the tables you want. It connects to 48 - your local clickhouse database. for example: 49 - 50 - ```bash 51 - ch2rs events -u default -d sp_analytics -S \ 52 - --derive Clone \ 53 - --derive Serialize \ 54 - --derive Deserialize \ 55 - -T 'UUID=uuid::Uuid' \ 56 - -T 'DateTime64(3)=chrono::DateTime<chrono::Utc>' \ 57 - -O 'properties=String' \ 58 - -O 'blob=Vec<u8>' \ 59 - -B 'blob' \ 60 - -I 'ignored' 61 - ``` 62 - 63 - ## Testing 64 - 65 - ```bash 66 - # in this folder 67 - cargo test 68 - ```
···
-4
rust/sp-analytics/build.rs
··· 1 - fn main() -> Result<(), Box<dyn std::error::Error>> { 2 - tonic_build::compile_protos("proto/analytics.proto")?; 3 - Ok(()) 4 - }
···
-18
rust/sp-analytics/config.toml
··· 1 - [server] 2 - grpc_port = 9090 3 - 4 - [clickhouse] 5 - url = "http://localhost:8123" 6 - database = "sp_analytics" 7 - username = "" 8 - password = "" 9 - 10 - [wal] 11 - path = "./data/analytics.wal" 12 - enabled = true 13 - 14 - [ingestion] 15 - batch_size = 1000 16 - flush_interval_ms = 5000 17 - max_retry_attempts = 10 18 - retry_backoff_base_ms = 1000
···
-43
rust/sp-analytics/docker-compose.yml
··· 1 - version: "3.8" 2 - 3 - services: 4 - clickhouse: 5 - image: clickhouse/clickhouse-server:latest 6 - ports: 7 - - "8123:8123" 8 - - "9000:9000" 9 - volumes: 10 - - clickhouse-data:/var/lib/clickhouse 11 - environment: 12 - CLICKHOUSE_DB: sp_analytics 13 - CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1 14 - CLICKHOUSE_PASSWORD: yourpassword 15 - healthcheck: 16 - test: ["CMD", "clickhouse-client", "--query", "SELECT 1"] 17 - interval: 10s 18 - timeout: 5s 19 - retries: 5 20 - 21 - analytics: 22 - build: 23 - context: ../.. 24 - dockerfile: rust/sp-analytics/Dockerfile 25 - ports: 26 - - "9090:9090" 27 - - "9091:9091" 28 - depends_on: 29 - clickhouse: 30 - condition: service_healthy 31 - environment: 32 - SP_ANALYTICS_CLICKHOUSE__URL: http://clickhouse:8123 33 - SP_ANALYTICS_CLICKHOUSE__DATABASE: sp_analytics 34 - SP_ANALYTICS_SERVER__GRPC_PORT: 9090 35 - SP_ANALYTICS_WAL__PATH: /app/data/analytics.wal 36 - SP_ANALYTICS_WAL__ENABLED: "true" 37 - RUST_LOG: sp_analytics=info 38 - volumes: 39 - - analytics-data:/app/data 40 - 41 - volumes: 42 - clickhouse-data: 43 - analytics-data:
···
-82
rust/sp-analytics/migrations/001_initial.sql
··· 1 - -- Streamers dimension table 2 - CREATE TABLE IF NOT EXISTS streamers ( 3 - streamer_did String, 4 - username String, 5 - display_name String, 6 - created_at DateTime64(3), 7 - updated_at DateTime64(3), 8 - 9 - -- aggregates 10 - total_streams UInt32 DEFAULT 0, 11 - total_events UInt64 DEFAULT 0, 12 - follower_count UInt32 DEFAULT 0 13 - ) 14 - ENGINE = ReplacingMergeTree(updated_at) 15 - ORDER BY streamer_did; 16 - 17 - -- Follows table 18 - CREATE TABLE IF NOT EXISTS follows ( 19 - follower_did String, 20 - streamer_did String, 21 - followed_at DateTime64(3), 22 - unfollowed_at Nullable(DateTime64(3)), 23 - status LowCardinality(String), -- active, unfollowed 24 - updated_at DateTime64(3) 25 - ) 26 - ENGINE = ReplacingMergeTree(updated_at) 27 - ORDER BY (follower_did, streamer_did); 28 - 29 - -- Streams dimension table 30 - CREATE TABLE IF NOT EXISTS streams ( 31 - stream_id String, 32 - streamer_did String, 33 - title String, 34 - started_at DateTime64(3), 35 - ended_at Nullable(DateTime64(3)), 36 - status LowCardinality(String), -- live, ended, error 37 - 38 - -- metadata 39 - created_at DateTime64(3), 40 - updated_at DateTime64(3), 41 - 42 - -- aggregates 43 - total_viewers UInt32 DEFAULT 0, 44 - peak_viewers UInt32 DEFAULT 0, 45 - total_events UInt64 DEFAULT 0 46 - ) 47 - ENGINE = ReplacingMergeTree(updated_at) 48 - ORDER BY stream_id; 49 - 50 - -- Events table 51 - CREATE TABLE IF NOT EXISTS events ( 52 - event_id UUID, 53 - event_type LowCardinality(String), 54 - device_id String, 55 - did Nullable(String), 56 - session_id String, 57 - 58 - timestamp DateTime64(3), 59 - 60 - streamer_did String, 61 - stream_id Nullable(String), 62 - 63 - properties String, 64 - schema_version UInt16, 65 - 66 - client_version String, 67 - platform LowCardinality(String) 68 - ) 69 - ENGINE = MergeTree() 70 - PARTITION BY toYYYYMM(timestamp) 71 - ORDER BY (streamer_did, timestamp, device_id); 72 - 73 - -- Deletion requests audit table 74 - CREATE TABLE IF NOT EXISTS deletion_requests ( 75 - request_id UUID, 76 - did String, 77 - requested_at DateTime64(3), 78 - completed_at Nullable(DateTime64(3)), 79 - status LowCardinality(String) 80 - ) 81 - ENGINE = MergeTree() 82 - ORDER BY requested_at;
···
-116
rust/sp-analytics/proto/analytics.proto
··· 1 - syntax = "proto3"; 2 - 3 - package analytics; 4 - 5 - option go_package = "streamplace/pkg/analytics/pb;pb"; 6 - 7 - service Analytics { 8 - rpc IngestEvents(IngestEventsRequest) returns (IngestEventsResponse); 9 - rpc GetStreamerStats(StreamerStatsRequest) returns (StreamerStatsResponse); 10 - rpc GetViewerHistory(ViewerHistoryRequest) returns (ViewerHistoryResponse); 11 - rpc GetRealtimeStats(RealtimeStatsRequest) returns (RealtimeStatsResponse); 12 - rpc DeleteUserData(DeleteUserDataRequest) returns (DeleteUserDataResponse); 13 - rpc GetDeletionStatus(GetDeletionStatusRequest) returns (DeletionStatusResponse); 14 - } 15 - 16 - message IngestEventsRequest { 17 - repeated Event events = 1; 18 - } 19 - 20 - message IngestEventsResponse { 21 - uint32 accepted = 1; 22 - uint32 rejected = 2; 23 - repeated string errors = 3; 24 - } 25 - 26 - message Event { 27 - string event_id = 1; 28 - string event_type = 2; 29 - string device_id = 3; 30 - optional string did = 4; 31 - string session_id = 5; 32 - int64 timestamp_ms = 6; 33 - string streamer_did = 7; 34 - optional string stream_id = 8; 35 - string properties_json = 9; 36 - uint32 schema_version = 10; 37 - string client_version = 11; 38 - string platform = 12; 39 - } 40 - 41 - message StreamerStatsRequest { 42 - string streamer_did = 1; 43 - optional int64 start_time_ms = 2; 44 - optional int64 end_time_ms = 3; 45 - } 46 - 47 - message StreamerStatsResponse { 48 - string streamer_did = 1; 49 - uint64 total_views = 2; 50 - uint64 total_watch_time_ms = 3; 51 - uint64 unique_viewers = 4; 52 - repeated DailyStats daily_stats = 5; 53 - } 54 - 55 - message DailyStats { 56 - string date = 1; 57 - uint64 views = 2; 58 - uint64 watch_time_ms = 3; 59 - uint64 unique_viewers = 4; 60 - } 61 - 62 - message ViewerHistoryRequest { 63 - string did = 1; 64 - optional int64 start_time_ms = 2; 65 - optional int64 end_time_ms = 3; 66 - uint32 limit = 4; 67 - } 68 - 69 - message ViewerHistoryResponse { 70 - repeated WatchSession sessions = 1; 71 - } 72 - 73 - message WatchSession { 74 - string session_id = 1; 75 - string streamer_did = 2; 76 - optional string stream_id = 3; 77 - int64 start_time_ms = 4; 78 - int64 end_time_ms = 5; 79 - uint64 duration_ms = 6; 80 - } 81 - 82 - message RealtimeStatsRequest { 83 - optional string streamer_did = 1; 84 - uint32 window_minutes = 2; 85 - } 86 - 87 - message RealtimeStatsResponse { 88 - repeated StreamerRealtimeStats streamers = 1; 89 - } 90 - 91 - message StreamerRealtimeStats { 92 - string streamer_did = 1; 93 - uint64 current_viewers = 2; 94 - uint64 total_watch_time_ms = 3; 95 - } 96 - 97 - message DeleteUserDataRequest { 98 - string did = 1; 99 - } 100 - 101 - message DeleteUserDataResponse { 102 - string request_id = 1; 103 - string status = 2; 104 - } 105 - 106 - message GetDeletionStatusRequest { 107 - string request_id = 1; 108 - } 109 - 110 - message DeletionStatusResponse { 111 - string request_id = 1; 112 - string did = 2; 113 - string status = 3; 114 - optional int64 requested_at_ms = 4; 115 - optional int64 completed_at_ms = 5; 116 - }
···
-254
rust/sp-analytics/src/api/grpc.rs
··· 1 - use crate::db::clickhouse::{ClickHouseClient, EventRow}; 2 - use crate::ingest::{EventBuffer, validate_event}; 3 - use crate::proto::analytics_server::Analytics; 4 - use crate::proto::*; 5 - use crate::query::{get_realtime_stats, get_streamer_stats, get_viewer_history}; 6 - use chrono::{DateTime, TimeZone, Utc}; 7 - use std::str::FromStr; 8 - use std::sync::Arc; 9 - use tonic::{Request, Response, Status}; 10 - use tracing::{error, warn}; 11 - use uuid::Uuid; 12 - 13 - pub struct AnalyticsService { 14 - clickhouse: ClickHouseClient, 15 - buffer: Arc<EventBuffer>, 16 - } 17 - 18 - impl AnalyticsService { 19 - pub fn new(clickhouse: ClickHouseClient, buffer: Arc<EventBuffer>) -> Self { 20 - Self { clickhouse, buffer } 21 - } 22 - } 23 - 24 - #[tonic::async_trait] 25 - impl Analytics for AnalyticsService { 26 - async fn ingest_events( 27 - &self, 28 - request: Request<IngestEventsRequest>, 29 - ) -> Result<Response<IngestEventsResponse>, Status> { 30 - let req = request.into_inner(); 31 - let mut accepted = 0u32; 32 - let mut rejected = 0u32; 33 - let mut errors = Vec::new(); 34 - 35 - let mut valid_events = Vec::new(); 36 - 37 - for event in req.events { 38 - match validate_event(&event) { 39 - Ok(_) => match convert_to_event_row(&event) { 40 - Ok(row) => { 41 - valid_events.push(row); 42 - accepted += 1; 43 - } 44 - Err(e) => { 45 - rejected += 1; 46 - errors.push(format!( 47 - "conversion error for event {}: {}", 48 - event.event_id, e 49 - )); 50 - } 51 - }, 52 - Err(e) => { 53 - rejected += 1; 54 - errors.push(format!( 55 - "validation error for event {}: {}", 56 - event.event_id, e 57 - )); 58 - } 59 - } 60 - } 61 - 62 - if !valid_events.is_empty() { 63 - if let Err(e) = self.buffer.add_events(valid_events).await { 64 - error!("failed to buffer events: {}", e); 65 - return Err(Status::internal("failed to buffer events")); 66 - } 67 - } 68 - 69 - Ok(Response::new(IngestEventsResponse { 70 - accepted, 71 - rejected, 72 - errors, 73 - })) 74 - } 75 - 76 - async fn get_streamer_stats( 77 - &self, 78 - request: Request<StreamerStatsRequest>, 79 - ) -> Result<Response<StreamerStatsResponse>, Status> { 80 - let req = request.into_inner(); 81 - 82 - let (total_views, total_watch_time_ms, unique_viewers, daily_stats) = get_streamer_stats( 83 - self.clickhouse.client(), 84 - &req.streamer_did, 85 - req.start_time_ms, 86 - req.end_time_ms, 87 - ) 88 - .await 89 - .map_err(|e| { 90 - error!("failed to get streamer stats: {}", e); 91 - Status::internal("query failed") 92 - })?; 93 - 94 - let daily_stats_proto: Vec<DailyStats> = daily_stats 95 - .into_iter() 96 - .map(|s| DailyStats { 97 - date: s.date, 98 - views: s.views, 99 - watch_time_ms: s.watch_time_ms, 100 - unique_viewers: s.unique_viewers, 101 - }) 102 - .collect(); 103 - 104 - Ok(Response::new(StreamerStatsResponse { 105 - streamer_did: req.streamer_did, 106 - total_views, 107 - total_watch_time_ms, 108 - unique_viewers, 109 - daily_stats: daily_stats_proto, 110 - })) 111 - } 112 - 113 - async fn get_viewer_history( 114 - &self, 115 - request: Request<ViewerHistoryRequest>, 116 - ) -> Result<Response<ViewerHistoryResponse>, Status> { 117 - let req = request.into_inner(); 118 - 119 - let sessions = get_viewer_history( 120 - self.clickhouse.client(), 121 - &req.did, 122 - req.start_time_ms, 123 - req.end_time_ms, 124 - req.limit, 125 - ) 126 - .await 127 - .map_err(|e| { 128 - error!("failed to get viewer history: {}", e); 129 - Status::internal("query failed") 130 - })?; 131 - 132 - let sessions_proto: Vec<WatchSession> = sessions 133 - .into_iter() 134 - .map(|s| WatchSession { 135 - session_id: s.session_id, 136 - streamer_did: s.streamer_did, 137 - stream_id: s.stream_id, 138 - start_time_ms: s.start_time_ms, 139 - end_time_ms: s.end_time_ms, 140 - duration_ms: s.duration_ms, 141 - }) 142 - .collect(); 143 - 144 - Ok(Response::new(ViewerHistoryResponse { 145 - sessions: sessions_proto, 146 - })) 147 - } 148 - 149 - async fn get_realtime_stats( 150 - &self, 151 - request: Request<RealtimeStatsRequest>, 152 - ) -> Result<Response<RealtimeStatsResponse>, Status> { 153 - let req = request.into_inner(); 154 - 155 - let stats = get_realtime_stats( 156 - self.clickhouse.client(), 157 - req.streamer_did.as_deref(), 158 - req.window_minutes, 159 - ) 160 - .await 161 - .map_err(|e| { 162 - error!("failed to get realtime stats: {}", e); 163 - Status::internal("query failed") 164 - })?; 165 - 166 - let streamers: Vec<StreamerRealtimeStats> = stats 167 - .into_iter() 168 - .map(|s| StreamerRealtimeStats { 169 - streamer_did: s.streamer_did, 170 - current_viewers: s.current_viewers, 171 - total_watch_time_ms: s.total_watch_time_ms, 172 - }) 173 - .collect(); 174 - 175 - Ok(Response::new(RealtimeStatsResponse { streamers })) 176 - } 177 - 178 - async fn delete_user_data( 179 - &self, 180 - request: Request<DeleteUserDataRequest>, 181 - ) -> Result<Response<DeleteUserDataResponse>, Status> { 182 - let req = request.into_inner(); 183 - 184 - let request_id = crate::privacy::delete_user_data(&self.clickhouse, req.did) 185 - .await 186 - .map_err(|e| { 187 - error!("failed to create deletion request: {}", e); 188 - Status::internal("deletion request failed") 189 - })?; 190 - 191 - Ok(Response::new(DeleteUserDataResponse { 192 - request_id: request_id.to_string(), 193 - status: "pending".to_string(), 194 - })) 195 - } 196 - 197 - async fn get_deletion_status( 198 - &self, 199 - request: Request<GetDeletionStatusRequest>, 200 - ) -> Result<Response<DeletionStatusResponse>, Status> { 201 - let req = request.into_inner(); 202 - 203 - let request_id = Uuid::from_str(&req.request_id).map_err(|e| { 204 - warn!("invalid request_id: {}", e); 205 - Status::invalid_argument("invalid request_id") 206 - })?; 207 - 208 - let status = crate::privacy::get_deletion_status(&self.clickhouse, request_id) 209 - .await 210 - .map_err(|e| { 211 - error!("failed to get deletion status: {}", e); 212 - Status::internal("query failed") 213 - })?; 214 - 215 - match status { 216 - Some(s) => Ok(Response::new(DeletionStatusResponse { 217 - request_id: s.request_id.to_string(), 218 - did: s.did, 219 - status: s.status, 220 - requested_at_ms: Some(s.requested_at.timestamp_millis()), 221 - completed_at_ms: s.completed_at.map(|dt| dt.timestamp_millis()), 222 - })), 223 - None => Err(Status::not_found("deletion request not found")), 224 - } 225 - } 226 - } 227 - 228 - fn convert_to_event_row(event: &Event) -> Result<EventRow, String> { 229 - let event_id = 230 - Uuid::from_str(&event.event_id).map_err(|e| format!("invalid event_id: {}", e))?; 231 - 232 - let timestamp_secs = event.timestamp_ms / 1000; 233 - let timestamp_nanos = ((event.timestamp_ms % 1000) * 1_000_000) as u32; 234 - 235 - let timestamp: DateTime<Utc> = Utc 236 - .timestamp_opt(timestamp_secs, timestamp_nanos) 237 - .single() 238 - .ok_or_else(|| "invalid timestamp".to_string())?; 239 - 240 - Ok(EventRow { 241 - event_id, 242 - event_type: event.event_type.clone(), 243 - device_id: event.device_id.clone(), 244 - did: event.did.clone(), 245 - session_id: event.session_id.clone(), 246 - timestamp, 247 - streamer_did: event.streamer_did.clone(), 248 - stream_id: event.stream_id.clone(), 249 - properties: event.properties_json.clone(), 250 - schema_version: event.schema_version as u16, 251 - client_version: event.client_version.clone(), 252 - platform: event.platform.clone(), 253 - }) 254 - }
···
-3
rust/sp-analytics/src/api/mod.rs
··· 1 - pub mod grpc; 2 - 3 - pub use grpc::*;
···
-132
rust/sp-analytics/src/config.rs
··· 1 - use figment::{ 2 - Figment, 3 - providers::{Env, Format, Toml}, 4 - }; 5 - use serde::{Deserialize, Serialize}; 6 - 7 - #[derive(Debug, Clone, Deserialize, Serialize)] 8 - pub struct Config { 9 - pub server: ServerConfig, 10 - pub clickhouse: ClickHouseConfig, 11 - pub wal: WalConfig, 12 - pub ingestion: IngestionConfig, 13 - } 14 - 15 - #[derive(Debug, Clone, Deserialize, Serialize)] 16 - pub struct ServerConfig { 17 - #[serde(default = "default_grpc_port")] 18 - pub grpc_port: u16, 19 - } 20 - 21 - #[derive(Debug, Clone, Deserialize, Serialize)] 22 - pub struct ClickHouseConfig { 23 - #[serde(default = "default_clickhouse_url")] 24 - pub url: String, 25 - #[serde(default = "default_database")] 26 - pub database: String, 27 - #[serde(default)] 28 - pub username: String, 29 - #[serde(default)] 30 - pub password: String, 31 - } 32 - 33 - #[derive(Debug, Clone, Deserialize, Serialize)] 34 - pub struct WalConfig { 35 - #[serde(default = "default_wal_path")] 36 - pub path: String, 37 - #[serde(default = "default_wal_enabled")] 38 - pub enabled: bool, 39 - } 40 - 41 - #[derive(Debug, Clone, Deserialize, Serialize)] 42 - pub struct IngestionConfig { 43 - #[serde(default = "default_batch_size")] 44 - pub batch_size: usize, 45 - #[serde(default = "default_flush_interval_ms")] 46 - pub flush_interval_ms: u64, 47 - #[serde(default = "default_max_retry_attempts")] 48 - pub max_retry_attempts: u32, 49 - #[serde(default = "default_retry_backoff_base_ms")] 50 - pub retry_backoff_base_ms: u64, 51 - } 52 - 53 - fn default_grpc_port() -> u16 { 54 - 9090 55 - } 56 - 57 - fn default_clickhouse_url() -> String { 58 - "http://localhost:8123".to_string() 59 - } 60 - 61 - fn default_database() -> String { 62 - "sp_analytics".to_string() 63 - } 64 - 65 - fn default_wal_path() -> String { 66 - "./data/analytics.wal".to_string() 67 - } 68 - 69 - fn default_wal_enabled() -> bool { 70 - true 71 - } 72 - 73 - fn default_batch_size() -> usize { 74 - 1000 75 - } 76 - 77 - fn default_flush_interval_ms() -> u64 { 78 - 5000 79 - } 80 - 81 - fn default_max_retry_attempts() -> u32 { 82 - 10 83 - } 84 - 85 - fn default_retry_backoff_base_ms() -> u64 { 86 - 1000 87 - } 88 - 89 - impl Config { 90 - pub fn load() -> Result<Self, figment::Error> { 91 - let figment = Figment::new() 92 - .merge(Toml::file("config.toml")) 93 - .merge(Env::prefixed("SP_ANALYTICS_").split("__")); 94 - 95 - tracing::debug!("figment profile: {:?}", figment.profile()); 96 - 97 - let config: Config = figment.extract()?; 98 - 99 - tracing::debug!( 100 - "loaded config: clickhouse.username = '{}'", 101 - config.clickhouse.username 102 - ); 103 - 104 - Ok(config) 105 - } 106 - } 107 - 108 - impl Default for Config { 109 - fn default() -> Self { 110 - Self { 111 - server: ServerConfig { 112 - grpc_port: default_grpc_port(), 113 - }, 114 - clickhouse: ClickHouseConfig { 115 - url: default_clickhouse_url(), 116 - database: default_database(), 117 - username: String::new(), 118 - password: String::new(), 119 - }, 120 - wal: WalConfig { 121 - path: default_wal_path(), 122 - enabled: default_wal_enabled(), 123 - }, 124 - ingestion: IngestionConfig { 125 - batch_size: default_batch_size(), 126 - flush_interval_ms: default_flush_interval_ms(), 127 - max_retry_attempts: default_max_retry_attempts(), 128 - retry_backoff_base_ms: default_retry_backoff_base_ms(), 129 - }, 130 - } 131 - } 132 - }
···
-122
rust/sp-analytics/src/db/clickhouse.rs
··· 1 - use crate::config::ClickHouseConfig; 2 - use anyhow::Result; 3 - use chrono::{DateTime, Utc}; 4 - use clickhouse::{Client, Row}; 5 - use serde::{Deserialize, Serialize}; 6 - use uuid::Uuid; 7 - 8 - #[derive(Clone)] 9 - pub struct ClickHouseClient { 10 - client: Client, 11 - } 12 - 13 - #[derive(Debug, Clone, Serialize, Deserialize, Row)] 14 - pub struct EventRow { 15 - #[serde(with = "clickhouse::serde::uuid")] 16 - pub event_id: Uuid, 17 - pub event_type: String, 18 - pub device_id: String, 19 - pub did: Option<String>, 20 - pub session_id: String, 21 - #[serde(with = "clickhouse::serde::chrono::datetime64::millis")] 22 - pub timestamp: DateTime<Utc>, 23 - pub streamer_did: String, 24 - pub stream_id: Option<String>, 25 - pub properties: String, 26 - pub schema_version: u16, 27 - pub client_version: String, 28 - pub platform: String, 29 - } 30 - 31 - #[derive(Debug, Clone, Serialize, Deserialize, Row)] 32 - pub struct DeletionRequest { 33 - pub request_id: Uuid, 34 - pub did: String, 35 - pub requested_at: DateTime<Utc>, 36 - pub completed_at: Option<DateTime<Utc>>, 37 - pub status: String, 38 - } 39 - 40 - impl ClickHouseClient { 41 - pub fn new(config: &ClickHouseConfig) -> Result<Self> { 42 - tracing::debug!( 43 - "creating clickhouse client: url={}, db={}, username='{}', password_len={}", 44 - config.url, 45 - config.database, 46 - config.username, 47 - config.password.len() 48 - ); 49 - 50 - let client = Client::default() 51 - .with_url(&config.url) 52 - .with_database(&config.database); 53 - 54 - let client = if !config.username.is_empty() { 55 - tracing::debug!("setting username and password"); 56 - client 57 - .with_user(&config.username) 58 - .with_password(&config.password) 59 - } else { 60 - tracing::debug!("no username set, using default auth"); 61 - client 62 - }; 63 - 64 - Ok(Self { client }) 65 - } 66 - 67 - pub fn client(&self) -> &Client { 68 - &self.client 69 - } 70 - 71 - pub async fn insert_events(&self, events: Vec<EventRow>) -> Result<()> { 72 - if events.is_empty() { 73 - return Ok(()); 74 - } 75 - 76 - let mut insert = self.client.insert("events")?; 77 - for event in events { 78 - insert.write(&event).await?; 79 - } 80 - insert.end().await?; 81 - 82 - Ok(()) 83 - } 84 - 85 - pub async fn create_deletion_request(&self, did: String) -> Result<Uuid> { 86 - let request_id = Uuid::new_v4(); 87 - let request = DeletionRequest { 88 - request_id, 89 - did: did.clone(), 90 - requested_at: Utc::now(), 91 - completed_at: None, 92 - status: "pending".to_string(), 93 - }; 94 - 95 - let mut insert = self.client.insert("deletion_requests")?; 96 - insert.write(&request).await?; 97 - insert.end().await?; 98 - 99 - self.client 100 - .query("ALTER TABLE events DELETE WHERE did = ?") 101 - .bind(&did) 102 - .execute() 103 - .await?; 104 - 105 - Ok(request_id) 106 - } 107 - 108 - pub async fn get_deletion_status(&self, request_id: Uuid) -> Result<Option<DeletionRequest>> { 109 - let result = self 110 - .client 111 - .query("SELECT * FROM deletion_requests WHERE request_id = ?") 112 - .bind(request_id) 113 - .fetch_one::<DeletionRequest>() 114 - .await; 115 - 116 - match result { 117 - Ok(req) => Ok(Some(req)), 118 - Err(e) if e.to_string().contains("not found") => Ok(None), 119 - Err(e) => Err(e.into()), 120 - } 121 - } 122 - }
···
-4
rust/sp-analytics/src/db/mod.rs
··· 1 - pub mod clickhouse; 2 - pub mod schema; 3 - 4 - pub use clickhouse::ClickHouseClient;
···
-21
rust/sp-analytics/src/db/schema.rs
··· 1 - use anyhow::Result; 2 - use clickhouse::Client; 3 - use tracing::info; 4 - 5 - const MIGRATIONS: &[&str] = &[include_str!("../../migrations/001_initial.sql")]; 6 - 7 - // TODO: better way to do CH migrations than to run them on every startup 8 - pub async fn run_migrations(client: &Client) -> Result<()> { 9 - info!("running database migrations"); 10 - 11 - for (idx, migration) in MIGRATIONS.iter().enumerate() { 12 - info!("running migration {}", idx + 1); 13 - 14 - for statement in migration.split(';').filter(|s| !s.trim().is_empty()) { 15 - client.query(statement).execute().await?; 16 - } 17 - } 18 - 19 - info!("migrations complete"); 20 - Ok(()) 21 - }
···
-159
rust/sp-analytics/src/ingest/buffer.rs
··· 1 - use crate::config::IngestionConfig; 2 - use crate::db::clickhouse::{ClickHouseClient, EventRow}; 3 - use crate::ingest::wal::WriteAheadLog; 4 - use anyhow::Result; 5 - use std::sync::Arc; 6 - use std::time::Duration; 7 - use tokio::sync::Mutex; 8 - use tokio::time; 9 - use tracing::{debug, error, info, warn}; 10 - use uuid::Uuid; 11 - 12 - pub struct EventBuffer { 13 - buffer: Arc<Mutex<Vec<EventRow>>>, 14 - clickhouse: ClickHouseClient, 15 - wal: Option<WriteAheadLog>, 16 - config: IngestionConfig, 17 - } 18 - 19 - impl EventBuffer { 20 - pub fn new( 21 - clickhouse: ClickHouseClient, 22 - wal: Option<WriteAheadLog>, 23 - config: IngestionConfig, 24 - ) -> Self { 25 - Self { 26 - buffer: Arc::new(Mutex::new(Vec::new())), 27 - clickhouse, 28 - wal, 29 - config, 30 - } 31 - } 32 - 33 - pub async fn add_events(&self, events: Vec<EventRow>) -> Result<()> { 34 - if let Some(wal) = &self.wal { 35 - wal.write_events(&events)?; 36 - } 37 - 38 - let mut buffer = self.buffer.lock().await; 39 - buffer.extend(events); 40 - 41 - if buffer.len() >= self.config.batch_size { 42 - drop(buffer); 43 - self.flush().await?; 44 - } 45 - 46 - Ok(()) 47 - } 48 - 49 - pub async fn flush(&self) -> Result<()> { 50 - let events = { 51 - let mut buffer = self.buffer.lock().await; 52 - if buffer.is_empty() { 53 - return Ok(()); 54 - } 55 - std::mem::take(&mut *buffer) 56 - }; 57 - 58 - let event_count = events.len(); 59 - debug!("flushing {} events to ClickHouse", event_count); 60 - 61 - match self.flush_with_retry(&events).await { 62 - Ok(_) => { 63 - info!("successfully flushed {} events", event_count); 64 - 65 - if let Some(wal) = &self.wal { 66 - let event_ids: Vec<Uuid> = events.iter().map(|e| e.event_id).collect(); 67 - if let Err(e) = wal.remove_events(&event_ids) { 68 - error!("failed to remove events from WAL: {}", e); 69 - } 70 - } 71 - 72 - Ok(()) 73 - } 74 - Err(e) => { 75 - error!("failed to flush events after retries: {}", e); 76 - 77 - let mut buffer = self.buffer.lock().await; 78 - buffer.extend(events); 79 - 80 - Err(e) 81 - } 82 - } 83 - } 84 - 85 - async fn flush_with_retry(&self, events: &[EventRow]) -> Result<()> { 86 - let mut attempts = 0; 87 - let max_attempts = self.config.max_retry_attempts; 88 - 89 - loop { 90 - match self.clickhouse.insert_events(events.to_vec()).await { 91 - Ok(_) => return Ok(()), 92 - Err(e) => { 93 - attempts += 1; 94 - if attempts >= max_attempts { 95 - return Err(e); 96 - } 97 - 98 - let backoff = Duration::from_millis( 99 - self.config.retry_backoff_base_ms * 2u64.pow(attempts - 1), 100 - ); 101 - 102 - warn!( 103 - "flush attempt {}/{} failed: {}, retrying in {:?}", 104 - attempts, max_attempts, e, backoff 105 - ); 106 - 107 - time::sleep(backoff).await; 108 - } 109 - } 110 - } 111 - } 112 - 113 - pub fn start_periodic_flush(self: Arc<Self>) { 114 - let flush_interval = Duration::from_millis(self.config.flush_interval_ms); 115 - 116 - tokio::spawn(async move { 117 - let mut interval = time::interval(flush_interval); 118 - 119 - loop { 120 - interval.tick().await; 121 - 122 - if let Err(e) = self.flush().await { 123 - error!("periodic flush failed: {}", e); 124 - } 125 - } 126 - }); 127 - } 128 - 129 - pub async fn replay_wal(&self) -> Result<usize> { 130 - let wal = match &self.wal { 131 - Some(wal) => wal, 132 - None => return Ok(0), 133 - }; 134 - 135 - let events = wal.read_all_events()?; 136 - let count = events.len(); 137 - 138 - if count == 0 { 139 - return Ok(0); 140 - } 141 - 142 - info!("replaying {} events from WAL", count); 143 - 144 - dbg!(&events); 145 - 146 - match self.flush_with_retry(&events).await { 147 - Ok(_) => { 148 - info!("successfully replayed {} events", count); 149 - let event_ids: Vec<Uuid> = events.iter().map(|e| e.event_id).collect(); 150 - wal.remove_events(&event_ids)?; 151 - Ok(count) 152 - } 153 - Err(e) => { 154 - error!("failed to replay WAL events: {}", e); 155 - Err(e) 156 - } 157 - } 158 - } 159 - }
···
-7
rust/sp-analytics/src/ingest/mod.rs
··· 1 - pub mod buffer; 2 - pub mod validator; 3 - pub mod wal; 4 - 5 - pub use buffer::EventBuffer; 6 - pub use validator::{validate_event, ValidationError}; 7 - pub use wal::WriteAheadLog;
···
-116
rust/sp-analytics/src/ingest/validator.rs
··· 1 - use crate::proto::Event; 2 - use thiserror::Error; 3 - 4 - #[derive(Debug, Error)] 5 - pub enum ValidationError { 6 - #[error("missing required field: {0}")] 7 - MissingField(String), 8 - 9 - #[error("invalid field value: {field}: {reason}")] 10 - InvalidField { field: String, reason: String }, 11 - 12 - #[error("invalid JSON in properties: {0}")] 13 - InvalidJson(String), 14 - } 15 - 16 - pub fn validate_event(event: &Event) -> Result<(), ValidationError> { 17 - if event.event_id.is_empty() { 18 - return Err(ValidationError::MissingField("event_id".to_string())); 19 - } 20 - 21 - if event.event_type.is_empty() { 22 - return Err(ValidationError::MissingField("event_type".to_string())); 23 - } 24 - 25 - if event.device_id.is_empty() { 26 - return Err(ValidationError::MissingField("device_id".to_string())); 27 - } 28 - 29 - if event.session_id.is_empty() { 30 - return Err(ValidationError::MissingField("session_id".to_string())); 31 - } 32 - 33 - if event.streamer_did.is_empty() { 34 - return Err(ValidationError::MissingField("streamer_did".to_string())); 35 - } 36 - 37 - if event.client_version.is_empty() { 38 - return Err(ValidationError::MissingField("client_version".to_string())); 39 - } 40 - 41 - if event.platform.is_empty() { 42 - return Err(ValidationError::MissingField("platform".to_string())); 43 - } 44 - 45 - if event.timestamp_ms <= 0 { 46 - return Err(ValidationError::InvalidField { 47 - field: "timestamp_ms".to_string(), 48 - reason: "must be positive".to_string(), 49 - }); 50 - } 51 - 52 - if !event.properties_json.is_empty() { 53 - serde_json::from_str::<serde_json::Value>(&event.properties_json) 54 - .map_err(|e| ValidationError::InvalidJson(e.to_string()))?; 55 - } 56 - 57 - Ok(()) 58 - } 59 - 60 - #[cfg(test)] 61 - mod tests { 62 - use super::*; 63 - 64 - fn valid_event() -> Event { 65 - Event { 66 - event_id: "550e8400-e29b-41d4-a716-446655440000".to_string(), 67 - event_type: "watch".to_string(), 68 - device_id: "device123".to_string(), 69 - did: Some("did:plc:user123".to_string()), 70 - session_id: "session456".to_string(), 71 - timestamp_ms: 1704067200000, 72 - streamer_did: "did:plc:streamer789".to_string(), 73 - stream_id: Some("stream101".to_string()), 74 - properties_json: r#"{"duration_ms": 30000}"#.to_string(), 75 - schema_version: 1, 76 - client_version: "1.0.0".to_string(), 77 - platform: "ios".to_string(), 78 - } 79 - } 80 - 81 - #[test] 82 - fn test_valid_event() { 83 - let event = valid_event(); 84 - assert!(validate_event(&event).is_ok()); 85 - } 86 - 87 - #[test] 88 - fn test_missing_event_id() { 89 - let mut event = valid_event(); 90 - event.event_id = String::new(); 91 - assert!(matches!( 92 - validate_event(&event), 93 - Err(ValidationError::MissingField(_)) 94 - )); 95 - } 96 - 97 - #[test] 98 - fn test_invalid_timestamp() { 99 - let mut event = valid_event(); 100 - event.timestamp_ms = 0; 101 - assert!(matches!( 102 - validate_event(&event), 103 - Err(ValidationError::InvalidField { .. }) 104 - )); 105 - } 106 - 107 - #[test] 108 - fn test_invalid_json() { 109 - let mut event = valid_event(); 110 - event.properties_json = "not valid json".to_string(); 111 - assert!(matches!( 112 - validate_event(&event), 113 - Err(ValidationError::InvalidJson(_)) 114 - )); 115 - } 116 - }
···
-154
rust/sp-analytics/src/ingest/wal.rs
··· 1 - use crate::db::clickhouse::EventRow; 2 - use anyhow::{Context, Result}; 3 - use redb::{Database, ReadableTable, ReadableTableMetadata, TableDefinition}; 4 - use std::path::Path; 5 - use std::sync::Arc; 6 - use tracing::{debug, info}; 7 - use uuid::Uuid; 8 - 9 - const EVENTS_TABLE: TableDefinition<&str, &[u8]> = TableDefinition::new("events"); 10 - 11 - #[derive(Clone)] 12 - pub struct WriteAheadLog { 13 - db: Arc<Database>, 14 - } 15 - 16 - impl WriteAheadLog { 17 - pub fn new<P: AsRef<Path>>(path: P) -> Result<Self> { 18 - let db = Database::create(path).context("failed to create WAL database")?; 19 - Ok(Self { db: Arc::new(db) }) 20 - } 21 - 22 - pub fn write_events(&self, events: &[EventRow]) -> Result<()> { 23 - let write_txn = self.db.begin_write()?; 24 - { 25 - let mut table = write_txn.open_table(EVENTS_TABLE)?; 26 - for event in events { 27 - let key = event.event_id.to_string(); 28 - let value = serde_json::to_vec(event)?; 29 - table.insert(key.as_str(), value.as_slice())?; 30 - } 31 - } 32 - write_txn.commit()?; 33 - debug!("wrote {} events to WAL", events.len()); 34 - Ok(()) 35 - } 36 - 37 - pub fn remove_events(&self, event_ids: &[Uuid]) -> Result<()> { 38 - let write_txn = self.db.begin_write()?; 39 - { 40 - let mut table = write_txn.open_table(EVENTS_TABLE)?; 41 - for event_id in event_ids { 42 - let key = event_id.to_string(); 43 - table.remove(key.as_str())?; 44 - } 45 - } 46 - write_txn.commit()?; 47 - debug!("removed {} events from WAL", event_ids.len()); 48 - Ok(()) 49 - } 50 - 51 - pub fn read_all_events(&self) -> Result<Vec<EventRow>> { 52 - let read_txn = self.db.begin_read()?; 53 - let table = read_txn.open_table(EVENTS_TABLE)?; 54 - 55 - let mut events = Vec::new(); 56 - for entry in table.iter()? { 57 - let (_, value) = entry?; 58 - let event: EventRow = serde_json::from_slice(value.value())?; 59 - events.push(event); 60 - } 61 - 62 - info!("read {} events from WAL", events.len()); 63 - Ok(events) 64 - } 65 - 66 - pub fn count(&self) -> Result<usize> { 67 - let read_txn = self.db.begin_read()?; 68 - let table = read_txn.open_table(EVENTS_TABLE)?; 69 - Ok(table.len()? as usize) 70 - } 71 - 72 - pub fn clear_all(&self) -> Result<()> { 73 - let write_txn = self.db.begin_write()?; 74 - { 75 - let mut table = write_txn.open_table(EVENTS_TABLE)?; 76 - let keys: Vec<String> = table 77 - .iter()? 78 - .map(|entry| entry.map(|(k, _)| k.value().to_string())) 79 - .collect::<Result<_, _>>()?; 80 - 81 - for key in keys { 82 - table.remove(key.as_str())?; 83 - } 84 - } 85 - write_txn.commit()?; 86 - info!("cleared all events from WAL"); 87 - Ok(()) 88 - } 89 - } 90 - 91 - #[cfg(test)] 92 - mod tests { 93 - use super::*; 94 - use chrono::Utc; 95 - use tempfile::tempdir; 96 - 97 - #[test] 98 - fn test_wal_write_and_read() { 99 - let dir = tempdir().unwrap(); 100 - let wal_path = dir.path().join("test.wal"); 101 - let wal = WriteAheadLog::new(&wal_path).unwrap(); 102 - 103 - let events = vec![EventRow { 104 - event_id: Uuid::new_v4(), 105 - event_type: "watch".to_string(), 106 - device_id: "device123".to_string(), 107 - did: Some("did:plc:user123".to_string()), 108 - session_id: "session456".to_string(), 109 - timestamp: Utc::now(), 110 - streamer_did: "did:plc:streamer789".to_string(), 111 - stream_id: Some("stream101".to_string()), 112 - properties: r#"{"duration_ms": 30000}"#.to_string(), 113 - schema_version: 1, 114 - client_version: "1.0.0".to_string(), 115 - platform: "ios".to_string(), 116 - }]; 117 - 118 - wal.write_events(&events).unwrap(); 119 - assert_eq!(wal.count().unwrap(), 1); 120 - 121 - let read_events = wal.read_all_events().unwrap(); 122 - assert_eq!(read_events.len(), 1); 123 - assert_eq!(read_events[0].event_id, events[0].event_id); 124 - } 125 - 126 - #[test] 127 - fn test_wal_remove() { 128 - let dir = tempdir().unwrap(); 129 - let wal_path = dir.path().join("test.wal"); 130 - let wal = WriteAheadLog::new(&wal_path).unwrap(); 131 - 132 - let event_id = Uuid::new_v4(); 133 - let events = vec![EventRow { 134 - event_id, 135 - event_type: "watch".to_string(), 136 - device_id: "device123".to_string(), 137 - did: None, 138 - session_id: "session456".to_string(), 139 - timestamp: Utc::now(), 140 - streamer_did: "did:plc:streamer789".to_string(), 141 - stream_id: None, 142 - properties: "{}".to_string(), 143 - schema_version: 1, 144 - client_version: "1.0.0".to_string(), 145 - platform: "web".to_string(), 146 - }]; 147 - 148 - wal.write_events(&events).unwrap(); 149 - assert_eq!(wal.count().unwrap(), 1); 150 - 151 - wal.remove_events(&[event_id]).unwrap(); 152 - assert_eq!(wal.count().unwrap(), 0); 153 - } 154 - }
···
-13
rust/sp-analytics/src/lib.rs
··· 1 - pub mod api; 2 - pub mod config; 3 - pub mod db; 4 - pub mod ingest; 5 - pub mod metrics; 6 - pub mod privacy; 7 - pub mod query; 8 - 9 - pub use config::Config; 10 - 11 - pub mod proto { 12 - tonic::include_proto!("analytics"); 13 - }
···
-89
rust/sp-analytics/src/main.rs
··· 1 - use sp_analytics::{ 2 - api::AnalyticsService, 3 - config::Config, 4 - db::{ClickHouseClient, schema::run_migrations}, 5 - ingest::{EventBuffer, WriteAheadLog}, 6 - metrics, 7 - proto::analytics_server::AnalyticsServer, 8 - }; 9 - use std::sync::Arc; 10 - use tonic::transport::Server; 11 - use tracing::{error, info}; 12 - use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; 13 - 14 - #[tokio::main] 15 - async fn main() -> Result<(), Box<dyn std::error::Error>> { 16 - dotenvy::dotenv().ok(); 17 - // get a env variable just in case 18 - dbg!(std::env::var("SP_ANALYTICS_CLICKHOUSE__USERNAME").ok()); 19 - tracing_subscriber::registry() 20 - .with( 21 - tracing_subscriber::EnvFilter::try_from_default_env() 22 - .unwrap_or_else(|_| "sp_analytics=info,tower_http=debug".into()), 23 - ) 24 - .with(tracing_subscriber::fmt::layer()) 25 - .init(); 26 - 27 - info!("starting sp-analytics service"); 28 - 29 - let config = Config::load().unwrap_or_else(|e| { 30 - error!("failed to load config: {}, using defaults", e); 31 - Config::default() 32 - }); 33 - 34 - info!("initializing prometheus metrics on port 9091"); 35 - metrics::init_metrics(9091)?; 36 - 37 - info!("connecting to ClickHouse at {}", config.clickhouse.url); 38 - let clickhouse = ClickHouseClient::new(&config.clickhouse)?; 39 - 40 - info!("running database migrations"); 41 - run_migrations(clickhouse.client()).await?; 42 - 43 - let wal = if config.wal.enabled { 44 - info!("initializing WAL at {}", config.wal.path); 45 - 46 - if let Some(parent) = std::path::Path::new(&config.wal.path).parent() { 47 - std::fs::create_dir_all(parent)?; 48 - } 49 - 50 - Some(WriteAheadLog::new(&config.wal.path)?) 51 - } else { 52 - info!("WAL disabled"); 53 - None 54 - }; 55 - 56 - let buffer = Arc::new(EventBuffer::new( 57 - clickhouse.clone(), 58 - wal.clone(), 59 - config.ingestion.clone(), 60 - )); 61 - 62 - if config.wal.enabled { 63 - info!("replaying WAL"); 64 - match buffer.replay_wal().await { 65 - Ok(count) => { 66 - info!("replayed {} events from WAL", count); 67 - metrics::record_wal_replay(count as u64); 68 - } 69 - Err(e) => { 70 - error!("failed to replay WAL: {}", e); 71 - } 72 - } 73 - } 74 - 75 - info!("starting periodic flush"); 76 - buffer.clone().start_periodic_flush(); 77 - 78 - let service = AnalyticsService::new(clickhouse, buffer); 79 - 80 - let addr = format!("0.0.0.0:{}", config.server.grpc_port).parse()?; 81 - info!("gRPC server listening on {}", addr); 82 - 83 - Server::builder() 84 - .add_service(AnalyticsServer::new(service)) 85 - .serve(addr) 86 - .await?; 87 - 88 - Ok(()) 89 - }
···
-34
rust/sp-analytics/src/metrics.rs
··· 1 - use metrics_exporter_prometheus::PrometheusBuilder; 2 - use std::net::SocketAddr; 3 - use tracing::info; 4 - 5 - pub fn init_metrics(port: u16) -> Result<(), Box<dyn std::error::Error>> { 6 - let addr: SocketAddr = ([0, 0, 0, 0], port).into(); 7 - 8 - PrometheusBuilder::new() 9 - .with_http_listener(addr) 10 - .install()?; 11 - 12 - info!("prometheus metrics server listening on {}", addr); 13 - Ok(()) 14 - } 15 - 16 - pub fn record_events_ingested(count: u64) { 17 - metrics::counter!("events_ingested_total").increment(count); 18 - } 19 - 20 - pub fn record_events_rejected(count: u64) { 21 - metrics::counter!("events_rejected_total").increment(count); 22 - } 23 - 24 - pub fn record_events_flushed(count: u64) { 25 - metrics::counter!("events_flushed_total").increment(count); 26 - } 27 - 28 - pub fn record_flush_duration(duration_ms: f64) { 29 - metrics::histogram!("flush_duration_ms").record(duration_ms); 30 - } 31 - 32 - pub fn record_wal_replay(count: u64) { 33 - metrics::counter!("wal_replay_total").increment(count); 34 - }
···
-14
rust/sp-analytics/src/privacy/deletion.rs
··· 1 - use crate::db::clickhouse::ClickHouseClient; 2 - use anyhow::Result; 3 - use uuid::Uuid; 4 - 5 - pub async fn delete_user_data(clickhouse: &ClickHouseClient, did: String) -> Result<Uuid> { 6 - clickhouse.create_deletion_request(did).await 7 - } 8 - 9 - pub async fn get_deletion_status( 10 - clickhouse: &ClickHouseClient, 11 - request_id: Uuid, 12 - ) -> Result<Option<crate::db::clickhouse::DeletionRequest>> { 13 - clickhouse.get_deletion_status(request_id).await 14 - }
···
-3
rust/sp-analytics/src/privacy/mod.rs
··· 1 - pub mod deletion; 2 - 3 - pub use deletion::*;
···
-139
rust/sp-analytics/src/query/aggregations.rs
··· 1 - use anyhow::Result; 2 - use clickhouse::{Client, Row}; 3 - use serde::{Deserialize, Serialize}; 4 - 5 - #[derive(Debug, Clone, Serialize, Deserialize, Row)] 6 - pub struct DailyStatsRow { 7 - pub date: String, 8 - pub views: u64, 9 - pub watch_time_ms: u64, 10 - pub unique_viewers: u64, 11 - } 12 - 13 - #[derive(Debug, Clone, Serialize, Deserialize, Row)] 14 - pub struct WatchSessionRow { 15 - pub session_id: String, 16 - pub streamer_did: String, 17 - pub stream_id: Option<String>, 18 - pub start_time_ms: i64, 19 - pub end_time_ms: i64, 20 - pub duration_ms: u64, 21 - } 22 - 23 - pub async fn get_streamer_stats( 24 - client: &Client, 25 - streamer_did: &str, 26 - start_time_ms: Option<i64>, 27 - end_time_ms: Option<i64>, 28 - ) -> Result<(u64, u64, u64, Vec<DailyStatsRow>)> { 29 - let mut query = String::from( 30 - "SELECT 31 - count() as views, 32 - sum(JSONExtractInt(properties, 'duration_ms')) as watch_time_ms, 33 - uniqExact(device_id) as unique_viewers 34 - FROM events 35 - WHERE streamer_did = ? AND event_type = 'watch'" 36 - ); 37 - 38 - if start_time_ms.is_some() { 39 - query.push_str(" AND timestamp >= toDateTime64(?, 3)"); 40 - } 41 - if end_time_ms.is_some() { 42 - query.push_str(" AND timestamp <= toDateTime64(?, 3)"); 43 - } 44 - 45 - #[derive(Debug, Row, Deserialize)] 46 - struct TotalStats { 47 - views: u64, 48 - watch_time_ms: u64, 49 - unique_viewers: u64, 50 - } 51 - 52 - let mut q = client.query(&query).bind(streamer_did); 53 - if let Some(start) = start_time_ms { 54 - q = q.bind(start / 1000); 55 - } 56 - if let Some(end) = end_time_ms { 57 - q = q.bind(end / 1000); 58 - } 59 - 60 - let totals: TotalStats = q.fetch_one().await?; 61 - 62 - let mut daily_query = String::from( 63 - "SELECT 64 - toDate(timestamp) as date, 65 - count() as views, 66 - sum(JSONExtractInt(properties, 'duration_ms')) as watch_time_ms, 67 - uniqExact(device_id) as unique_viewers 68 - FROM events 69 - WHERE streamer_did = ? AND event_type = 'watch'" 70 - ); 71 - 72 - if start_time_ms.is_some() { 73 - daily_query.push_str(" AND timestamp >= toDateTime64(?, 3)"); 74 - } 75 - if end_time_ms.is_some() { 76 - daily_query.push_str(" AND timestamp <= toDateTime64(?, 3)"); 77 - } 78 - daily_query.push_str(" GROUP BY date ORDER BY date DESC"); 79 - 80 - let mut dq = client.query(&daily_query).bind(streamer_did); 81 - if let Some(start) = start_time_ms { 82 - dq = dq.bind(start / 1000); 83 - } 84 - if let Some(end) = end_time_ms { 85 - dq = dq.bind(end / 1000); 86 - } 87 - 88 - let daily_stats: Vec<DailyStatsRow> = dq.fetch_all().await?; 89 - 90 - Ok(( 91 - totals.views, 92 - totals.watch_time_ms, 93 - totals.unique_viewers, 94 - daily_stats, 95 - )) 96 - } 97 - 98 - pub async fn get_viewer_history( 99 - client: &Client, 100 - did: &str, 101 - start_time_ms: Option<i64>, 102 - end_time_ms: Option<i64>, 103 - limit: u32, 104 - ) -> Result<Vec<WatchSessionRow>> { 105 - let mut query = String::from( 106 - "SELECT 107 - session_id, 108 - streamer_did, 109 - stream_id, 110 - toUnixTimestamp64Milli(min(timestamp)) as start_time_ms, 111 - toUnixTimestamp64Milli(max(timestamp)) as end_time_ms, 112 - sum(JSONExtractInt(properties, 'duration_ms')) as duration_ms 113 - FROM events 114 - WHERE did = ? AND event_type = 'watch'" 115 - ); 116 - 117 - if start_time_ms.is_some() { 118 - query.push_str(" AND timestamp >= toDateTime64(?, 3)"); 119 - } 120 - if end_time_ms.is_some() { 121 - query.push_str(" AND timestamp <= toDateTime64(?, 3)"); 122 - } 123 - 124 - query.push_str(" GROUP BY session_id, streamer_did, stream_id"); 125 - query.push_str(" ORDER BY start_time_ms DESC"); 126 - query.push_str(" LIMIT ?"); 127 - 128 - let mut q = client.query(&query).bind(did); 129 - if let Some(start) = start_time_ms { 130 - q = q.bind(start / 1000); 131 - } 132 - if let Some(end) = end_time_ms { 133 - q = q.bind(end / 1000); 134 - } 135 - q = q.bind(limit); 136 - 137 - let sessions = q.fetch_all().await?; 138 - Ok(sessions) 139 - }
···
-5
rust/sp-analytics/src/query/mod.rs
··· 1 - pub mod aggregations; 2 - pub mod realtime; 3 - 4 - pub use aggregations::*; 5 - pub use realtime::*;
···
-57
rust/sp-analytics/src/query/realtime.rs
··· 1 - use anyhow::Result; 2 - use clickhouse::{Client, Row}; 3 - use serde::{Deserialize, Serialize}; 4 - 5 - #[derive(Debug, Clone, Serialize, Deserialize, Row)] 6 - pub struct StreamerRealtimeRow { 7 - pub streamer_did: String, 8 - pub current_viewers: u64, 9 - pub total_watch_time_ms: u64, 10 - } 11 - 12 - pub async fn get_realtime_stats( 13 - client: &Client, 14 - streamer_did: Option<&str>, 15 - window_minutes: u32, 16 - ) -> Result<Vec<StreamerRealtimeRow>> { 17 - let mut query = String::from( 18 - "SELECT 19 - streamer_did, 20 - uniqExact(device_id) as current_viewers, 21 - sum( 22 - CASE 23 - WHEN session_duration > 0 THEN session_duration 24 - ELSE 5000 25 - END 26 - ) as total_watch_time_ms 27 - FROM ( 28 - SELECT 29 - streamer_did, 30 - device_id, 31 - session_id, 32 - dateDiff('millisecond', min(timestamp), max(timestamp)) as session_duration 33 - FROM events 34 - WHERE event_type = 'aq-played' 35 - AND timestamp > now() - INTERVAL ? MINUTE", 36 - ); 37 - 38 - if streamer_did.is_some() { 39 - query.push_str(" AND streamer_did = ?"); 40 - } 41 - 42 - query.push_str( 43 - " 44 - GROUP BY streamer_did, device_id, session_id 45 - ) 46 - GROUP BY streamer_did", 47 - ); 48 - 49 - let mut q = client.query(&query).bind(window_minutes); 50 - 51 - if let Some(did) = streamer_did { 52 - q = q.bind(did); 53 - } 54 - 55 - let stats = q.fetch_all().await?; 56 - Ok(stats) 57 - }
···
+9
wrangler.toml
···
··· 1 + name = "streamplace-docs" 2 + compatibility_date = "2025-04-01" 3 + 4 + [assets] 5 + directory = "./js/docs/dist/" 6 + not_found_handling = "404-page" 7 + 8 + [build] 9 + command = "pnpm install --filter=streamplace-docs... && cd js/docs && astro build --outDir ./dist/docs && cp ./_redirects ./dist/_redirects && cp ./src/assets/cube.png ./dist/favicon.ico"