mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-17 13:21:44 +01:00
Remove legacy relay connection pool
This commit is contained in:
parent
d44e989195
commit
1d04e20110
5
.changeset/eleven-planets-hear.md
Normal file
5
.changeset/eleven-planets-hear.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Remove legacy relay connection pool
|
300
pnpm-lock.yaml
generated
300
pnpm-lock.yaml
generated
@ -104,28 +104,28 @@ importers:
|
||||
version: 0.7.2
|
||||
applesauce-accounts:
|
||||
specifier: next
|
||||
version: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
version: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
applesauce-content:
|
||||
specifier: next
|
||||
version: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
version: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
applesauce-core:
|
||||
specifier: next
|
||||
version: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
version: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
applesauce-factory:
|
||||
specifier: next
|
||||
version: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
version: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
applesauce-loaders:
|
||||
specifier: next
|
||||
version: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
version: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
applesauce-net:
|
||||
specifier: ^0.10.0
|
||||
version: 0.10.0(typescript@5.7.3)
|
||||
applesauce-react:
|
||||
specifier: next
|
||||
version: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
version: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
applesauce-signers:
|
||||
specifier: next
|
||||
version: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
version: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
bech32:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
@ -426,7 +426,7 @@ importers:
|
||||
version: 4.7.5
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^4.3.4
|
||||
version: 4.3.4(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0))
|
||||
version: 4.3.4(vite@5.4.14(@types/node@22.13.1)(terser@5.38.0))
|
||||
camelcase:
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.0
|
||||
@ -441,13 +441,13 @@ importers:
|
||||
version: 5.7.3
|
||||
vite:
|
||||
specifier: ^5.4.14
|
||||
version: 5.4.14(@types/node@22.13.1)(terser@5.37.0)
|
||||
version: 5.4.14(@types/node@22.13.1)(terser@5.38.0)
|
||||
vite-plugin-pwa:
|
||||
specifier: ^0.21.1
|
||||
version: 0.21.1(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0)
|
||||
version: 0.21.1(vite@5.4.14(@types/node@22.13.1)(terser@5.38.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0)
|
||||
vite-tsconfig-paths:
|
||||
specifier: ^5.1.4
|
||||
version: 5.1.4(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0))
|
||||
version: 5.1.4(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.1)(terser@5.38.0))
|
||||
workbox-build:
|
||||
specifier: ^7.3.0
|
||||
version: 7.3.0(@types/babel__core@7.20.5)
|
||||
@ -1720,98 +1720,98 @@ packages:
|
||||
rollup:
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.34.2':
|
||||
resolution: {integrity: sha512-6Fyg9yQbwJR+ykVdT9sid1oc2ewejS6h4wzQltmJfSW53N60G/ah9pngXGANdy9/aaE/TcUFpWosdm7JXS1WTQ==}
|
||||
'@rollup/rollup-android-arm-eabi@4.34.3':
|
||||
resolution: {integrity: sha512-8kq/NjMKkMTGKMPldWihncOl62kgnLYk7cW+/4NCUWfS70/wz4+gQ7rMxMMpZ3dIOP/xw7wKNzIuUnN/H2GfUg==}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-android-arm64@4.34.2':
|
||||
resolution: {integrity: sha512-K5GfWe+vtQ3kyEbihrimM38UgX57UqHp+oME7X/EX9Im6suwZfa7Hsr8AtzbJvukTpwMGs+4s29YMSO3rwWtsw==}
|
||||
'@rollup/rollup-android-arm64@4.34.3':
|
||||
resolution: {integrity: sha512-1PqMHiuRochQ6++SDI7SaRDWJKr/NgAlezBi5nOne6Da6IWJo3hK0TdECBDwd92IUDPG4j/bZmWuwOnomNT8wA==}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.34.2':
|
||||
resolution: {integrity: sha512-PSN58XG/V/tzqDb9kDGutUruycgylMlUE59f40ny6QIRNsTEIZsrNQTJKUN2keMMSmlzgunMFqyaGLmly39sug==}
|
||||
'@rollup/rollup-darwin-arm64@4.34.3':
|
||||
resolution: {integrity: sha512-fqbrykX4mGV3DlCDXhF4OaMGcchd2tmLYxVt3On5oOZWVDFfdEoYAV2alzNChl8OzNaeMAGqm1f7gk7eIw/uDg==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.34.2':
|
||||
resolution: {integrity: sha512-gQhK788rQJm9pzmXyfBB84VHViDERhAhzGafw+E5mUpnGKuxZGkMVDa3wgDFKT6ukLC5V7QTifzsUKdNVxp5qQ==}
|
||||
'@rollup/rollup-darwin-x64@4.34.3':
|
||||
resolution: {integrity: sha512-8Wxrx/KRvMsTyLTbdrMXcVKfpW51cCNW8x7iQD72xSEbjvhCY3b+w83Bea3nQfysTMR7K28esc+ZFITThXm+1w==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.34.2':
|
||||
resolution: {integrity: sha512-eiaHgQwGPpxLC3+zTAcdKl4VsBl3r0AiJOd1Um/ArEzAjN/dbPK1nROHrVkdnoE6p7Svvn04w3f/jEZSTVHunA==}
|
||||
'@rollup/rollup-freebsd-arm64@4.34.3':
|
||||
resolution: {integrity: sha512-lpBmV2qSiELh+ATQPTjQczt5hvbTLsE0c43Rx4bGxN2VpnAZWy77we7OO62LyOSZNY7CzjMoceRPc+Lt4e9J6A==}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.34.2':
|
||||
resolution: {integrity: sha512-lhdiwQ+jf8pewYOTG4bag0Qd68Jn1v2gO1i0mTuiD+Qkt5vNfHVK/jrT7uVvycV8ZchlzXp5HDVmhpzjC6mh0g==}
|
||||
'@rollup/rollup-freebsd-x64@4.34.3':
|
||||
resolution: {integrity: sha512-sNPvBIXpgaYcI6mAeH13GZMXFrrw5mdZVI1M9YQPRG2LpjwL8DSxSIflZoh/B5NEuOi53kxsR/S2GKozK1vDXA==}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.34.2':
|
||||
resolution: {integrity: sha512-lfqTpWjSvbgQP1vqGTXdv+/kxIznKXZlI109WkIFPbud41bjigjNmOAAKoazmRGx+k9e3rtIdbq2pQZPV1pMig==}
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.34.3':
|
||||
resolution: {integrity: sha512-MW6N3AoC61OfE1VgnN5O1OW0gt8VTbhx9s/ZEPLBM11wEdHjeilPzOxVmmsrx5YmejpGPvez8QwGGvMU+pGxpw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.34.2':
|
||||
resolution: {integrity: sha512-RGjqULqIurqqv+NJTyuPgdZhka8ImMLB32YwUle2BPTDqDoXNgwFjdjQC59FbSk08z0IqlRJjrJ0AvDQ5W5lpw==}
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.34.3':
|
||||
resolution: {integrity: sha512-2SQkhr5xvatYq0/+H6qyW0zvrQz9LM4lxGkpWURLoQX5+yP8MsERh4uWmxFohOvwCP6l/+wgiHZ1qVwLDc7Qmw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.34.2':
|
||||
resolution: {integrity: sha512-ZvkPiheyXtXlFqHpsdgscx+tZ7hoR59vOettvArinEspq5fxSDSgfF+L5wqqJ9R4t+n53nyn0sKxeXlik7AY9Q==}
|
||||
'@rollup/rollup-linux-arm64-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-R3JLYt8YoRwKI5shJsovLpcR6pwIMui/MGG/MmxZ1DYI3iRSKI4qcYrvYgDf4Ss2oCR3RL3F3dYK7uAGQgMIuQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.34.2':
|
||||
resolution: {integrity: sha512-UlFk+E46TZEoxD9ufLKDBzfSG7Ki03fo6hsNRRRHF+KuvNZ5vd1RRVQm8YZlGsjcJG8R252XFK0xNPay+4WV7w==}
|
||||
'@rollup/rollup-linux-arm64-musl@4.34.3':
|
||||
resolution: {integrity: sha512-4XQhG8v/t3S7Rxs7rmFUuM6j09hVrTArzONS3fUZ6oBRSN/ps9IPQjVhp62P0W3KhqJdQADo/MRlYRMdgxr/3w==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-loongarch64-gnu@4.34.2':
|
||||
resolution: {integrity: sha512-hJhfsD9ykx59jZuuoQgYT1GEcNNi3RCoEmbo5OGfG8RlHOiVS7iVNev9rhLKh7UBYq409f4uEw0cclTXx8nh8Q==}
|
||||
'@rollup/rollup-linux-loongarch64-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-QlW1jCUZ1LHUIYCAK2FciVw1ptHsxzApYVi05q7bz2A8oNE8QxQ85NhM4arLxkAlcnS42t4avJbSfzSQwbIaKg==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.34.2':
|
||||
resolution: {integrity: sha512-g/O5IpgtrQqPegvqopvmdCF9vneLE7eqYfdPWW8yjPS8f63DNam3U4ARL1PNNB64XHZDHKpvO2Giftf43puB8Q==}
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-kMbLToizVeCcN69+nnm20Dh0hrRIAjgaaL+Wh0gWZcNt8e542d2FUGtsyuNsHVNNF3gqTJrpzUGIdwMGLEUM7g==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.34.2':
|
||||
resolution: {integrity: sha512-bSQijDC96M6PuooOuXHpvXUYiIwsnDmqGU8+br2U7iPoykNi9JtMUpN7K6xml29e0evK0/g0D1qbAUzWZFHY5Q==}
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-YgD0DnZ3CHtvXRH8rzjVSxwI0kMTr0RQt3o1N92RwxGdx7YejzbBO0ELlSU48DP96u1gYYVWfUhDRyaGNqJqJg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.34.2':
|
||||
resolution: {integrity: sha512-49TtdeVAsdRuiUHXPrFVucaP4SivazetGUVH8CIxVsNsaPHV4PFkpLmH9LeqU/R4Nbgky9lzX5Xe1NrzLyraVA==}
|
||||
'@rollup/rollup-linux-s390x-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-dIOoOz8altjp6UjAi3U9EW99s8nta4gzi52FeI45GlPyrUH4QixUoBMH9VsVjt+9A2RiZBWyjYNHlJ/HmJOBCQ==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.34.2':
|
||||
resolution: {integrity: sha512-j+jFdfOycLIQ7FWKka9Zd3qvsIyugg5LeZuHF6kFlXo6MSOc6R1w37YUVy8VpAKd81LMWGi5g9J25P09M0SSIw==}
|
||||
'@rollup/rollup-linux-x64-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-lOyG3aF4FTKrhpzXfMmBXgeKUUXdAWmP2zSNf8HTAXPqZay6QYT26l64hVizBjq+hJx3pl0DTEyvPi9sTA6VGA==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.34.2':
|
||||
resolution: {integrity: sha512-aDPHyM/D2SpXfSNCVWCxyHmOqN9qb7SWkY1+vaXqMNMXslZYnwh9V/UCudl6psyG0v6Ukj7pXanIpfZwCOEMUg==}
|
||||
'@rollup/rollup-linux-x64-musl@4.34.3':
|
||||
resolution: {integrity: sha512-usztyYLu2i+mYzzOjqHZTaRXbUOqw3P6laNUh1zcqxbPH1P2Tz/QdJJCQSnGxCtsRQeuU2bCyraGMtMumC46rw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.34.2':
|
||||
resolution: {integrity: sha512-LQRkCyUBnAo7r8dbEdtNU08EKLCJMgAk2oP5H3R7BnUlKLqgR3dUjrLBVirmc1RK6U6qhtDw29Dimeer8d5hzQ==}
|
||||
'@rollup/rollup-win32-arm64-msvc@4.34.3':
|
||||
resolution: {integrity: sha512-ojFOKaz/ZyalIrizdBq2vyc2f0kFbJahEznfZlxdB6pF9Do6++i1zS5Gy6QLf8D7/S57MHrmBLur6AeRYeQXSA==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.34.2':
|
||||
resolution: {integrity: sha512-wt8OhpQUi6JuPFkm1wbVi1BByeag87LDFzeKSXzIdGcX4bMLqORTtKxLoCbV57BHYNSUSOKlSL4BYYUghainYA==}
|
||||
'@rollup/rollup-win32-ia32-msvc@4.34.3':
|
||||
resolution: {integrity: sha512-K/V97GMbNa+Da9mGcZqmSl+DlJmWfHXTuI9V8oB2evGsQUtszCl67+OxWjBKpeOnYwox9Jpmt/J6VhpeRCYqow==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.34.2':
|
||||
resolution: {integrity: sha512-rUrqINax0TvrPBXrFKg0YbQx18NpPN3NNrgmaao9xRNbTwek7lOXObhx8tQy8gelmQ/gLaGy1WptpU2eKJZImg==}
|
||||
'@rollup/rollup-win32-x64-msvc@4.34.3':
|
||||
resolution: {integrity: sha512-CUypcYP31Q8O04myV6NKGzk9GVXslO5EJNfmARNSzLF2A+5rmZUlDJ4et6eoJaZgBT9wrC2p4JZH04Vkic8HdQ==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
@ -2192,32 +2192,32 @@ packages:
|
||||
engines: {node: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
applesauce-accounts@0.0.0-next-20250204170704:
|
||||
resolution: {integrity: sha512-y80D4PfoT9gkd+TtUExeQdiq5grlchUbsdjRfmEG3JuAopTCzdgEAa2L7wfLT4DmsUwBvO8ISAm+zKRZ+GI/NQ==}
|
||||
applesauce-accounts@0.0.0-next-20250204175150:
|
||||
resolution: {integrity: sha512-b3zqfiDc6X9aKhrLXgSuyuivdn3GEQW8prwg/Bu7nZD7egoGcLsTX4fyAAzgBz6H2CO2oKxnwoyziugHEy6ZIQ==}
|
||||
|
||||
applesauce-content@0.0.0-next-20250204170704:
|
||||
resolution: {integrity: sha512-hY6H2v6wSa/rzq6OCnjSL+y2Lv4/AR5z7irdqbSuzhSElslm78pqUPjsFlnVt7nu5K+1cAv0B/Ib/2yhaacgYw==}
|
||||
applesauce-content@0.0.0-next-20250204175150:
|
||||
resolution: {integrity: sha512-rFi/cWZbUYpMlFU8fNrEo0KkFy8lCyeGXxylcDW2zB6eMu8rUqQ2SZ9CiW9VUuBmjpxugetkhNJZtrINXhKj+w==}
|
||||
|
||||
applesauce-core@0.0.0-next-20250204170704:
|
||||
resolution: {integrity: sha512-TcvcmFHYmduVFZsR+87/cPldZEUz/uafyHIMGPdM8Go4TWg/SMB2tRILdDuUrEjgIgtUVskAGlPF4uIoiH/bEA==}
|
||||
applesauce-core@0.0.0-next-20250204175150:
|
||||
resolution: {integrity: sha512-mirjWA0QdyKMGWqtmCWCr8vi+BH68KdWVjuP1mMn636rz1JvbseS0IG/TkuClJaZenZOaPQIfO0n/pK8EzzYzQ==}
|
||||
|
||||
applesauce-core@0.10.0:
|
||||
resolution: {integrity: sha512-QMhUh4FIARcqY5soCB4Z8DIu+py0rYb28IgWT4gP9DLBGpDrY8lStXk7W1/46TLjEH97y0hbiXFK7kMCZ31oOQ==}
|
||||
|
||||
applesauce-factory@0.0.0-next-20250204170704:
|
||||
resolution: {integrity: sha512-5lA2aWaKibpt3jNQkNSJJWjopk9CNSWJzDOiM156fBG2Qhe8GzdN7fBiCPlm+iPCRogGyDCAHabSS+JnZB6LTA==}
|
||||
applesauce-factory@0.0.0-next-20250204175150:
|
||||
resolution: {integrity: sha512-zYIg/5bh7xaGS8CiniHS50aTeAbKT3CTeu4BDv4Sbygu86b8R9Xd9LjxW8MsVDNwn6dlj+OqfC8r0mlUK/icEg==}
|
||||
|
||||
applesauce-loaders@0.0.0-next-20250204170704:
|
||||
resolution: {integrity: sha512-7mYbE2qJA58A5cfdnpfQbdkohRvg6uhct+QieLlGOc/mNEmMxpA10GP9Wu7FprokWdCJEs0Pn7q7pobsJgPpKw==}
|
||||
applesauce-loaders@0.0.0-next-20250204175150:
|
||||
resolution: {integrity: sha512-z/cPftJvuIHWOaaPmq2YSQbkVIZ90K4QD7T+ZPh8IBZzlz2/tvdoidDBA174KXEVmBUn5fVE6Z1CAxrf/PBGDA==}
|
||||
|
||||
applesauce-net@0.10.0:
|
||||
resolution: {integrity: sha512-ZsAs/MkeGHiPZ2/a8lwP8lx/Eh+5Dot0qG4BLTAqjg4emP/RsiqW+hyc6v6QcVbdvuR0+hP1gka3+wWtiy/cTA==}
|
||||
|
||||
applesauce-react@0.0.0-next-20250204170704:
|
||||
resolution: {integrity: sha512-rHA9dO4k5UUeZESMtsrD0oGk7q26AFlpjLjWHBDKiFxRPsr5MusoKyW8X2fZOrN1fyNhgHD+lhCtesTWVUOU7Q==}
|
||||
applesauce-react@0.0.0-next-20250204175150:
|
||||
resolution: {integrity: sha512-J9ULdSeedSJXmFZtwECx+51I2cOVoCaOkWn7/HcFN4LiBtXuufx7viEZypWPv/nSdvpNK8Xb7jbOSuE75GmNWQ==}
|
||||
|
||||
applesauce-signers@0.0.0-next-20250204170704:
|
||||
resolution: {integrity: sha512-SZUA5uZQChBReIRj34t1y4ZQnV8LR96oHyMelnhAPFJXZT57wUfMJB7Z6KVkxbMHwo2SYUP6qi4MpkC6KQyGng==}
|
||||
applesauce-signers@0.0.0-next-20250204175150:
|
||||
resolution: {integrity: sha512-n7tzmEHCnyLOULG2aYYsil6cEkmI3St2f8if6Dshu92avTRi83/rpn6g8nIFxXu5iBLzuEJup9kXsZtVfdfDAg==}
|
||||
|
||||
arg@4.1.3:
|
||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
||||
@ -3033,8 +3033,8 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
hasBin: true
|
||||
|
||||
electron-to-chromium@1.5.91:
|
||||
resolution: {integrity: sha512-sNSHHyq048PFmZY4S90ax61q+gLCs0X0YmcOII9wG9S2XwbVr+h4VW2wWhnbp/Eys3cCwTxVF292W3qPaxIapQ==}
|
||||
electron-to-chromium@1.5.92:
|
||||
resolution: {integrity: sha512-BeHgmNobs05N1HMmMZ7YIuHfYBGlq/UmvlsTgg+fsbFs9xVMj+xJHFg19GN04+9Q+r8Xnh9LXqaYIyEWElnNgQ==}
|
||||
|
||||
elementtree@0.1.7:
|
||||
resolution: {integrity: sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==}
|
||||
@ -3667,8 +3667,8 @@ packages:
|
||||
resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-boolean-object@1.2.1:
|
||||
resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==}
|
||||
is-boolean-object@1.2.2:
|
||||
resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-callable@1.2.7:
|
||||
@ -4456,8 +4456,8 @@ packages:
|
||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
object-inspect@1.13.3:
|
||||
resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==}
|
||||
object-inspect@1.13.4:
|
||||
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
object-keys@1.1.1:
|
||||
@ -5135,8 +5135,8 @@ packages:
|
||||
engines: {node: '>=10.0.0'}
|
||||
hasBin: true
|
||||
|
||||
rollup@4.34.2:
|
||||
resolution: {integrity: sha512-sBDUoxZEaqLu9QeNalL8v3jw6WjPku4wfZGyTU7l7m1oC+rpRihXc/n/H+4148ZkGz5Xli8CHMns//fFGKvpIQ==}
|
||||
rollup@4.34.3:
|
||||
resolution: {integrity: sha512-ORCtU0UBJyiAIn9m0llUXJXAswG/68pZptCrqxHG7//Z2DDzAUeyyY5hqf4XrsGlUxscMr9GkQ2QI7KTLqeyPw==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
@ -5506,8 +5506,8 @@ packages:
|
||||
resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
terser@5.37.0:
|
||||
resolution: {integrity: sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==}
|
||||
terser@5.38.0:
|
||||
resolution: {integrity: sha512-a4GD5R1TjEeuCT6ZRiYMHmIf7okbCPEuhQET8bczV6FrQMMlFXA1n+G0KKjdlFCm3TEHV77GxfZB3vZSUQGFpg==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
@ -7888,7 +7888,7 @@ snapshots:
|
||||
dependencies:
|
||||
serialize-javascript: 6.0.2
|
||||
smob: 1.5.0
|
||||
terser: 5.37.0
|
||||
terser: 5.38.0
|
||||
optionalDependencies:
|
||||
rollup: 2.79.2
|
||||
|
||||
@ -7907,61 +7907,61 @@ snapshots:
|
||||
optionalDependencies:
|
||||
rollup: 2.79.2
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.34.2':
|
||||
'@rollup/rollup-android-arm-eabi@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm64@4.34.2':
|
||||
'@rollup/rollup-android-arm64@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.34.2':
|
||||
'@rollup/rollup-darwin-arm64@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.34.2':
|
||||
'@rollup/rollup-darwin-x64@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.34.2':
|
||||
'@rollup/rollup-freebsd-arm64@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.34.2':
|
||||
'@rollup/rollup-freebsd-x64@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.34.2':
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.34.2':
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.34.2':
|
||||
'@rollup/rollup-linux-arm64-gnu@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.34.2':
|
||||
'@rollup/rollup-linux-arm64-musl@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-loongarch64-gnu@4.34.2':
|
||||
'@rollup/rollup-linux-loongarch64-gnu@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.34.2':
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.34.2':
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.34.2':
|
||||
'@rollup/rollup-linux-s390x-gnu@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.34.2':
|
||||
'@rollup/rollup-linux-x64-gnu@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.34.2':
|
||||
'@rollup/rollup-linux-x64-musl@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.34.2':
|
||||
'@rollup/rollup-win32-arm64-msvc@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.34.2':
|
||||
'@rollup/rollup-win32-ia32-msvc@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.34.2':
|
||||
'@rollup/rollup-win32-x64-msvc@4.34.3':
|
||||
optional: true
|
||||
|
||||
'@sagold/json-pointer@5.1.2': {}
|
||||
@ -8329,14 +8329,14 @@ snapshots:
|
||||
|
||||
'@ungap/structured-clone@1.3.0': {}
|
||||
|
||||
'@vitejs/plugin-react@4.3.4(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0))':
|
||||
'@vitejs/plugin-react@4.3.4(vite@5.4.14(@types/node@22.13.1)(terser@5.38.0))':
|
||||
dependencies:
|
||||
'@babel/core': 7.26.7
|
||||
'@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.7)
|
||||
'@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.7)
|
||||
'@types/babel__core': 7.20.5
|
||||
react-refresh: 0.14.2
|
||||
vite: 5.4.14(@types/node@22.13.1)(terser@5.37.0)
|
||||
vite: 5.4.14(@types/node@22.13.1)(terser@5.38.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@ -8423,10 +8423,10 @@ snapshots:
|
||||
dependencies:
|
||||
entities: 2.2.0
|
||||
|
||||
applesauce-accounts@0.0.0-next-20250204170704(typescript@5.7.3):
|
||||
applesauce-accounts@0.0.0-next-20250204175150(typescript@5.7.3):
|
||||
dependencies:
|
||||
'@noble/hashes': 1.7.1
|
||||
applesauce-signers: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
applesauce-signers: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
nanoid: 5.0.9
|
||||
nostr-tools: 2.10.4(typescript@5.7.3)
|
||||
rxjs: 7.8.1
|
||||
@ -8434,13 +8434,13 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
applesauce-content@0.0.0-next-20250204170704(typescript@5.7.3):
|
||||
applesauce-content@0.0.0-next-20250204175150(typescript@5.7.3):
|
||||
dependencies:
|
||||
'@cashu/cashu-ts': 2.0.0-rc1
|
||||
'@types/hast': 3.0.4
|
||||
'@types/mdast': 4.0.4
|
||||
'@types/unist': 3.0.3
|
||||
applesauce-core: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
applesauce-core: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
mdast-util-find-and-replace: 3.0.2
|
||||
nostr-tools: 2.10.4(typescript@5.7.3)
|
||||
remark: 15.0.1
|
||||
@ -8451,7 +8451,7 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
applesauce-core@0.0.0-next-20250204170704(typescript@5.7.3):
|
||||
applesauce-core@0.0.0-next-20250204175150(typescript@5.7.3):
|
||||
dependencies:
|
||||
'@scure/base': 1.2.4
|
||||
debug: 4.4.0
|
||||
@ -8479,19 +8479,19 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
applesauce-factory@0.0.0-next-20250204170704(typescript@5.7.3):
|
||||
applesauce-factory@0.0.0-next-20250204175150(typescript@5.7.3):
|
||||
dependencies:
|
||||
applesauce-content: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
applesauce-core: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
applesauce-content: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
applesauce-core: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
nanoid: 5.0.9
|
||||
nostr-tools: 2.10.4(typescript@5.7.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
applesauce-loaders@0.0.0-next-20250204170704(typescript@5.7.3):
|
||||
applesauce-loaders@0.0.0-next-20250204175150(typescript@5.7.3):
|
||||
dependencies:
|
||||
applesauce-core: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
applesauce-core: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
nanoid: 5.0.9
|
||||
nostr-tools: 2.10.4(typescript@5.7.3)
|
||||
rx-nostr: 3.5.0
|
||||
@ -8510,12 +8510,12 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
applesauce-react@0.0.0-next-20250204170704(typescript@5.7.3):
|
||||
applesauce-react@0.0.0-next-20250204175150(typescript@5.7.3):
|
||||
dependencies:
|
||||
applesauce-accounts: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
applesauce-content: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
applesauce-core: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
applesauce-factory: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
applesauce-accounts: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
applesauce-content: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
applesauce-core: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
applesauce-factory: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
nostr-tools: 2.10.4(typescript@5.7.3)
|
||||
react: 18.3.1
|
||||
rxjs: 7.8.1
|
||||
@ -8523,12 +8523,12 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
applesauce-signers@0.0.0-next-20250204170704(typescript@5.7.3):
|
||||
applesauce-signers@0.0.0-next-20250204175150(typescript@5.7.3):
|
||||
dependencies:
|
||||
'@noble/hashes': 1.7.1
|
||||
'@noble/secp256k1': 1.7.1
|
||||
'@scure/base': 1.2.4
|
||||
applesauce-core: 0.0.0-next-20250204170704(typescript@5.7.3)
|
||||
applesauce-core: 0.0.0-next-20250204175150(typescript@5.7.3)
|
||||
debug: 4.4.0
|
||||
nanoid: 5.0.9
|
||||
nostr-tools: 2.10.4(typescript@5.7.3)
|
||||
@ -8753,7 +8753,7 @@ snapshots:
|
||||
browserslist@4.24.4:
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001697
|
||||
electron-to-chromium: 1.5.91
|
||||
electron-to-chromium: 1.5.92
|
||||
node-releases: 2.0.19
|
||||
update-browserslist-db: 1.1.2(browserslist@4.24.4)
|
||||
|
||||
@ -9450,7 +9450,7 @@ snapshots:
|
||||
dependencies:
|
||||
jake: 10.9.2
|
||||
|
||||
electron-to-chromium@1.5.91: {}
|
||||
electron-to-chromium@1.5.92: {}
|
||||
|
||||
elementtree@0.1.7:
|
||||
dependencies:
|
||||
@ -9535,7 +9535,7 @@ snapshots:
|
||||
is-typed-array: 1.1.15
|
||||
is-weakref: 1.1.1
|
||||
math-intrinsics: 1.1.0
|
||||
object-inspect: 1.13.3
|
||||
object-inspect: 1.13.4
|
||||
object-keys: 1.1.1
|
||||
object.assign: 4.1.7
|
||||
own-keys: 1.0.1
|
||||
@ -10194,7 +10194,7 @@ snapshots:
|
||||
dependencies:
|
||||
has-bigints: 1.1.0
|
||||
|
||||
is-boolean-object@1.2.1:
|
||||
is-boolean-object@1.2.2:
|
||||
dependencies:
|
||||
call-bound: 1.0.3
|
||||
has-tostringtag: 1.0.2
|
||||
@ -11156,7 +11156,7 @@ snapshots:
|
||||
|
||||
object-assign@4.1.1: {}
|
||||
|
||||
object-inspect@1.13.3: {}
|
||||
object-inspect@1.13.4: {}
|
||||
|
||||
object-keys@1.1.1: {}
|
||||
|
||||
@ -11911,29 +11911,29 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
rollup@4.34.2:
|
||||
rollup@4.34.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.6
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-android-arm-eabi': 4.34.2
|
||||
'@rollup/rollup-android-arm64': 4.34.2
|
||||
'@rollup/rollup-darwin-arm64': 4.34.2
|
||||
'@rollup/rollup-darwin-x64': 4.34.2
|
||||
'@rollup/rollup-freebsd-arm64': 4.34.2
|
||||
'@rollup/rollup-freebsd-x64': 4.34.2
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.34.2
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.34.2
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.34.2
|
||||
'@rollup/rollup-linux-arm64-musl': 4.34.2
|
||||
'@rollup/rollup-linux-loongarch64-gnu': 4.34.2
|
||||
'@rollup/rollup-linux-powerpc64le-gnu': 4.34.2
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.34.2
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.34.2
|
||||
'@rollup/rollup-linux-x64-gnu': 4.34.2
|
||||
'@rollup/rollup-linux-x64-musl': 4.34.2
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.34.2
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.34.2
|
||||
'@rollup/rollup-win32-x64-msvc': 4.34.2
|
||||
'@rollup/rollup-android-arm-eabi': 4.34.3
|
||||
'@rollup/rollup-android-arm64': 4.34.3
|
||||
'@rollup/rollup-darwin-arm64': 4.34.3
|
||||
'@rollup/rollup-darwin-x64': 4.34.3
|
||||
'@rollup/rollup-freebsd-arm64': 4.34.3
|
||||
'@rollup/rollup-freebsd-x64': 4.34.3
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.34.3
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.34.3
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.34.3
|
||||
'@rollup/rollup-linux-arm64-musl': 4.34.3
|
||||
'@rollup/rollup-linux-loongarch64-gnu': 4.34.3
|
||||
'@rollup/rollup-linux-powerpc64le-gnu': 4.34.3
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.34.3
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.34.3
|
||||
'@rollup/rollup-linux-x64-gnu': 4.34.3
|
||||
'@rollup/rollup-linux-x64-musl': 4.34.3
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.34.3
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.34.3
|
||||
'@rollup/rollup-win32-x64-msvc': 4.34.3
|
||||
fsevents: 2.3.3
|
||||
|
||||
rtl-css-js@1.16.1:
|
||||
@ -12084,27 +12084,27 @@ snapshots:
|
||||
side-channel-list@1.0.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
object-inspect: 1.13.3
|
||||
object-inspect: 1.13.4
|
||||
|
||||
side-channel-map@1.0.1:
|
||||
dependencies:
|
||||
call-bound: 1.0.3
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.2.7
|
||||
object-inspect: 1.13.3
|
||||
object-inspect: 1.13.4
|
||||
|
||||
side-channel-weakmap@1.0.2:
|
||||
dependencies:
|
||||
call-bound: 1.0.3
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.2.7
|
||||
object-inspect: 1.13.3
|
||||
object-inspect: 1.13.4
|
||||
side-channel-map: 1.0.1
|
||||
|
||||
side-channel@1.1.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
object-inspect: 1.13.3
|
||||
object-inspect: 1.13.4
|
||||
side-channel-list: 1.0.0
|
||||
side-channel-map: 1.0.1
|
||||
side-channel-weakmap: 1.0.2
|
||||
@ -12392,7 +12392,7 @@ snapshots:
|
||||
|
||||
term-size@2.2.1: {}
|
||||
|
||||
terser@5.37.0:
|
||||
terser@5.38.0:
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.6
|
||||
acorn: 8.14.0
|
||||
@ -12722,37 +12722,37 @@ snapshots:
|
||||
|
||||
vite-plugin-funding@0.1.0: {}
|
||||
|
||||
vite-plugin-pwa@0.21.1(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0):
|
||||
vite-plugin-pwa@0.21.1(vite@5.4.14(@types/node@22.13.1)(terser@5.38.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0):
|
||||
dependencies:
|
||||
debug: 4.4.0
|
||||
pretty-bytes: 6.1.1
|
||||
tinyglobby: 0.2.10
|
||||
vite: 5.4.14(@types/node@22.13.1)(terser@5.37.0)
|
||||
vite: 5.4.14(@types/node@22.13.1)(terser@5.38.0)
|
||||
workbox-build: 7.3.0(@types/babel__core@7.20.5)
|
||||
workbox-window: 7.3.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0)):
|
||||
vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.1)(terser@5.38.0)):
|
||||
dependencies:
|
||||
debug: 4.4.0
|
||||
globrex: 0.1.2
|
||||
tsconfck: 3.1.4(typescript@5.7.3)
|
||||
optionalDependencies:
|
||||
vite: 5.4.14(@types/node@22.13.1)(terser@5.37.0)
|
||||
vite: 5.4.14(@types/node@22.13.1)(terser@5.38.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
vite@5.4.14(@types/node@22.13.1)(terser@5.37.0):
|
||||
vite@5.4.14(@types/node@22.13.1)(terser@5.38.0):
|
||||
dependencies:
|
||||
esbuild: 0.21.5
|
||||
postcss: 8.5.1
|
||||
rollup: 4.34.2
|
||||
rollup: 4.34.3
|
||||
optionalDependencies:
|
||||
'@types/node': 22.13.1
|
||||
fsevents: 2.3.3
|
||||
terser: 5.37.0
|
||||
terser: 5.38.0
|
||||
|
||||
w3c-keyname@2.2.8: {}
|
||||
|
||||
@ -12790,7 +12790,7 @@ snapshots:
|
||||
which-boxed-primitive@1.1.1:
|
||||
dependencies:
|
||||
is-bigint: 1.1.0
|
||||
is-boolean-object: 1.2.1
|
||||
is-boolean-object: 1.2.2
|
||||
is-number-object: 1.1.1
|
||||
is-string: 1.1.1
|
||||
is-symbol: 1.1.1
|
||||
|
@ -1,243 +0,0 @@
|
||||
import { AbstractRelay } from "nostr-tools/abstract-relay";
|
||||
import { IConnectionPool } from "applesauce-net/connection";
|
||||
import dayjs from "dayjs";
|
||||
import { Subject, BehaviorSubject } from "rxjs";
|
||||
|
||||
import { logger } from "../helpers/debug";
|
||||
import { safeRelayUrl, validateRelayURL } from "../helpers/relay";
|
||||
import SuperMap from "./super-map";
|
||||
import verifyEventMethod from "../services/verify-event";
|
||||
import localSettings from "../services/local-settings";
|
||||
|
||||
export type Notice = {
|
||||
message: string;
|
||||
date: number;
|
||||
relay: AbstractRelay;
|
||||
};
|
||||
|
||||
export type RelayAuthMode = "always" | "ask" | "never";
|
||||
|
||||
export default class RelayPool implements IConnectionPool {
|
||||
log = logger.extend("RelayPool");
|
||||
|
||||
relays = new Map<string, AbstractRelay>();
|
||||
onRelayCreated = new Subject<AbstractRelay>();
|
||||
onRelayChallenge = new Subject<[AbstractRelay, string]>();
|
||||
|
||||
notices = new SuperMap<AbstractRelay, BehaviorSubject<Notice[]>>(() => new BehaviorSubject<Notice[]>([]));
|
||||
|
||||
connectionErrors = new SuperMap<AbstractRelay, Error[]>(() => []);
|
||||
connecting = new SuperMap<AbstractRelay, BehaviorSubject<boolean>>(() => new BehaviorSubject(false));
|
||||
|
||||
challenges = new SuperMap<AbstractRelay, BehaviorSubject<string | undefined>>(
|
||||
() => new BehaviorSubject<string | undefined>(undefined),
|
||||
);
|
||||
authForPublish = new SuperMap<AbstractRelay, BehaviorSubject<boolean | undefined>>(
|
||||
() => new BehaviorSubject<boolean | undefined>(undefined),
|
||||
);
|
||||
authForSubscribe = new SuperMap<AbstractRelay, BehaviorSubject<boolean | undefined>>(
|
||||
() => new BehaviorSubject<boolean | undefined>(undefined),
|
||||
);
|
||||
|
||||
authenticated = new SuperMap<AbstractRelay, BehaviorSubject<boolean>>(() => new BehaviorSubject(false));
|
||||
|
||||
getRelay(relayOrUrl: string | URL | AbstractRelay) {
|
||||
if (typeof relayOrUrl === "string") {
|
||||
const safeURL = safeRelayUrl(relayOrUrl);
|
||||
if (safeURL) {
|
||||
return this.relays.get(safeURL) || this.requestRelay(safeURL);
|
||||
} else return;
|
||||
} else if (relayOrUrl instanceof URL) {
|
||||
return this.relays.get(relayOrUrl.toString()) || this.requestRelay(relayOrUrl.toString());
|
||||
}
|
||||
|
||||
return relayOrUrl;
|
||||
}
|
||||
|
||||
// TODO: for now this is just a copy of
|
||||
getConnection(relayOrUrl: string | URL | AbstractRelay) {
|
||||
if (typeof relayOrUrl === "string") {
|
||||
const safeURL = safeRelayUrl(relayOrUrl);
|
||||
if (safeURL) {
|
||||
return this.relays.get(safeURL) || this.requestRelay(safeURL);
|
||||
} else {
|
||||
throw new Error(`Bad relay url ${relayOrUrl}`);
|
||||
}
|
||||
} else if (relayOrUrl instanceof URL) {
|
||||
return this.relays.get(relayOrUrl.toString()) || this.requestRelay(relayOrUrl.toString());
|
||||
}
|
||||
|
||||
return relayOrUrl;
|
||||
}
|
||||
|
||||
getRelays(urls?: Iterable<string | URL | AbstractRelay>) {
|
||||
if (urls) {
|
||||
const relays: AbstractRelay[] = [];
|
||||
for (const url of urls) {
|
||||
const relay = this.getRelay(url);
|
||||
if (relay) relays.push(relay);
|
||||
}
|
||||
return relays;
|
||||
}
|
||||
|
||||
return Array.from(this.relays.values());
|
||||
}
|
||||
|
||||
requestRelay(url: string | URL, connect = true) {
|
||||
url = validateRelayURL(url);
|
||||
|
||||
const key = url.toString();
|
||||
if (!this.relays.has(key)) {
|
||||
const r = new AbstractRelay(key, { verifyEvent: verifyEventMethod });
|
||||
r._onauth = (challenge) => this.handleRelayChallenge(r, challenge);
|
||||
r.onnotice = (notice) => this.handleRelayNotice(r, notice);
|
||||
|
||||
this.relays.set(key, r);
|
||||
this.onRelayCreated.next(r);
|
||||
}
|
||||
|
||||
const relay = this.relays.get(key) as AbstractRelay;
|
||||
if (connect && !relay.connected) this.requestConnect(relay);
|
||||
return relay;
|
||||
}
|
||||
|
||||
async waitForOpen(relayOrUrl: string | URL | AbstractRelay, quite = true) {
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return Promise.reject("Missing relay");
|
||||
|
||||
if (relay.connected) return true;
|
||||
|
||||
try {
|
||||
// if the relay is connecting, wait. otherwise request a connection
|
||||
// @ts-expect-error
|
||||
(await relay.connectionPromise) || this.requestConnect(relay, quite);
|
||||
return true;
|
||||
} catch (err) {
|
||||
if (quite) return false;
|
||||
else throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async requestConnect(relayOrUrl: string | URL | AbstractRelay, quite = true) {
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return;
|
||||
|
||||
if (!relay.connected) {
|
||||
this.connecting.get(relay).next(true);
|
||||
try {
|
||||
await relay.connect();
|
||||
this.connecting.get(relay).next(false);
|
||||
} catch (e) {
|
||||
e = e || new Error("Unknown error");
|
||||
if (e instanceof Error) {
|
||||
this.log(`Failed to connect to ${relay.url}`, e.message);
|
||||
this.connectionErrors.get(relay).push(e);
|
||||
}
|
||||
this.connecting.get(relay).next(false);
|
||||
if (!quite) throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getRelayAuthStorageKey(relayOrUrl: string | URL | AbstractRelay) {
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
return `${relay!.url}-auth-mode`;
|
||||
}
|
||||
getRelayAuthMode(relayOrUrl: string | URL | AbstractRelay): RelayAuthMode | undefined {
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return;
|
||||
|
||||
const defaultMode = localSettings.defaultAuthenticationMode.value;
|
||||
const mode = (localStorage.getItem(this.getRelayAuthStorageKey(relay)) as RelayAuthMode) ?? undefined;
|
||||
|
||||
return mode || defaultMode;
|
||||
}
|
||||
setRelayAuthMode(relayOrUrl: string | URL | AbstractRelay, mode: RelayAuthMode) {
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return;
|
||||
|
||||
localStorage.setItem(this.getRelayAuthStorageKey(relay), mode);
|
||||
}
|
||||
|
||||
pendingAuth = new Map<AbstractRelay, Promise<string | undefined>>();
|
||||
async authenticate(
|
||||
relayOrUrl: string | URL | AbstractRelay,
|
||||
sign: Parameters<AbstractRelay["auth"]>[0],
|
||||
quite = true,
|
||||
) {
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return;
|
||||
|
||||
const pending = this.pendingAuth.get(relay);
|
||||
if (pending) return pending;
|
||||
|
||||
if (this.getRelayAuthMode(relay) === "never") throw new Error("Auth disabled for relay");
|
||||
|
||||
if (!relay.connected) throw new Error("Not connected");
|
||||
|
||||
const promise = new Promise<string | undefined>(async (res) => {
|
||||
if (!relay) return;
|
||||
|
||||
try {
|
||||
const message = await relay.auth(sign);
|
||||
this.authenticated.get(relay).next(true);
|
||||
res(message);
|
||||
} catch (e) {
|
||||
e = e || new Error("Unknown error");
|
||||
if (e instanceof Error) {
|
||||
this.log(`Failed to authenticate to ${relay.url}`, e.message);
|
||||
}
|
||||
this.authenticated.get(relay).next(false);
|
||||
if (!quite) throw e;
|
||||
}
|
||||
|
||||
this.pendingAuth.delete(relay);
|
||||
});
|
||||
|
||||
this.pendingAuth.set(relay, promise);
|
||||
|
||||
return await promise;
|
||||
}
|
||||
|
||||
canSubscribe(relayOrUrl: string | URL | AbstractRelay) {
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return false;
|
||||
|
||||
return this.authForSubscribe.get(relay).value !== false;
|
||||
}
|
||||
|
||||
private handleRelayChallenge(relay: AbstractRelay, challenge: string) {
|
||||
this.onRelayChallenge.next([relay, challenge]);
|
||||
this.challenges.get(relay).next(challenge);
|
||||
}
|
||||
|
||||
handleRelayNotice(relay: AbstractRelay, message: string) {
|
||||
const subject = this.notices.get(relay);
|
||||
subject.next([...subject.value, { message, date: dayjs().unix(), relay }]);
|
||||
|
||||
if (message.includes("auth-required")) {
|
||||
const authForSubscribe = this.authForSubscribe.get(relay);
|
||||
if (!authForSubscribe.value) authForSubscribe.next(true);
|
||||
}
|
||||
}
|
||||
|
||||
disconnectFromUnused() {
|
||||
for (const [url, relay] of this.relays) {
|
||||
if (!relay.connected) continue;
|
||||
|
||||
// don't disconnect from authenticated relays
|
||||
if (this.authenticated.get(relay).value) continue;
|
||||
|
||||
let disconnect = false;
|
||||
|
||||
if (disconnect) {
|
||||
this.log(`No active processes using ${relay.url}, disconnecting`);
|
||||
relay.close();
|
||||
|
||||
// NOTE: fix nostr-tools not resetting the connection promise
|
||||
// @ts-expect-error
|
||||
relay.connectionPromise = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -52,13 +52,11 @@ type GifPickerProps = Omit<ModalProps, "children"> & { onSelect: (gif: NostrEven
|
||||
|
||||
export default function GifPickerModal({ onClose, isOpen, onSelect, ...props }: GifPickerProps) {
|
||||
const [search, setSearch] = useState<string>();
|
||||
const [searchRelayUrl, setSearchRelayUrl] = useState<string>();
|
||||
const [searchRelay, setSearchRelay] = useState<string>("");
|
||||
|
||||
const [list, setList] = useState<ListId>("global");
|
||||
const { selected, setSelected, filter, listId } = usePeopleListSelect(list, setList);
|
||||
|
||||
// const searchRelay = useSearchRelay(searchRelayUrl);
|
||||
|
||||
const [debounceSearch, setDebounceSearch] = useState<string>();
|
||||
useEffect(() => {
|
||||
setDebounceSearch(undefined);
|
||||
@ -75,8 +73,8 @@ export default function GifPickerModal({ onClose, isOpen, onSelect, ...props }:
|
||||
|
||||
const readRelays = useReadRelays();
|
||||
const { loader, timeline } = useTimelineLoader(
|
||||
[listId, "gifs", searchRelayUrl ?? "all", debounceSearch ?? "all"].join("-"),
|
||||
searchRelayUrl !== undefined ? [searchRelayUrl] : readRelays,
|
||||
[listId, "gifs", searchRelay ?? "all", debounceSearch ?? "all"].join("-"),
|
||||
!!searchRelay ? [searchRelay] : readRelays,
|
||||
debounceSearch !== undefined ? { ...baseFilter, search: debounceSearch } : baseFilter,
|
||||
);
|
||||
|
||||
@ -96,7 +94,7 @@ export default function GifPickerModal({ onClose, isOpen, onSelect, ...props }:
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
<SearchRelayPicker value={searchRelayUrl} onChange={(e) => setSearchRelayUrl(e.target.value)} />
|
||||
<SearchRelayPicker value={searchRelay} onChange={(e) => setSearchRelay(e.target.value)} />
|
||||
<Button type="submit">Search</Button>
|
||||
</Flex>
|
||||
<ButtonGroup size="xs">
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Select, SelectProps } from "@chakra-ui/react";
|
||||
import { useObservable } from "applesauce-react/hooks";
|
||||
|
||||
import { RelayAuthMode } from "../../classes/relay-pool";
|
||||
import localSettings from "../../services/local-settings";
|
||||
import { RelayAuthMode } from "../../services/authentication-signer";
|
||||
|
||||
export default function RelayAuthModeSelect({
|
||||
relay,
|
||||
|
@ -2,7 +2,7 @@ import { Select, SelectProps } from "@chakra-ui/react";
|
||||
import { useObservable } from "applesauce-react/hooks";
|
||||
|
||||
import localSettings from "../../services/local-settings";
|
||||
import { RelayAuthMode } from "../../classes/relay-pool";
|
||||
import { RelayAuthMode } from "../../services/authentication-signer";
|
||||
|
||||
export default function DefaultAuthModeSelect({ ...props }: Omit<SelectProps, "children" | "value" | "onChange">) {
|
||||
const defaultAuthenticationMode = useObservable(localSettings.defaultAuthenticationMode);
|
||||
|
@ -1,15 +1,14 @@
|
||||
import { getReplaceableIdentifier, getTagValue } from "applesauce-core/helpers";
|
||||
import { NostrEvent, isDTag } from "../../types/nostr-event";
|
||||
|
||||
export const SELF_REPORTED_KIND = 10066;
|
||||
export const MONITOR_METADATA_KIND = 10166;
|
||||
export const MONITOR_STATS_KIND = 30066;
|
||||
export const MONITOR_STATS_KIND = 30166;
|
||||
|
||||
export function getRelayURL(stats: NostrEvent) {
|
||||
if (stats.kind === SELF_REPORTED_KIND) return stats.tags.find((t) => t[0] === "r")?.[1];
|
||||
return stats.tags.find(isDTag)?.[1];
|
||||
return getReplaceableIdentifier(stats);
|
||||
}
|
||||
export function getNetwork(stats: NostrEvent) {
|
||||
return stats.tags.find((t) => t[0] === "n")?.[1];
|
||||
return getTagValue(stats, "n");
|
||||
}
|
||||
export function getSupportedNIPs(stats: NostrEvent) {
|
||||
return stats.tags.filter((t) => t[0] === "N" && t[1]).map((t) => t[1] && parseInt(t[1]));
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { ThemeTypings } from "@chakra-ui/react";
|
||||
import { Filter } from "nostr-tools";
|
||||
import { SubCloser, SubscribeManyParams } from "nostr-tools/abstract-pool";
|
||||
import { AbstractRelay, Subscription } from "nostr-tools/abstract-relay";
|
||||
import { ConnectionState } from "rx-nostr";
|
||||
|
||||
// NOTE: only use this for equality checks and querying
|
||||
@ -96,85 +94,6 @@ export function splitQueryByPubkeys(query: Filter, relayPubkeyMap: Record<string
|
||||
return filtersByRelay;
|
||||
}
|
||||
|
||||
// copied from nostr-tools, SimplePool#subscribeMany
|
||||
export function subscribeMany(relays: string[], filters: Filter[], params: SubscribeManyParams): SubCloser {
|
||||
const _knownIds = new Set<string>();
|
||||
const subs: Subscription[] = [];
|
||||
|
||||
// batch all EOSEs into a single
|
||||
const eosesReceived: boolean[] = [];
|
||||
let handleEose = (i: number) => {
|
||||
eosesReceived[i] = true;
|
||||
if (eosesReceived.filter((a) => a).length === relays.length) {
|
||||
params.oneose?.();
|
||||
handleEose = () => {};
|
||||
}
|
||||
};
|
||||
// batch all closes into a single
|
||||
const closesReceived: string[] = [];
|
||||
let handleClose = (i: number, reason: string) => {
|
||||
handleEose(i);
|
||||
closesReceived[i] = reason;
|
||||
if (closesReceived.filter((a) => a).length === relays.length) {
|
||||
params.onclose?.(closesReceived);
|
||||
handleClose = () => {};
|
||||
}
|
||||
};
|
||||
|
||||
const localAlreadyHaveEventHandler = (id: string) => {
|
||||
if (params.alreadyHaveEvent?.(id)) {
|
||||
return true;
|
||||
}
|
||||
const have = _knownIds.has(id);
|
||||
_knownIds.add(id);
|
||||
return have;
|
||||
};
|
||||
|
||||
// open a subscription in all given relays
|
||||
const allOpened = Promise.all(
|
||||
relays.map(validateRelayURL).map(async (url, i, arr) => {
|
||||
if (arr.indexOf(url) !== i) {
|
||||
// duplicate
|
||||
handleClose(i, "duplicate url");
|
||||
return;
|
||||
}
|
||||
|
||||
let relay: AbstractRelay;
|
||||
try {
|
||||
const { default: relayPoolService } = await import("../services/relay-pool");
|
||||
relay = relayPoolService.requestRelay(url);
|
||||
await relayPoolService.requestConnect(relay);
|
||||
// changed from nostr-tools
|
||||
// relay = await this.ensureRelay(url, {
|
||||
// connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1000) : undefined,
|
||||
// });
|
||||
} catch (err) {
|
||||
handleClose(i, (err as any)?.message || String(err));
|
||||
return;
|
||||
}
|
||||
|
||||
const subscription = relay.subscribe(filters, {
|
||||
...params,
|
||||
oneose: () => handleEose(i),
|
||||
onclose: (reason) => handleClose(i, reason),
|
||||
alreadyHaveEvent: localAlreadyHaveEventHandler,
|
||||
eoseTimeout: params.maxWait,
|
||||
});
|
||||
|
||||
subs.push(subscription);
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
async close() {
|
||||
await allOpened;
|
||||
subs.forEach((sub) => {
|
||||
sub.close();
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function getConnectionStateColor(state: ConnectionState): ThemeTypings["colorSchemes"] {
|
||||
switch (state) {
|
||||
case "initialized":
|
||||
|
@ -1,17 +1,15 @@
|
||||
import { useObservable } from "applesauce-react/hooks";
|
||||
import relayStatsService from "../services/relay-stats";
|
||||
import { useEffect } from "react";
|
||||
import { useStoreQuery } from "applesauce-react/hooks";
|
||||
import { ReplaceableQuery } from "applesauce-core/queries";
|
||||
|
||||
import { MONITOR_PUBKEY, MONITOR_RELAY } from "../services/relay-status-loader";
|
||||
import monitorRelayStatusLoader from "../services/relay-status-loader";
|
||||
import { MONITOR_STATS_KIND } from "../helpers/nostr/relay-stats";
|
||||
|
||||
export default function useRelayStats(relay: string) {
|
||||
const monitorSub = relayStatsService.requestMonitorStats(relay);
|
||||
const selfReportedSub = relayStatsService.requestSelfReported(relay);
|
||||
useEffect(() => {
|
||||
monitorRelayStatusLoader.next({ value: relay, relays: [MONITOR_RELAY] });
|
||||
}, [relay]);
|
||||
|
||||
const monitor = useObservable(monitorSub);
|
||||
const selfReported = useObservable(selfReportedSub);
|
||||
const stats = monitor || selfReported || undefined;
|
||||
|
||||
return {
|
||||
monitor,
|
||||
selfReported,
|
||||
stats,
|
||||
};
|
||||
return useStoreQuery(ReplaceableQuery, [MONITOR_STATS_KIND, MONITOR_PUBKEY, relay]);
|
||||
}
|
||||
|
@ -3,6 +3,19 @@ import { useActiveAccount } from "applesauce-react/hooks";
|
||||
import { DEFAULT_SEARCH_RELAYS } from "../const";
|
||||
import { getRelaysFromList } from "../helpers/nostr/lists";
|
||||
import useUserSearchRelayList from "./use-user-search-relay-list";
|
||||
import useCacheRelay from "./use-cache-relay";
|
||||
import { useRelayInfo } from "./use-relay-info";
|
||||
import { AbstractRelay } from "nostr-tools/abstract-relay";
|
||||
import WasmRelay from "../services/wasm-relay";
|
||||
|
||||
export function useCacheRelaySupportsSearch() {
|
||||
const cacheRelay = useCacheRelay();
|
||||
const { info: cacheRelayInfo } = useRelayInfo(cacheRelay instanceof AbstractRelay ? cacheRelay : undefined, true);
|
||||
return (
|
||||
cacheRelay instanceof WasmRelay ||
|
||||
(cacheRelay instanceof AbstractRelay && !!cacheRelayInfo?.supported_nips?.includes(50))
|
||||
);
|
||||
}
|
||||
|
||||
export default function useSearchRelays() {
|
||||
const account = useActiveAccount();
|
||||
|
@ -1,5 +0,0 @@
|
||||
import RelayPool from "../classes/relay-pool";
|
||||
|
||||
const relayPoolService = new RelayPool();
|
||||
|
||||
export default relayPoolService;
|
@ -1,99 +0,0 @@
|
||||
import _throttle from "lodash.throttle";
|
||||
import { Filter } from "nostr-tools";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import SuperMap from "../classes/super-map";
|
||||
import { NostrEvent } from "../types/nostr-event";
|
||||
import relayInfoService from "./relay-info";
|
||||
import { MONITOR_STATS_KIND, SELF_REPORTED_KIND, getRelayURL } from "../helpers/nostr/relay-stats";
|
||||
import relayPoolService from "./relay-pool";
|
||||
import { alwaysVerify } from "./verify-event";
|
||||
import { eventStore } from "./event-store";
|
||||
import { getCacheRelay } from "./cache-relay";
|
||||
|
||||
const MONITOR_PUBKEY = "151c17c9d234320cf0f189af7b761f63419fd6c38c6041587a008b7682e4640f";
|
||||
const MONITOR_RELAY = "wss://relay.nostr.watch";
|
||||
|
||||
class RelayStatsService {
|
||||
private selfReported = new SuperMap<string, BehaviorSubject<NostrEvent | null | undefined>>(
|
||||
() => new BehaviorSubject<NostrEvent | null | undefined>(undefined),
|
||||
);
|
||||
private monitorStats = new SuperMap<string, BehaviorSubject<NostrEvent | undefined>>(
|
||||
() => new BehaviorSubject<NostrEvent | undefined>(undefined),
|
||||
);
|
||||
|
||||
constructor() {
|
||||
// load all stats from cache and subscribe to future ones
|
||||
getCacheRelay()?.subscribe([{ kinds: [SELF_REPORTED_KIND, MONITOR_STATS_KIND] }], {
|
||||
onevent: (e) => this.handleEvent(e),
|
||||
});
|
||||
}
|
||||
|
||||
handleEvent(event: NostrEvent) {
|
||||
if (!alwaysVerify(event)) return;
|
||||
|
||||
// ignore all events before NIP-66 start date
|
||||
if (event.created_at < 1704196800) return;
|
||||
|
||||
const relay = getRelayURL(event);
|
||||
if (!relay) return;
|
||||
|
||||
eventStore.add(event);
|
||||
|
||||
const sub = this.monitorStats.get(relay);
|
||||
if (event.kind === SELF_REPORTED_KIND) {
|
||||
if (!sub.value || event.created_at > sub.value.created_at) sub.next(event);
|
||||
} else if (event.kind === MONITOR_STATS_KIND) {
|
||||
if (!sub.value || event.created_at > sub.value.created_at) sub.next(event);
|
||||
}
|
||||
}
|
||||
|
||||
requestSelfReported(relay: string) {
|
||||
const sub = this.selfReported.get(relay);
|
||||
|
||||
if (sub.value === undefined) {
|
||||
relayInfoService.getInfo(relay).then((info) => {
|
||||
if (!info.pubkey) return sub.next(null);
|
||||
|
||||
const filter: Filter = { kinds: [SELF_REPORTED_KIND], authors: [info.pubkey] };
|
||||
const subscription = relayPoolService
|
||||
.requestRelay(MONITOR_RELAY)
|
||||
.subscribe([filter], { onevent: (event) => this.handleEvent(event), oneose: () => subscription.close() });
|
||||
});
|
||||
}
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
requestMonitorStats(relay: string) {
|
||||
const sub = this.monitorStats.get(relay);
|
||||
|
||||
if (sub.value === undefined) {
|
||||
this.pendingMonitorStats.add(relay);
|
||||
this.throttleBatchRequestMonitorStats();
|
||||
}
|
||||
return sub;
|
||||
}
|
||||
|
||||
throttleBatchRequestMonitorStats = _throttle(this.batchRequestMonitorStats, 200);
|
||||
pendingMonitorStats = new Set<string>();
|
||||
private batchRequestMonitorStats() {
|
||||
const relays = Array.from(this.pendingMonitorStats);
|
||||
|
||||
const filter: Filter = { since: 1704196800, kinds: [MONITOR_STATS_KIND], "#d": relays, authors: [MONITOR_PUBKEY] };
|
||||
const sub = relayPoolService
|
||||
.requestRelay(MONITOR_RELAY)
|
||||
.subscribe([filter], { onevent: (event) => this.handleEvent(event), oneose: () => sub.close() });
|
||||
|
||||
this.pendingMonitorStats.clear();
|
||||
}
|
||||
}
|
||||
|
||||
const relayStatsService = new RelayStatsService();
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
//@ts-expect-error debug
|
||||
window.relayStatsService = relayStatsService;
|
||||
}
|
||||
|
||||
export default relayStatsService;
|
21
src/services/relay-status-loader.ts
Normal file
21
src/services/relay-status-loader.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { MONITOR_STATS_KIND } from "../helpers/nostr/relay-stats";
|
||||
import { TagValueLoader } from "applesauce-loaders";
|
||||
import rxNostr from "./rx-nostr";
|
||||
import { eventStore } from "./event-store";
|
||||
|
||||
export const MONITOR_PUBKEY = "151c17c9d234320cf0f189af7b761f63419fd6c38c6041587a008b7682e4640f";
|
||||
export const MONITOR_RELAY = "wss://relay.nostr.watch/";
|
||||
|
||||
const monitorRelayStatusLoader = new TagValueLoader(rxNostr, "d", {
|
||||
name: "relay-monitor",
|
||||
kinds: [MONITOR_STATS_KIND],
|
||||
authors: [MONITOR_PUBKEY],
|
||||
since: 1704196800,
|
||||
});
|
||||
|
||||
// start the loader and send all events to the event store
|
||||
monitorRelayStatusLoader.subscribe((packet) => {
|
||||
eventStore.add(packet.event, packet.from);
|
||||
});
|
||||
|
||||
export default monitorRelayStatusLoader;
|
@ -2,6 +2,7 @@ import { NostrEvent } from "nostr-tools";
|
||||
import { Box, Button, Flex, Heading, Image, Spinner, Text, useDisclosure } from "@chakra-ui/react";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import { ThreadIcon } from "../../components/icons";
|
||||
import useParamsAddressPointer from "../../hooks/use-params-address-pointer";
|
||||
import useReplaceableEvent from "../../hooks/use-replaceable-event";
|
||||
import VerticalPageLayout from "../../components/vertical-page-layout";
|
||||
@ -24,7 +25,6 @@ import BookmarkEventButton from "../../components/note/bookmark-event";
|
||||
import EventQuoteButton from "../../components/note/event-quote-button";
|
||||
import { GenericComments } from "../../components/comment/generic-comments";
|
||||
import GenericCommentForm from "../../components/comment/generic-comment-form";
|
||||
import { ThreadIcon } from "../../components/icons";
|
||||
|
||||
function ArticlePage({ article }: { article: NostrEvent }) {
|
||||
const image = getArticleImage(article);
|
||||
|
@ -45,7 +45,7 @@ export const Metadata = ({ name, children }: { name: string } & PropsWithChildre
|
||||
|
||||
export function RelayMetadata({ url, extended }: { url: string; extended?: boolean }) {
|
||||
const { info } = useRelayInfo(url);
|
||||
const { stats } = useRelayStats(url);
|
||||
const stats = useRelayStats(url);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
|
@ -1,32 +1,18 @@
|
||||
import { forwardRef } from "react";
|
||||
import { Select, SelectProps } from "@chakra-ui/react";
|
||||
import { AbstractRelay } from "nostr-tools/abstract-relay";
|
||||
|
||||
import useSearchRelays from "../../../hooks/use-search-relays";
|
||||
import { useRelayInfo } from "../../../hooks/use-relay-info";
|
||||
import WasmRelay from "../../../services/wasm-relay";
|
||||
import relayPoolService from "../../../services/relay-pool";
|
||||
import useCacheRelay from "../../../hooks/use-cache-relay";
|
||||
import useSearchRelays, { useCacheRelaySupportsSearch } from "../../../hooks/use-search-relays";
|
||||
|
||||
export function useSearchRelay(relay?: string) {
|
||||
const cacheRelay = useCacheRelay();
|
||||
if (!relay) return undefined;
|
||||
if (relay === "local") return cacheRelay as AbstractRelay;
|
||||
else return relayPoolService.requestRelay(relay);
|
||||
}
|
||||
|
||||
const SearchRelayPicker = forwardRef<any, Omit<SelectProps, "children">>(({ value, onChange, ...props }, ref) => {
|
||||
const SearchRelayPicker = forwardRef<
|
||||
any,
|
||||
Omit<SelectProps, "children" | "value"> & { value?: string; showLocal?: boolean }
|
||||
>(({ value, onChange, showLocal, ...props }, ref) => {
|
||||
const searchRelays = useSearchRelays();
|
||||
const cacheRelay = useCacheRelay();
|
||||
|
||||
const { info: cacheRelayInfo } = useRelayInfo(cacheRelay instanceof AbstractRelay ? cacheRelay : undefined, true);
|
||||
const localSearchSupported =
|
||||
cacheRelay instanceof WasmRelay ||
|
||||
(cacheRelay instanceof AbstractRelay && !!cacheRelayInfo?.supported_nips?.includes(50));
|
||||
const localSearchSupported = useCacheRelaySupportsSearch();
|
||||
|
||||
return (
|
||||
<Select ref={ref} w="auto" value={value} onChange={onChange} {...props}>
|
||||
{localSearchSupported && <option value="local">Local Relay</option>}
|
||||
{showLocal && localSearchSupported && <option value="">Local Relay</option>}
|
||||
{searchRelays.map((url) => (
|
||||
<option key={url} value={url}>
|
||||
{url}
|
||||
|
@ -1,50 +1,48 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Filter, kinds, NostrEvent } from "nostr-tools";
|
||||
import { AbstractRelay, Subscription, SubscriptionParams } from "nostr-tools/abstract-relay";
|
||||
import { Alert, AlertDescription, AlertIcon, AlertTitle, Heading, Spinner, Text } from "@chakra-ui/react";
|
||||
import { map, Observable } from "rxjs";
|
||||
import { LRU } from "applesauce-core/helpers";
|
||||
|
||||
import relayPoolService from "../../../services/relay-pool";
|
||||
import ProfileSearchResults from "./profile-results";
|
||||
import NoteSearchResults from "./note-results";
|
||||
import ArticleSearchResults from "./article-results";
|
||||
import { eventStore } from "../../../services/event-store";
|
||||
import { createRxOneshotReq, EventPacket } from "rx-nostr";
|
||||
import rxNostr from "../../../services/rx-nostr";
|
||||
import { cacheRequest } from "../../../services/cache-relay";
|
||||
|
||||
function createSearchAction(url: string | AbstractRelay) {
|
||||
let sub: Subscription | undefined = undefined;
|
||||
export function createSearchAction(relays?: string[]): (filters: Filter[]) => Observable<EventPacket> {
|
||||
return (filters: Filter[]) => {
|
||||
// search local
|
||||
if (!relays || relays.length === 0)
|
||||
return cacheRequest(filters).pipe(
|
||||
map(
|
||||
(event) =>
|
||||
({
|
||||
event,
|
||||
from: "",
|
||||
subId: "cache",
|
||||
type: "EVENT",
|
||||
message: ["EVENT", "cache", event],
|
||||
}) as EventPacket,
|
||||
),
|
||||
);
|
||||
|
||||
let running = true;
|
||||
const search = async (filters: Filter[], params: Partial<SubscriptionParams>) => {
|
||||
running = true;
|
||||
const relay = typeof url === "string" ? await relayPoolService.requestRelay(url, false) : url;
|
||||
await relayPoolService.requestConnect(relay);
|
||||
|
||||
sub = relay.subscribe(filters, {
|
||||
onevent: (event) => running && params.onevent?.(event),
|
||||
oneose: () => {
|
||||
sub?.close();
|
||||
params.oneose?.();
|
||||
},
|
||||
onclose: params.onclose,
|
||||
});
|
||||
// search remote
|
||||
const req = createRxOneshotReq({ filters });
|
||||
return rxNostr.use(req, { on: { relays } });
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
running = false;
|
||||
if (sub) sub.close();
|
||||
};
|
||||
|
||||
return { search, cancel, relay: url };
|
||||
}
|
||||
|
||||
const searchCache = new LRU<NostrEvent[]>(10);
|
||||
|
||||
export default function SearchResults({ query, relay }: { query: string; relay: string | AbstractRelay }) {
|
||||
export default function SearchResults({ query, relay }: { query: string; relay: string }) {
|
||||
const [results, setResults] = useState<NostrEvent[]>([]);
|
||||
|
||||
const [searching, setSearching] = useState(false);
|
||||
const [error, setError] = useState<Error>();
|
||||
const search = useMemo(() => createSearchAction(relay), [relay]);
|
||||
const search = useMemo(() => createSearchAction(relay ? [relay] : []), [relay]);
|
||||
|
||||
useEffect(() => {
|
||||
if (query.length < 3) return;
|
||||
@ -59,22 +57,20 @@ export default function SearchResults({ query, relay }: { query: string; relay:
|
||||
// run a new search
|
||||
setResults([]);
|
||||
setSearching(true);
|
||||
search
|
||||
.search([{ search: query, kinds: [kinds.Metadata, kinds.ShortTextNote, kinds.LongFormArticle], limit: 200 }], {
|
||||
onevent: (event) => {
|
||||
event = eventStore.add(event, typeof search.relay === "string" ? search.relay : search.relay.url);
|
||||
|
||||
setResults((arr) => {
|
||||
const newArr = [...arr, event];
|
||||
searchCache.set(query + relay, newArr);
|
||||
return newArr;
|
||||
});
|
||||
},
|
||||
oneose: () => setSearching(false),
|
||||
})
|
||||
.catch((err) => setError(err));
|
||||
const sub = search([
|
||||
{ search: query, kinds: [kinds.Metadata, kinds.ShortTextNote, kinds.LongFormArticle], limit: 200 },
|
||||
]).subscribe((packet) => {
|
||||
const event = eventStore.add(packet.event, packet.from);
|
||||
|
||||
return () => search.cancel();
|
||||
setResults((arr) => {
|
||||
const newArr = [...arr, event];
|
||||
searchCache.set(query + relay, newArr);
|
||||
return newArr;
|
||||
});
|
||||
});
|
||||
|
||||
return () => sub.unsubscribe();
|
||||
}
|
||||
}, [query, search]);
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo } from "react";
|
||||
import { ButtonGroup, Flex, IconButton, Input, Select } from "@chakra-ui/react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { ButtonGroup, Flex, IconButton, Input } from "@chakra-ui/react";
|
||||
import { useNavigate, useSearchParams, Link as RouterLink } from "react-router-dom";
|
||||
import { AbstractRelay } from "nostr-tools/abstract-relay";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
import { safeDecode } from "../../helpers/nip19";
|
||||
@ -12,44 +11,32 @@ import PeopleListProvider from "../../providers/local/people-list-provider";
|
||||
import { useBreakpointValue } from "../../providers/global/breakpoint-provider";
|
||||
import QRCodeScannerButton from "../../components/qr-code/qr-code-scanner-button";
|
||||
import SearchResults from "./components/search-results";
|
||||
import useSearchRelays from "../../hooks/use-search-relays";
|
||||
import { useRelayInfo } from "../../hooks/use-relay-info";
|
||||
import WasmRelay from "../../services/wasm-relay";
|
||||
import relayPoolService from "../../services/relay-pool";
|
||||
import useSearchRelays, { useCacheRelaySupportsSearch } from "../../hooks/use-search-relays";
|
||||
import useCacheRelay from "../../hooks/use-cache-relay";
|
||||
import SearchRelayPicker from "./components/search-relay-picker";
|
||||
|
||||
export function SearchPage() {
|
||||
const cacheRelay = useCacheRelay();
|
||||
const navigate = useNavigate();
|
||||
const searchRelays = useSearchRelays();
|
||||
const { info: cacheRelayInfo } = useRelayInfo(cacheRelay instanceof AbstractRelay ? cacheRelay : undefined, true);
|
||||
const localSearchSupported =
|
||||
cacheRelay instanceof WasmRelay ||
|
||||
(cacheRelay instanceof AbstractRelay && !!cacheRelayInfo?.supported_nips?.includes(50));
|
||||
const localSearchSupported = useCacheRelaySupportsSearch();
|
||||
|
||||
const autoFocusSearch = useBreakpointValue({ base: false, lg: true });
|
||||
|
||||
const [params, setParams] = useSearchParams();
|
||||
const searchQuery = params.get("q") || "";
|
||||
|
||||
const relayURL = params.get("relay");
|
||||
const searchRelay = useMemo(() => {
|
||||
if (relayURL === "local") return cacheRelay;
|
||||
else if (relayURL) return relayPoolService.requestRelay(relayURL);
|
||||
else if (localSearchSupported) return cacheRelay;
|
||||
else return relayPoolService.requestRelay(searchRelays[0]);
|
||||
}, [relayURL, localSearchSupported, cacheRelay, searchRelays[0]]);
|
||||
const relay = params.get("relay") ?? (localSearchSupported ? "" : undefined) ?? searchRelays[0] ?? "";
|
||||
|
||||
const { register, handleSubmit, setValue } = useForm({
|
||||
defaultValues: { query: searchQuery, relay: searchRelay === cacheRelay ? "local" : searchRelay?.url },
|
||||
defaultValues: { query: searchQuery, relay },
|
||||
mode: "all",
|
||||
});
|
||||
|
||||
// reset the relay when the search relay changes
|
||||
useEffect(
|
||||
() => setValue("relay", searchRelay === cacheRelay ? "local" : searchRelay?.url),
|
||||
[searchRelay, cacheRelay],
|
||||
);
|
||||
// when the relay changes update the form
|
||||
useEffect(() => {
|
||||
setValue("relay", relay);
|
||||
}, [relay]);
|
||||
|
||||
const handleSearchText = (text: string) => {
|
||||
const cleanText = text.trim();
|
||||
@ -78,11 +65,12 @@ export function SearchPage() {
|
||||
const newParams = new URLSearchParams(params);
|
||||
newParams.set("q", values.query);
|
||||
if (values.relay) newParams.set("relay", values.relay);
|
||||
else newParams.delete("relay");
|
||||
setParams(newParams);
|
||||
}
|
||||
});
|
||||
|
||||
const shouldSearch = searchQuery && searchRelay;
|
||||
const shouldSearch = !!searchQuery && (!!relay || (localSearchSupported && !!cacheRelay));
|
||||
|
||||
return (
|
||||
<VerticalPageLayout>
|
||||
@ -106,14 +94,7 @@ export function SearchPage() {
|
||||
{...register("query", { required: true, minLength: 3 })}
|
||||
autoComplete="off"
|
||||
/>
|
||||
<Select w="auto" {...register("relay")}>
|
||||
{localSearchSupported && <option value="local">Local Relay</option>}
|
||||
{searchRelays.map((url) => (
|
||||
<option key={url} value={url}>
|
||||
{url}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
<SearchRelayPicker {...register("relay")} showLocal />
|
||||
<ButtonGroup>
|
||||
<IconButton type="submit" aria-label="Search" icon={<SearchIcon boxSize={5} />} colorScheme="primary" />
|
||||
<IconButton
|
||||
@ -127,7 +108,7 @@ export function SearchPage() {
|
||||
</Flex>
|
||||
|
||||
<Flex direction="column" gap="2">
|
||||
{shouldSearch ? <SearchResults relay={searchRelay as AbstractRelay} query={searchQuery} /> : null}
|
||||
{shouldSearch ? <SearchResults relay={relay} query={searchQuery} /> : null}
|
||||
</Flex>
|
||||
</VerticalPageLayout>
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { memo, useCallback, useRef, useState } from "react";
|
||||
import { memo, useCallback, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
@ -9,23 +9,20 @@ import {
|
||||
ButtonGroup,
|
||||
CloseButton,
|
||||
Flex,
|
||||
Heading,
|
||||
IconButton,
|
||||
Switch,
|
||||
Text,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import { NostrEvent } from "nostr-tools";
|
||||
import { AbstractRelay, Subscription } from "nostr-tools/abstract-relay";
|
||||
import { useLocalStorage } from "react-use";
|
||||
import { Subscription as IDBSubscription } from "nostr-idb";
|
||||
import _throttle from "lodash.throttle";
|
||||
import stringify from "json-stringify-deterministic";
|
||||
import { useLocation, useSearchParams } from "react-router-dom";
|
||||
import { safeParse } from "applesauce-core/helpers/json";
|
||||
import { createRxForwardReq, EventPacket } from "rx-nostr";
|
||||
import { Subscription } from "rxjs";
|
||||
|
||||
import VerticalPageLayout from "../../../components/vertical-page-layout";
|
||||
import BackButton from "../../../components/router/back-button";
|
||||
import Play from "../../../components/icons/play";
|
||||
import ClockRewind from "../../../components/icons/clock-rewind";
|
||||
import HistoryDrawer from "./history-drawer";
|
||||
@ -35,10 +32,12 @@ import HelpModal from "./help-modal";
|
||||
import HelpCircle from "../../../components/icons/help-circle";
|
||||
import { DownloadIcon, ShareIcon } from "../../../components/icons";
|
||||
import { RelayUrlInput } from "../../../components/relay-url-input";
|
||||
import { validateRelayURL } from "../../../helpers/relay";
|
||||
import FilterEditor from "./filter-editor";
|
||||
import relayPoolService from "../../../services/relay-pool";
|
||||
import useCacheRelay from "../../../hooks/use-cache-relay";
|
||||
import SimpleView from "../../../components/layout/presets/simple-view";
|
||||
import { cacheRequest } from "../../../services/cache-relay";
|
||||
import { eventStore } from "../../../services/event-store";
|
||||
import rxNostr from "../../../services/rx-nostr";
|
||||
|
||||
const EventTimeline = memo(({ events }: { events: NostrEvent[] }) => {
|
||||
return (
|
||||
@ -58,10 +57,9 @@ export default function EventConsoleView() {
|
||||
const [history, setHistory] = useLocalStorage<string[]>("console-history", []);
|
||||
const helpModal = useDisclosure();
|
||||
const queryRelay = useDisclosure({ defaultIsOpen: params.has("relay") });
|
||||
const [relayURL, setRelayURL] = useState(params.get("relay") || "");
|
||||
const [relay, setRelay] = useState<AbstractRelay | null>(null);
|
||||
const [relay, setRelay] = useState(params.get("relay") || "");
|
||||
|
||||
const [sub, setSub] = useState<Subscription | IDBSubscription | null>(null);
|
||||
const [sub, setSub] = useState<Subscription | null>(null);
|
||||
|
||||
const [query, setQuery] = useState(() => {
|
||||
if (params.has("filter") || location.state?.filter) {
|
||||
@ -82,54 +80,54 @@ export default function EventConsoleView() {
|
||||
const [events, setEvents] = useState<NostrEvent[]>([]);
|
||||
const loadEvents = useCallback(async () => {
|
||||
try {
|
||||
if (queryRelay.isOpen && !relayURL) throw new Error("Must set relay");
|
||||
|
||||
const filter = await processFilter(JSON.parse(query));
|
||||
setLoading(true);
|
||||
setHistory((arr) => (arr ? (!arr.includes(query) ? [query, ...arr] : arr) : [query]));
|
||||
setEvents([]);
|
||||
setError("");
|
||||
|
||||
if (sub) sub.close();
|
||||
// stop previous subscription
|
||||
if (sub) sub.unsubscribe();
|
||||
|
||||
const buffer: NostrEvent[] = [];
|
||||
const flush = _throttle(
|
||||
() => {
|
||||
setEvents([...buffer]);
|
||||
},
|
||||
1000 / 10,
|
||||
{ trailing: true },
|
||||
);
|
||||
|
||||
const handleEvent = (event: NostrEvent) => {
|
||||
event = eventStore.add(event);
|
||||
buffer.push(event);
|
||||
flush();
|
||||
};
|
||||
const handleEventPacket = (packet: EventPacket) => {
|
||||
const event = eventStore.add(packet.event, packet.from);
|
||||
buffer.push(event);
|
||||
flush();
|
||||
};
|
||||
|
||||
if (!cacheRelay) throw new Error("Local relay disabled");
|
||||
let r = cacheRelay!;
|
||||
if (queryRelay.isOpen) {
|
||||
const url = validateRelayURL(relayURL);
|
||||
if (!relay || relay.url !== url.toString()) {
|
||||
r = await relayPoolService.requestRelay(url);
|
||||
await relayPoolService.requestConnect(r);
|
||||
setRelay(r as AbstractRelay);
|
||||
} else r = relay;
|
||||
if (!relay) throw new Error("Must set relay");
|
||||
|
||||
// query remote relay
|
||||
const req = createRxForwardReq();
|
||||
const sub = rxNostr.use(req, { on: { relays: [relay] } }).subscribe(handleEventPacket);
|
||||
req.emit([filter]);
|
||||
setSub(sub);
|
||||
} else {
|
||||
if (relay) setRelay(null);
|
||||
// query cache relay
|
||||
if (!cacheRelay) throw new Error("Local relay disabled");
|
||||
const sub = cacheRequest([filter]).subscribe(handleEvent);
|
||||
setSub(sub);
|
||||
}
|
||||
|
||||
await new Promise<void>((res) => {
|
||||
const buffer: NostrEvent[] = [];
|
||||
const flush = _throttle(() => setEvents([...buffer]), 1000 / 10, { trailing: true });
|
||||
|
||||
setError("");
|
||||
|
||||
const s = r.subscribe([filter], {
|
||||
onevent: (e) => {
|
||||
buffer.push(e);
|
||||
flush();
|
||||
},
|
||||
oneose: () => {
|
||||
setEvents([...buffer]);
|
||||
res();
|
||||
},
|
||||
onclose: (reason) => {
|
||||
if (!buffer.length) setError(reason);
|
||||
},
|
||||
});
|
||||
setSub(s);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) setError(e.message);
|
||||
}
|
||||
setLoading(false);
|
||||
}, [queryRelay.isOpen, query, relayURL, relay, sub, cacheRelay]);
|
||||
}, [queryRelay.isOpen, query, relay, relay, sub, cacheRelay]);
|
||||
|
||||
const submitRef = useRef(loadEvents);
|
||||
submitRef.current = loadEvents;
|
||||
@ -146,47 +144,57 @@ export default function EventConsoleView() {
|
||||
const updateSharedURL = () => {
|
||||
const p = new URLSearchParams(params);
|
||||
p.set("filter", query);
|
||||
p.set("relay", relayURL);
|
||||
if (relay) p.set("relay", relay);
|
||||
setParams(p, { replace: true });
|
||||
};
|
||||
|
||||
return (
|
||||
<VerticalPageLayout>
|
||||
<Flex gap="2" alignItems="center" wrap="wrap">
|
||||
<BackButton size="sm" />
|
||||
<Heading size="md">Event Console</Heading>
|
||||
<SimpleView
|
||||
title="Event Console"
|
||||
actions={
|
||||
<>
|
||||
<ButtonGroup ml="auto">
|
||||
<IconButton icon={<HelpCircle />} aria-label="Help" title="Help" size="sm" onClick={helpModal.onOpen} />
|
||||
<IconButton icon={<ShareIcon />} aria-label="Share" size="sm" onClick={updateSharedURL} />
|
||||
<IconButton
|
||||
icon={<ClockRewind />}
|
||||
aria-label="History"
|
||||
title="History"
|
||||
size="sm"
|
||||
onClick={historyDrawer.onOpen}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Flex gap="2" wrap="wrap" alignItems="center">
|
||||
<Switch size="sm" isChecked={queryRelay.isOpen} onChange={queryRelay.onToggle}>
|
||||
Query Relay
|
||||
</Switch>
|
||||
{queryRelay.isOpen && (
|
||||
<RelayUrlInput
|
||||
size="sm"
|
||||
borderRadius="md"
|
||||
w="xs"
|
||||
value={relayURL}
|
||||
onChange={(e) => setRelayURL(e.target.value)}
|
||||
/>
|
||||
<RelayUrlInput size="sm" borderRadius="md" w="xs" value={relay} onChange={(e) => setRelay(e.target.value)} />
|
||||
)}
|
||||
<ButtonGroup ml="auto">
|
||||
<IconButton icon={<HelpCircle />} aria-label="Help" title="Help" size="sm" onClick={helpModal.onOpen} />
|
||||
{queryRelay.isOpen && (
|
||||
<IconButton icon={<ShareIcon />} aria-label="Share" size="sm" onClick={updateSharedURL} />
|
||||
</Flex>
|
||||
<FilterEditor value={query} onChange={setQuery} onRun={submitCode} />
|
||||
|
||||
<Flex gap="2" alignItems="center">
|
||||
<Text>{events.length} events</Text>
|
||||
{sub && <Text color="green.500">Subscribed</Text>}
|
||||
<ButtonGroup ms="auto" size="sm">
|
||||
{events.length > 0 && (
|
||||
<IconButton
|
||||
aria-label="Download Events"
|
||||
title="Download Events"
|
||||
icon={<DownloadIcon />}
|
||||
onClick={downloadEvents}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
icon={<ClockRewind />}
|
||||
aria-label="History"
|
||||
title="History"
|
||||
size="sm"
|
||||
onClick={historyDrawer.onOpen}
|
||||
/>
|
||||
<Button colorScheme="primary" onClick={loadEvents} isLoading={loading} leftIcon={<Play />} size="sm">
|
||||
<Button colorScheme="primary" onClick={loadEvents} isLoading={loading} leftIcon={<Play />}>
|
||||
Run
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</Flex>
|
||||
|
||||
<FilterEditor value={query} onChange={setQuery} onRun={submitCode} />
|
||||
|
||||
{error && (
|
||||
<Alert status="error">
|
||||
<AlertIcon />
|
||||
@ -205,23 +213,6 @@ export default function EventConsoleView() {
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Flex gap="2">
|
||||
<Text>{events.length} events</Text>
|
||||
{sub && (
|
||||
<Text color="green.500" ml="auto">
|
||||
Subscribed
|
||||
</Text>
|
||||
)}
|
||||
{events.length > 0 && (
|
||||
<IconButton
|
||||
aria-label="Download Events"
|
||||
title="Download Events"
|
||||
icon={<DownloadIcon />}
|
||||
onClick={downloadEvents}
|
||||
size="xs"
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
<Box>
|
||||
<EventTimeline events={events} />
|
||||
</Box>
|
||||
@ -238,6 +229,6 @@ export default function EventConsoleView() {
|
||||
/>
|
||||
|
||||
<HelpModal isOpen={helpModal.isOpen} onClose={helpModal.onClose} />
|
||||
</VerticalPageLayout>
|
||||
</SimpleView>
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { Box, Button, Flex, Input, Text } from "@chakra-ui/react";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import ForceGraph, { LinkObject, NodeObject } from "react-force-graph-3d";
|
||||
import { Filter, kinds } from "nostr-tools";
|
||||
import dayjs from "dayjs";
|
||||
import { getProfileContent } from "applesauce-core/helpers";
|
||||
import { useStoreQuery } from "applesauce-react/hooks";
|
||||
import { TimelineQuery } from "applesauce-core/queries";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useDebounce } from "react-use";
|
||||
import { useThrottle } from "react-use";
|
||||
import {
|
||||
Group,
|
||||
Mesh,
|
||||
@ -16,6 +18,7 @@ import {
|
||||
SpriteMaterial,
|
||||
TextureLoader,
|
||||
} from "three";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import { useActiveAccount } from "applesauce-react/hooks";
|
||||
import RequireActiveAccount from "../../components/router/require-active-account";
|
||||
@ -25,12 +28,9 @@ import useUserProfile from "../../hooks/use-user-profile";
|
||||
import { isPTag } from "../../types/nostr-event";
|
||||
import { ChevronLeftIcon } from "../../components/icons";
|
||||
import { useReadRelays } from "../../hooks/use-client-relays";
|
||||
import { subscribeMany } from "../../helpers/relay";
|
||||
import useUserProfiles from "../../hooks/use-user-profiles";
|
||||
import { eventStore } from "../../services/event-store";
|
||||
import { getProfileContent } from "applesauce-core/helpers";
|
||||
import { useStoreQuery } from "applesauce-react/hooks";
|
||||
import { TimelineQuery } from "applesauce-core/queries";
|
||||
import useForwardSubscription from "../../hooks/use-forward-subscription";
|
||||
|
||||
type NodeType = { id: string; image?: string; name?: string };
|
||||
|
||||
@ -48,27 +48,20 @@ function NetworkDMGraphPage() {
|
||||
const [until, setUntil] = useState(dayjs().unix());
|
||||
const [since, setSince] = useState(dayjs().subtract(1, "week").unix());
|
||||
|
||||
const [fetchData] = useDebounce(
|
||||
() => {
|
||||
if (!contacts) return;
|
||||
|
||||
const filter: Filter = {
|
||||
const filters = useMemo<Filter[]>(
|
||||
() => [
|
||||
{
|
||||
authors: contactsPubkeys,
|
||||
kinds: [kinds.EncryptedDirectMessage],
|
||||
since,
|
||||
until,
|
||||
};
|
||||
const sub = subscribeMany(Array.from(relays), [filter], {
|
||||
onevent: (event) => eventStore.add(event),
|
||||
oneose: () => sub.close(),
|
||||
});
|
||||
},
|
||||
2 * 1000,
|
||||
[relays, contactsPubkeys, since, until],
|
||||
},
|
||||
],
|
||||
[contactsPubkeys, since, until],
|
||||
);
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [relays, contactsPubkeys, since, until]);
|
||||
|
||||
const throttledFilter = useThrottle(filters, 2 * 1000);
|
||||
useForwardSubscription(relays, throttledFilter);
|
||||
|
||||
const selfMetadata = useUserProfile(account.pubkey);
|
||||
const userProfiles = useUserProfiles(contactsPubkeys);
|
||||
|
@ -1,25 +1,22 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Navigate } from "react-router-dom";
|
||||
import { Button, Flex, Heading, Input, Link } from "@chakra-ui/react";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { Filter, NostrEvent } from "nostr-tools";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { Subscription, getEventUID } from "nostr-idb";
|
||||
import { getEventUID } from "nostr-idb";
|
||||
|
||||
import VerticalPageLayout from "../../components/vertical-page-layout";
|
||||
import useRouteSearchValue from "../../hooks/use-route-search-value";
|
||||
import { subscribeMany } from "../../helpers/relay";
|
||||
import { DEFAULT_SEARCH_RELAYS, WIKI_RELAYS } from "../../const";
|
||||
import { WIKI_PAGE_KIND } from "../../helpers/nostr/wiki";
|
||||
import { cacheRelay$ } from "../../services/cache-relay";
|
||||
import WikiPageResult from "./components/wiki-page-result";
|
||||
import { useWebOfTrust } from "../../providers/global/web-of-trust-provider";
|
||||
import { useObservable } from "applesauce-react/hooks";
|
||||
import { eventStore } from "../../services/event-store";
|
||||
import { ErrorBoundary } from "../../components/error-boundary";
|
||||
import { createSearchAction } from "../search/components/search-results";
|
||||
|
||||
export default function WikiSearchView() {
|
||||
const cacheRelay = useObservable(cacheRelay$);
|
||||
const webOfTrust = useWebOfTrust();
|
||||
const { value: query, setValue: setQuery } = useRouteSearchValue("q");
|
||||
if (!query) return <Navigate to="/wiki" />;
|
||||
@ -30,6 +27,7 @@ export default function WikiSearchView() {
|
||||
});
|
||||
|
||||
const [results, setResults] = useState<NostrEvent[]>([]);
|
||||
const search = useMemo(() => createSearchAction([...DEFAULT_SEARCH_RELAYS, ...WIKI_RELAYS]), []);
|
||||
|
||||
useEffect(() => {
|
||||
setResults([]);
|
||||
@ -38,25 +36,18 @@ export default function WikiSearchView() {
|
||||
|
||||
const seen = new Set<string>();
|
||||
const handleEvent = (event: NostrEvent) => {
|
||||
eventStore.add(event);
|
||||
|
||||
if (seen.has(getEventUID(event))) return;
|
||||
setResults((arr) => arr.concat(event));
|
||||
seen.add(getEventUID(event));
|
||||
};
|
||||
|
||||
const remoteSearchSub = subscribeMany([...DEFAULT_SEARCH_RELAYS, ...WIKI_RELAYS], [filter], {
|
||||
onevent: handleEvent,
|
||||
oneose: () => remoteSearchSub.close(),
|
||||
const sub = search([filter]).subscribe((packet) => {
|
||||
eventStore.add(packet.event, packet.from);
|
||||
handleEvent(packet.event);
|
||||
});
|
||||
|
||||
if (cacheRelay) {
|
||||
const localSearchSub: Subscription = cacheRelay.subscribe([filter], {
|
||||
onevent: handleEvent,
|
||||
oneose: () => localSearchSub.close(),
|
||||
});
|
||||
}
|
||||
}, [query, setResults, cacheRelay]);
|
||||
return () => sub.unsubscribe();
|
||||
}, [query, setResults]);
|
||||
|
||||
const sorted = webOfTrust ? webOfTrust.sortByDistanceAndConnections(results, (p) => p.pubkey) : results;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user