OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-overlay commits / 0b59f6e

overlay : remove transitional V2 aliases (full convergence)
All consumers migrated to canonical names + deployed, so the transitional aliases are no longer used by anyone (verified fleet-wide). Removed: root index.js HyperOverlayV2/OverlayProtocolV2 re-exports; lib/protocol.js OverlayProtocolV2 alias; lib/overlay.js HyperOverlayV2 alias; package.json /protocol-v2,/overlay-v2, /messages-v2 subpaths. lib/ is now the pure Ok engine + our superset (tree/pointer/ ignore/manifest + getIndexMeta + Keet backpressure). Suite 29 files green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0b59f6ec9122336bcc440eb1cbec9650592f1fcc
by plankatron <fleeky@gmail.com> · 2026-07-11T22:07:43.000Z

Changed files (6) +209 -269

index.js +0 -7
……@@ -46,13 +46,6 @@ export {
4646} from './lib/chunker.js'
4747export * as messages from './lib/messages.js'
4848
49// Transitional aliases for consumers still on the pre-3.0 v2 naming
50// (`HyperOverlayV2` / `OverlayProtocolV2`, and the `/protocol-v2`, `/overlay-v2`,
51// `/messages-v2` subpaths in package.json). Same classes — prefer the new names.
52// These let 0.3.0 land without forcing simultaneous edits to the live consumers.
53export { HyperOverlay as HyperOverlayV2 } from './lib/overlay.js'
54export { OverlayProtocol as OverlayProtocolV2 } from './lib/protocol.js'
55
5649// Our kept superset — dropped by ok/hyper-overlay-v3, retained here because
5750// pgh (tree/pointer/ignore), hyper-deploy (tree), and the forge (manifest)
5851// import them via subpaths. Not application concerns; they are the
lib/overlay.js +0 -5
……@@ -415,8 +415,3 @@ async function hashFileOnDisk (diskPath, size) {
415415 for await (const buf of fs.createReadStream(diskPath)) hasher.update(buf)
416416 return hasher.digest()
417417}
418
419// Transitional alias for pre-0.3.0 subpath consumers that import
420// `{ HyperOverlayV2 } from 'hyper-overlay/overlay-v2'`. Same class — lets 0.3.0
421// land without touching those consumers.
422export { HyperOverlay as HyperOverlayV2 }
lib/protocol.js +0 -5
……@@ -1042,8 +1042,3 @@ export class OverlayProtocol {
10421042function fileExists (p) {
10431043 try { return fs.statSync(p).isFile() } catch { return false }
10441044}
1045
1046// Transitional alias for pre-0.3.0 subpath consumers that import
1047// `{ OverlayProtocolV2 } from 'hyper-overlay/protocol-v2'` (pgh, hyper-deploy,
1048// pgh-sidecar). Same class — lets 0.3.0 land without touching those consumers.
1049export { OverlayProtocol as OverlayProtocolV2 }
package-lock.json +39 -248
……@@ -1,40 +1,35 @@
11{
22 "name": "hyper-overlay",
3 "version": "0.2.9",
3 "version": "0.3.1",
44 "lockfileVersion": 3,
55 "requires": true,
66 "packages": {
77 "": {
88 "name": "hyper-overlay",
9 "version": "0.2.9",
9 "version": "0.3.1",
1010 "license": "AGPL-3.0",
1111 "dependencies": {
12 "@hyperswarm/testnet": "^3.1.4",
1312 "b4a": "^1.0.0",
1413 "bare-fs": "^4.7.2",
15 "bare-http1": "^4.5.5",
16 "bare-native": "^0.1.2",
1714 "bare-os": "^3.8.7",
1815 "bare-path": "^3.0.0",
19 "bare-process": "^4.4.1",
2016 "bare-zlib": "^1.3.3",
21 "blind-pairing": "^2.3.1",
2217 "compact-encoding": "^3.2.0",
2318 "corestore": "^7.0.0",
2419 "hyperbee": "^2.0.0",
2520 "hypercore-crypto": "^3.0.0",
26 "hyperswarm": "^4.0.0",
27 "localwatch": "^1.4.3",
2821 "protomux": "^3.0.0",
29 "quickbit-universal": "^2.0.0",
3022 "ready-resource": "^1.0.0",
23 "sodium-universal": "^5.0.1",
3124 "streamx": "^2.0.0"
3225 },
3326 "devDependencies": {
34 "brittle": "^3.0.0"
27 "@hyperswarm/testnet": "^3.1.4",
28 "brittle": "^3.0.0",
29 "hyperswarm": "^4.0.0"
3530 },
36 "optionalDependencies": {
37 "fuse-native": "^2.2.6"
31 "engines": {
32 "bare": ">=1.16.0"
3833 }
3934 },
4035 "node_modules/@hyperswarm/secret-stream": {
……@@ -58,6 +53,7 @@
5853 "version": "3.1.4",
5954 "resolved": "https://registry.npmjs.org/@hyperswarm/testnet/-/testnet-3.1.4.tgz",
6055 "integrity": "sha512-Jw8JIZ9kdZ4R9jwJHsqctj5YeRqecw3aeCg2NS12HBXCqMioQIYzVqHs/8BWdOQCf34+BEXkwMQjba9CzaLwkg==",
56 "dev": true,
6157 "license": "Apache-2.0",
6258 "dependencies": {
6359 "hyperdht": "^6.6.0"
……@@ -105,6 +101,7 @@
105101 "version": "1.0.1",
106102 "resolved": "https://registry.npmjs.org/adaptive-timeout/-/adaptive-timeout-1.0.1.tgz",
107103 "integrity": "sha512-+seGiBtHqbnyZ0Quq/ZGxxwP66153WBABawa07/QeyuPFzbduPBjiGQAyCiriiLDzt3dkbMBskSlfqtRwblK8Q==",
104 "dev": true,
108105 "license": "Apache-2.0",
109106 "dependencies": {
110107 "xache": "^1.2.1"
……@@ -128,6 +125,7 @@
128125 "version": "2.0.13",
129126 "resolved": "https://registry.npmjs.org/bare-abort/-/bare-abort-2.0.13.tgz",
130127 "integrity": "sha512-zdc8l88eB11Jsz5rDd6sCAgv2kUFXgdrZWoMlgU6JMkfAi1/uuGFC3IEHswKbIRQTk5H3T5CMuechsXYxiaHlQ==",
128 "dev": true,
131129 "license": "Apache-2.0"
132130 },
133131 "node_modules/bare-addon-resolve": {
……@@ -165,16 +163,6 @@
165163 }
166164 }
167165 },
168 "node_modules/bare-app-kit": {
169 "version": "0.1.0",
170 "resolved": "https://registry.npmjs.org/bare-app-kit/-/bare-app-kit-0.1.0.tgz",
171 "integrity": "sha512-yX2U9WMMRpCHhx1ZooBnh32h+Vs8whxyqJKxvud171uhwzYaQsC7w/im5liMcbv6ajBWHjV7PTn9nutJaZK7pA==",
172 "license": "Apache-2.0",
173 "dependencies": {
174 "bare-events": "^2.8.2",
175 "require-asset": "^1.1.0"
176 }
177 },
178166 "node_modules/bare-assert": {
179167 "version": "1.2.0",
180168 "resolved": "https://registry.npmjs.org/bare-assert/-/bare-assert-1.2.0.tgz",
……@@ -253,6 +241,7 @@
253241 "version": "2.1.4",
254242 "resolved": "https://registry.npmjs.org/bare-dns/-/bare-dns-2.1.4.tgz",
255243 "integrity": "sha512-abwjHmpWqSRNB7V5615QxPH92L71AVzFm/kKTs8VYiNTAi2xVdonpv0BjJ0hwXLwomoW+xsSOPjW6PZPO14asg==",
244 "dev": true,
256245 "license": "Apache-2.0",
257246 "engines": {
258247 "bare": ">=1.7.0"
……@@ -277,6 +266,7 @@
277266 "version": "3.0.0",
278267 "resolved": "https://registry.npmjs.org/bare-env/-/bare-env-3.0.0.tgz",
279268 "integrity": "sha512-0u964P5ZLAxTi+lW4Kjp7YRJQ5gZr9ycYOtjLxsSrupgMz3sn5Z9n4SH/JIifHwvadsf1brA2JAjP+9IOWwTiw==",
269 "dev": true,
280270 "license": "Apache-2.0",
281271 "dependencies": {
282272 "bare-os": "^3.0.1"
……@@ -330,31 +320,25 @@
330320 }
331321 }
332322 },
333 "node_modules/bare-gtk": {
334 "version": "0.1.1",
335 "resolved": "https://registry.npmjs.org/bare-gtk/-/bare-gtk-0.1.1.tgz",
336 "integrity": "sha512-vUg16KxqRTxT6ghcgSv9lylI2XDqNHBC2Aw8oAo0ZAYYW3H8im4JH6/kZqzS3u/Sef9L4D2tK6460shJY36pQg==",
337 "license": "Apache-2.0",
338 "dependencies": {
339 "require-asset": "^1.1.0"
340 }
341 },
342323 "node_modules/bare-hrtime": {
343324 "version": "2.1.1",
344325 "resolved": "https://registry.npmjs.org/bare-hrtime/-/bare-hrtime-2.1.1.tgz",
345326 "integrity": "sha512-VMb3tHo05gsnbu3OXTmkDiwTjMlOsbQmKoysKqKEyR09m77TuDrYFbj3Q5GGk10dAKsUHrnXmwCaeJqzVpB5ZA==",
327 "dev": true,
346328 "license": "Apache-2.0"
347329 },
348330 "node_modules/bare-http-parser": {
349331 "version": "1.1.5",
350332 "resolved": "https://registry.npmjs.org/bare-http-parser/-/bare-http-parser-1.1.5.tgz",
351333 "integrity": "sha512-sPaDetLbWRmth04JmuTCvw/hoNdWJvYUJN8n1tYdGW3HM0mMnCvK2f0oIxE6HK7iOq+WlsRzEMg1LT/b0wGbLQ==",
334 "dev": true,
352335 "license": "Apache-2.0"
353336 },
354337 "node_modules/bare-http1": {
355338 "version": "4.5.7",
356339 "resolved": "https://registry.npmjs.org/bare-http1/-/bare-http1-4.5.7.tgz",
357340 "integrity": "sha512-PRuzs9ywt4vUvrC3mnHhQyaQfLYzdFy8XKOH0oKeKmYfyYYUqXBkdbJE2csESLBxJEbKDBjxPGLU+Qa0l1ds4A==",
341 "dev": true,
358342 "license": "Apache-2.0",
359343 "dependencies": {
360344 "bare-events": "^2.6.0",
……@@ -485,31 +469,6 @@
485469 }
486470 }
487471 },
488 "node_modules/bare-native": {
489 "version": "0.1.2",
490 "resolved": "https://registry.npmjs.org/bare-native/-/bare-native-0.1.2.tgz",
491 "integrity": "sha512-gQ3UfQ/uMwyZ8BqdXkn3oeYgdq8cZau1oCUlFU5dw11tl0zlEMLe71GjnXYWCLL3gWCO1rF3U2yN9QkwsTBKJA==",
492 "license": "Apache-2.0",
493 "dependencies": {
494 "bare-app-kit": "^0.1.0",
495 "bare-events": "^2.8.2",
496 "bare-gtk": "^0.1.0",
497 "bare-ndk": "^0.1.2",
498 "bare-ui-kit": "^0.1.1",
499 "bare-web-kit": "^0.1.0",
500 "bare-web-kit-gtk": "^0.1.0",
501 "bare-win-ui": "^0.1.0"
502 }
503 },
504 "node_modules/bare-ndk": {
505 "version": "0.1.4",
506 "resolved": "https://registry.npmjs.org/bare-ndk/-/bare-ndk-0.1.4.tgz",
507 "integrity": "sha512-MUgolvfASD+4RADb9F8mq898sV4EPj8MgqQR6XTcoqER6P5td8E7BziDkHU2RWSpEbSiYJSp4C4yDBRFIt2KyQ==",
508 "license": "Apache-2.0",
509 "dependencies": {
510 "require-asset": "^1.1.0"
511 }
512 },
513472 "node_modules/bare-net": {
514473 "version": "2.3.2",
515474 "resolved": "https://registry.npmjs.org/bare-net/-/bare-net-2.3.2.tgz",
……@@ -545,6 +504,7 @@
545504 "version": "4.2.2",
546505 "resolved": "https://registry.npmjs.org/bare-pipe/-/bare-pipe-4.2.2.tgz",
547506 "integrity": "sha512-Wkf6//CmKS8inHrkgi3X/xNMeaGfs2I0ayLM0B8cbPB4DxYHcoes6Ng+muCBfXNIJ9qmEjwDDJjAUz7nRxxjgQ==",
507 "dev": true,
548508 "license": "Apache-2.0",
549509 "peer": true,
550510 "dependencies": {
……@@ -559,6 +519,7 @@
559519 "version": "4.4.1",
560520 "resolved": "https://registry.npmjs.org/bare-process/-/bare-process-4.4.1.tgz",
561521 "integrity": "sha512-JfcTtymq6akqM2bdyTsP4A4GYJceBzb91k/ECmFps75uFf6uO33SM1bOZsRAqyRXExabsQJLn5S41NBl8HTM4A==",
522 "dev": true,
562523 "license": "Apache-2.0",
563524 "dependencies": {
564525 "bare-abort": "^2.0.13",
……@@ -580,6 +541,7 @@
580541 "version": "4.2.0",
581542 "resolved": "https://registry.npmjs.org/bare-signals/-/bare-signals-4.2.0.tgz",
582543 "integrity": "sha512-fNHMOdQIlYuTvMB3Oh9Apk99hLKn351+Ir8vz+khiPTcOqIyGG4uWWjdLTzxWdYGsA0eT+We3y0K74hjj2nq7A==",
544 "dev": true,
583545 "license": "Apache-2.0",
584546 "dependencies": {
585547 "bare-events": "^2.5.3",
……@@ -593,6 +555,7 @@
593555 "version": "1.0.2",
594556 "resolved": "https://registry.npmjs.org/bare-stdio/-/bare-stdio-1.0.2.tgz",
595557 "integrity": "sha512-3WJDqtvVGP4f+j68kyEC05umOYNwKJ1xG+YAXL8yZ605WgNqiRhVaFq+mVIhBt2eKNp7pa5vCQdhOt1pNh79SA==",
558 "dev": true,
596559 "license": "Apache-2.0",
597560 "dependencies": {
598561 "bare-fs": "^4.5.2",
……@@ -667,6 +630,7 @@
667630 "version": "2.5.1",
668631 "resolved": "https://registry.npmjs.org/bare-tcp/-/bare-tcp-2.5.1.tgz",
669632 "integrity": "sha512-N32OosAegmGzksr/huxIYLU/uaUARte6utO+vAu/EPQztMM7iAC55VeQSfzr2/XBJoz2OIETMvmU7/sdfiOGjw==",
633 "dev": true,
670634 "license": "Apache-2.0",
671635 "dependencies": {
672636 "bare-dns": "^2.0.4",
……@@ -703,6 +667,7 @@
703667 "version": "5.1.1",
704668 "resolved": "https://registry.npmjs.org/bare-tty/-/bare-tty-5.1.1.tgz",
705669 "integrity": "sha512-cXCMAlcLCFTCWwCtXBIhDuXa4hutTEbrHHIK5pvSSb4BLaSGJ9tvxVN3mvGOvXXqONS7l04mTiP+eIUlZKI92g==",
670 "dev": true,
706671 "license": "Apache-2.0",
707672 "dependencies": {
708673 "bare-events": "^2.2.0",
……@@ -722,16 +687,6 @@
722687 "bare": ">=1.2.0"
723688 }
724689 },
725 "node_modules/bare-ui-kit": {
726 "version": "0.1.1",
727 "resolved": "https://registry.npmjs.org/bare-ui-kit/-/bare-ui-kit-0.1.1.tgz",
728 "integrity": "sha512-pvfxcpcvISBcKtKSRiU4sDKVI4luuy7oM1MbdvU4SRP7Qy8/GsRnYNwTcsk8Gg7Nv3OAQo2BTc+UxcK940NmRg==",
729 "license": "Apache-2.0",
730 "dependencies": {
731 "bare-events": "^2.8.2",
732 "require-asset": "^1.1.0"
733 }
734 },
735690 "node_modules/bare-url": {
736691 "version": "2.4.5",
737692 "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.5.tgz",
……@@ -775,36 +730,6 @@
775730 "which-runtime": "^1.2.1"
776731 }
777732 },
778 "node_modules/bare-web-kit": {
779 "version": "0.1.2",
780 "resolved": "https://registry.npmjs.org/bare-web-kit/-/bare-web-kit-0.1.2.tgz",
781 "integrity": "sha512-q00WnUSq25S8gmcBgPBHuNPf3ZPjwRshzOM/h+KZbNjWh9z+zVNqFyHAMFcJcfYBC+p7t1cYrLQN6jv29tDo9g==",
782 "license": "Apache-2.0",
783 "dependencies": {
784 "bare-events": "^2.8.2",
785 "require-asset": "^1.1.0"
786 }
787 },
788 "node_modules/bare-web-kit-gtk": {
789 "version": "0.1.0",
790 "resolved": "https://registry.npmjs.org/bare-web-kit-gtk/-/bare-web-kit-gtk-0.1.0.tgz",
791 "integrity": "sha512-8mcB21OK0gRNfbE2MjqyX01MSltzRfWa174nYv1QlG8D6Net21oRH6E0uxMz9LNGxzVo3kyeIds/nk39lk2XAA==",
792 "license": "Apache-2.0",
793 "dependencies": {
794 "bare-gtk": "^0.1.0",
795 "require-asset": "^1.1.0"
796 }
797 },
798 "node_modules/bare-win-ui": {
799 "version": "0.1.0",
800 "resolved": "https://registry.npmjs.org/bare-win-ui/-/bare-win-ui-0.1.0.tgz",
801 "integrity": "sha512-7wNQELWaEZFjgOJF2iZvsTMFsvJKx+HKWRUok9bTwy4s5iezHte2eaJhN3IppK1Job/JzLf8SOupOKyXzoub1w==",
802 "license": "Apache-2.0",
803 "dependencies": {
804 "bare-events": "^2.8.2",
805 "require-asset": "^1.1.0"
806 }
807 },
808733 "node_modules/bare-ws": {
809734 "version": "3.0.0",
810735 "resolved": "https://registry.npmjs.org/bare-ws/-/bare-ws-3.0.0.tgz",
……@@ -858,46 +783,17 @@
858783 "version": "1.3.0",
859784 "resolved": "https://registry.npmjs.org/bits-to-bytes/-/bits-to-bytes-1.3.0.tgz",
860785 "integrity": "sha512-OJoHTpFXS9bXHBCekGTByf3MqM8CGblBDIduKQeeVVeiU9dDWywSSirXIBYGgg3d1zbVuvnMa1vD4r6PA0kOKg==",
786 "dev": true,
861787 "license": "ISC",
862788 "dependencies": {
863789 "b4a": "^1.5.0"
864790 }
865791 },
866 "node_modules/blind-pairing": {
867 "version": "2.3.1",
868 "resolved": "https://registry.npmjs.org/blind-pairing/-/blind-pairing-2.3.1.tgz",
869 "integrity": "sha512-E678Mi6n07Yc8iRtgwzQLmk9EgHmYHBRzKDxpkdkS+Sh476RQ88iv75cvRkPp62rd7nsrP4lqku8uU9EeKGLiA==",
870 "license": "Apache-2.0",
871 "dependencies": {
872 "b4a": "^1.6.4",
873 "blind-pairing-core": "^2.0.0",
874 "debounceify": "^1.1.0",
875 "hypercore-crypto": "^3.4.0",
876 "is-options": "^1.0.2",
877 "ready-resource": "^1.0.0",
878 "safety-catch": "^1.0.2",
879 "xache": "^1.2.0"
880 }
881 },
882 "node_modules/blind-pairing-core": {
883 "version": "2.10.1",
884 "resolved": "https://registry.npmjs.org/blind-pairing-core/-/blind-pairing-core-2.10.1.tgz",
885 "integrity": "sha512-CD16k4iFJdrSruNUJOB12jRPGHlWR43CJQ9ss4lRkg44f+YCmrrkmCGUbg2hLnxdPkulkix56fjiNIYMRMe19Q==",
886 "license": "Apache-2.0",
887 "dependencies": {
888 "b4a": "^1.6.4",
889 "bare-events": "^2.5.0",
890 "bogon": "^1.1.0",
891 "compact-encoding": "^3.0.0",
892 "hypercore-crypto": "^3.4.0",
893 "sodium-universal": "^5.0.1",
894 "tiny-buffer-map": "^1.1.1"
895 }
896 },
897792 "node_modules/blind-relay": {
898793 "version": "1.6.1",
899794 "resolved": "https://registry.npmjs.org/blind-relay/-/blind-relay-1.6.1.tgz",
900795 "integrity": "sha512-38YmKCl/m9NcTkwueBbcGIt9Zx3IT/Q9Nsluu6C5Gur6PqfE0zWPhPwCzia1hri/g0ICYxrqkgLtEaoWD5WeSQ==",
796 "dev": true,
901797 "license": "Apache-2.0",
902798 "dependencies": {
903799 "b4a": "^1.6.4",
……@@ -914,6 +810,7 @@
914810 "version": "1.3.0",
915811 "resolved": "https://registry.npmjs.org/bogon/-/bogon-1.3.0.tgz",
916812 "integrity": "sha512-04tu0G/v0f2HPuQlSfhO635WwHDBCaITJ490rhxH9ttUlgPqOirZVKV02YB6NvPf5VkmbqJCm3bnZwrPk/eDSg==",
813 "dev": true,
917814 "license": "MIT",
918815 "dependencies": {
919816 "compact-encoding": "^3.0.0",
……@@ -972,6 +869,7 @@
972869 "version": "1.1.0",
973870 "resolved": "https://registry.npmjs.org/compact-encoding-bitfield/-/compact-encoding-bitfield-1.1.0.tgz",
974871 "integrity": "sha512-F6wliSKHi50BsBStmnsRJAzJgYSIYzdfSe3M0oHj4uQ1RcctJK/NQVD7wF51bj/DBMne2i5gUxrGUFkNZQns5w==",
872 "dev": true,
975873 "license": "Apache-2.0",
976874 "dependencies": {
977875 "compact-encoding": "^3.0.0"
……@@ -981,6 +879,7 @@
981879 "version": "1.3.0",
982880 "resolved": "https://registry.npmjs.org/compact-encoding-net/-/compact-encoding-net-1.3.0.tgz",
983881 "integrity": "sha512-HIYjL3aMiSENApR691aMLngXt6rkTHb9HUkEukcx3YwIZpoMUVXHXyjBzoo9kVwC7KakooBA1RRWb46Cu6qtAQ==",
882 "dev": true,
984883 "license": "Apache-2.0",
985884 "dependencies": {
986885 "compact-encoding": "^3.0.0"
……@@ -1035,6 +934,7 @@
1035934 "version": "6.27.0",
1036935 "resolved": "https://registry.npmjs.org/dht-rpc/-/dht-rpc-6.27.0.tgz",
1037936 "integrity": "sha512-NsfgRlFDQnkA2+H+hJXMPLmBOn/TSIIc0cRMV8q42M4xc1uAXWtpvIIQsONF5tYcYC6px0bslrUGideN1h4S4A==",
937 "dev": true,
1038938 "license": "MIT",
1039939 "dependencies": {
1040940 "adaptive-timeout": "^1.0.1",
……@@ -1104,56 +1004,6 @@
11041004 "which-runtime": "^1.2.0"
11051005 }
11061006 },
1107 "node_modules/fuse-native": {
1108 "version": "2.2.6",
1109 "resolved": "https://registry.npmjs.org/fuse-native/-/fuse-native-2.2.6.tgz",
1110 "integrity": "sha512-Y5wXd7vUsWWWIIHbjluv7jKZgPZaSVA5YWaW3I5fXIJfcGWL6IRUgoBUveQAq+D8cG9cCiGNahv9CeToccCXrw==",
1111 "hasInstallScript": true,
1112 "license": "MIT",
1113 "optional": true,
1114 "dependencies": {
1115 "fuse-shared-library": "^1.0.2",
1116 "nanoresource": "^1.3.0",
1117 "napi-macros": "^2.0.0",
1118 "node-gyp-build": "^4.2.0"
1119 },
1120 "bin": {
1121 "fuse-native": "bin.js"
1122 }
1123 },
1124 "node_modules/fuse-shared-library": {
1125 "version": "1.1.1",
1126 "resolved": "https://registry.npmjs.org/fuse-shared-library/-/fuse-shared-library-1.1.1.tgz",
1127 "integrity": "sha512-EfgTo/eS1euZFUe7x8KqyA40hV4DwP7kqp1VNZApu2nlPnJv8SanraBE3VXyX7ff41sxw7M0oWY7re3G3wnZVA==",
1128 "license": "MIT",
1129 "optional": true,
1130 "dependencies": {
1131 "fuse-shared-library-darwin": "^1.0.3",
1132 "fuse-shared-library-linux": "^1.0.1",
1133 "fuse-shared-library-linux-arm": "^1.0.0"
1134 }
1135 },
1136 "node_modules/fuse-shared-library-darwin": {
1137 "version": "1.1.3",
1138 "resolved": "https://registry.npmjs.org/fuse-shared-library-darwin/-/fuse-shared-library-darwin-1.1.3.tgz",
1139 "integrity": "sha512-4Q8gMxyMl1+gwHGpiYUoKKpi7xq8WcPo0TvJvjZzHMuCiszouu2GgEs6SJAqPB3LjfmEkl6kPV+2Oluczr0Nig==",
1140 "license": "MIT",
1141 "optional": true
1142 },
1143 "node_modules/fuse-shared-library-linux": {
1144 "version": "1.0.1",
1145 "resolved": "https://registry.npmjs.org/fuse-shared-library-linux/-/fuse-shared-library-linux-1.0.1.tgz",
1146 "integrity": "sha512-07MQRSobrBKwW4D7oKm0gM2TwgvZWb+gC08JdiYDG4KBTncxk9ssqEDiDMKll8hpseZufsY2w1yc/feOu2DPmQ==",
1147 "license": "MIT",
1148 "optional": true
1149 },
1150 "node_modules/fuse-shared-library-linux-arm": {
1151 "version": "1.0.0",
1152 "resolved": "https://registry.npmjs.org/fuse-shared-library-linux-arm/-/fuse-shared-library-linux-arm-1.0.0.tgz",
1153 "integrity": "sha512-Dj4ssxo1/MKGvOsVWRblSRu+o5F5OJTrVPDkjSyGDU2yKvVnIzQSwy1deiWA0qCcS/Q8iJMlZaCpCcZWSwvoug==",
1154 "license": "MIT",
1155 "optional": true
1156 },
11571007 "node_modules/generate-object-property": {
11581008 "version": "2.0.0",
11591009 "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-2.0.0.tgz",
……@@ -1285,6 +1135,7 @@
12851135 "version": "6.32.0",
12861136 "resolved": "https://registry.npmjs.org/hyperdht/-/hyperdht-6.32.0.tgz",
12871137 "integrity": "sha512-Y/SibEN7wue0E8ydh8lx9IX7SOE9o00b6tufPA7hRxAafXsisWUBrW36fIHdyxg148T4Z3olrooOGZDZ89LYag==",
1138 "dev": true,
12881139 "license": "MIT",
12891140 "dependencies": {
12901141 "@hyperswarm/secret-stream": "^6.6.2",
……@@ -1315,6 +1166,7 @@
13151166 "version": "1.1.1",
13161167 "resolved": "https://registry.npmjs.org/hyperdht-address/-/hyperdht-address-1.1.1.tgz",
13171168 "integrity": "sha512-Mu/+7SW2cwvHxMXswa5mOrhrS5BJyntViAuB25k8d8wNtA8eAPs4LaIq6TwN1SS/KQY02h1r+gM8cQeN/k360w==",
1169 "dev": true,
13181170 "license": "Apache-2.0",
13191171 "dependencies": {
13201172 "compact-encoding": "^3.0.0",
……@@ -1337,6 +1189,7 @@
13371189 "version": "4.17.0",
13381190 "resolved": "https://registry.npmjs.org/hyperswarm/-/hyperswarm-4.17.0.tgz",
13391191 "integrity": "sha512-oe86sK961Ueg7rvDN/veFwG8xH+Iv6vObPhGDkPJcDVxk/NduW41ZhAcVDnHzRbm7S0eLU7WaDUvehOYoKSpRQ==",
1192 "dev": true,
13401193 "license": "MIT",
13411194 "dependencies": {
13421195 "b4a": "^1.3.1",
……@@ -1357,13 +1210,6 @@
13571210 "b4a": "^1.6.4"
13581211 }
13591212 },
1360 "node_modules/inherits": {
1361 "version": "2.0.4",
1362 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1363 "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1364 "license": "ISC",
1365 "optional": true
1366 },
13671213 "node_modules/is-options": {
13681214 "version": "1.0.2",
13691215 "resolved": "https://registry.npmjs.org/is-options/-/is-options-1.0.2.tgz",
……@@ -1383,23 +1229,12 @@
13831229 "version": "1.0.6",
13841230 "resolved": "https://registry.npmjs.org/kademlia-routing-table/-/kademlia-routing-table-1.0.6.tgz",
13851231 "integrity": "sha512-Ve6jwIlUCYvUzBnXnzVRHDZCFgXURW9gmF3r7n05kZs/2rNbLHXwGdcq0qIaSwdmJCvtosgR4JensnVU65hzNQ==",
1232 "dev": true,
13861233 "license": "MIT",
13871234 "dependencies": {
13881235 "bare-events": "^2.2.0"
13891236 }
13901237 },
1391 "node_modules/localwatch": {
1392 "version": "1.4.3",
1393 "resolved": "https://registry.npmjs.org/localwatch/-/localwatch-1.4.3.tgz",
1394 "integrity": "sha512-P57a2VIczhUXAkMIP9u75qlLW7PYPv4f8Q7GXoQ2rEvPgU06OwXA2n2p+cuKqVciQSC71MBoKvFdlj3O4fWtyQ==",
1395 "license": "Apache-2.0",
1396 "dependencies": {
1397 "bare-fs": "^4.0.1",
1398 "bare-path": "^3.0.0",
1399 "streamx": "^2.16.1",
1400 "which-runtime": "^1.2.0"
1401 }
1402 },
14031238 "node_modules/mutexify": {
14041239 "version": "1.4.0",
14051240 "resolved": "https://registry.npmjs.org/mutexify/-/mutexify-1.4.0.tgz",
……@@ -1415,41 +1250,13 @@
14151250 "integrity": "sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==",
14161251 "license": "ISC"
14171252 },
1418 "node_modules/nanoresource": {
1419 "version": "1.3.0",
1420 "resolved": "https://registry.npmjs.org/nanoresource/-/nanoresource-1.3.0.tgz",
1421 "integrity": "sha512-OI5dswqipmlYfyL3k/YMm7mbERlh4Bd1KuKdMHpeoVD1iVxqxaTMKleB4qaA2mbQZ6/zMNSxCXv9M9P/YbqTuQ==",
1422 "license": "MIT",
1423 "optional": true,
1424 "dependencies": {
1425 "inherits": "^2.0.4"
1426 }
1427 },
1428 "node_modules/napi-macros": {
1429 "version": "2.2.2",
1430 "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz",
1431 "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==",
1432 "license": "MIT",
1433 "optional": true
1434 },
14351253 "node_modules/nat-sampler": {
14361254 "version": "1.0.1",
14371255 "resolved": "https://registry.npmjs.org/nat-sampler/-/nat-sampler-1.0.1.tgz",
14381256 "integrity": "sha512-yQvyNN7xbqR8crTKk3U8gRgpcV1Az+vfCEijiHu9oHHsnIl8n3x+yXNHl42M6L3czGynAVoOT9TqBfS87gDdcw==",
1257 "dev": true,
14391258 "license": "MIT"
14401259 },
1441 "node_modules/node-gyp-build": {
1442 "version": "4.8.4",
1443 "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
1444 "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
1445 "license": "MIT",
1446 "optional": true,
1447 "bin": {
1448 "node-gyp-build": "bin.js",
1449 "node-gyp-build-optional": "optional.js",
1450 "node-gyp-build-test": "build-test.js"
1451 }
1452 },
14531260 "node_modules/noise-curve-ed": {
14541261 "version": "2.1.0",
14551262 "resolved": "https://registry.npmjs.org/noise-curve-ed/-/noise-curve-ed-2.1.0.tgz",
……@@ -1570,6 +1377,7 @@
15701377 "version": "1.2.0",
15711378 "resolved": "https://registry.npmjs.org/record-cache/-/record-cache-1.2.0.tgz",
15721379 "integrity": "sha512-kyy3HWCez2WrotaL3O4fTn0rsIdfRKOdQQcEJ9KpvmKmbffKVvwsloX063EgRUlpJIXHiDQFhJcTbZequ2uTZw==",
1380 "dev": true,
15731381 "license": "MIT",
15741382 "dependencies": {
15751383 "b4a": "^1.3.1"
……@@ -1593,19 +1401,6 @@
15931401 "bare": ">=1.10.0"
15941402 }
15951403 },
1596 "node_modules/require-asset": {
1597 "version": "1.2.2",
1598 "resolved": "https://registry.npmjs.org/require-asset/-/require-asset-1.2.2.tgz",
1599 "integrity": "sha512-uc8nWKhqAxVD9Z4rST2b4yaemrC9Xb5vA1wlCz5AiCYnBYdwGRWNqFjneA5zRILzlo1MNrB63ry9+pc8wNR26w==",
1600 "license": "Apache-2.0",
1601 "dependencies": {
1602 "bare-module-resolve": "^1.6.2"
1603 },
1604 "engines": {
1605 "bare": ">=1.10.0",
1606 "node": ">=18"
1607 }
1608 },
16091404 "node_modules/resolve-reject-promise": {
16101405 "version": "1.1.0",
16111406 "resolved": "https://registry.npmjs.org/resolve-reject-promise/-/resolve-reject-promise-1.1.0.tgz",
……@@ -1659,6 +1454,7 @@
16591454 "version": "2.1.0",
16601455 "resolved": "https://registry.npmjs.org/shuffled-priority-queue/-/shuffled-priority-queue-2.1.0.tgz",
16611456 "integrity": "sha512-xhdh7fHyMsr0m/w2kDfRJuBFRS96b9l8ZPNWGaQ+PMvnUnZ/Eh+gJJ9NsHBd7P9k0399WYlCLzsy18EaMfyadA==",
1457 "dev": true,
16621458 "license": "MIT",
16631459 "dependencies": {
16641460 "unordered-set": "^2.0.1"
……@@ -1795,6 +1591,7 @@
17951591 "version": "2.0.1",
17961592 "resolved": "https://registry.npmjs.org/time-ordered-set/-/time-ordered-set-2.0.1.tgz",
17971593 "integrity": "sha512-VJEKmgSN2UiOLB8BpN8Sh2b9LGMHTP5OPrQRpnKjvOheOyzk0mufbjzjKTIG2gO4A+Y+vDJ+0TcLbpUmMLsg8A==",
1594 "dev": true,
17981595 "license": "MIT"
17991596 },
18001597 "node_modules/timeout-refresh": {
……@@ -1803,15 +1600,6 @@
18031600 "integrity": "sha512-SVqEcMZBsZF9mA78rjzCrYrUs37LMJk3ShZ851ygZYW1cMeIjs9mL57KO6Iv5mmjSQnOe/29/VAfGXo+oRCiVw==",
18041601 "license": "MIT"
18051602 },
1806 "node_modules/tiny-buffer-map": {
1807 "version": "1.1.1",
1808 "resolved": "https://registry.npmjs.org/tiny-buffer-map/-/tiny-buffer-map-1.1.1.tgz",
1809 "integrity": "sha512-C1eDw6ks9CmkDbWVCPHobuixPTkxGa7IDERlaVk98dv4tOUdz42o3haHBr0uhNxbj0gczBTVIyS2uQsu+1vc2Q==",
1810 "license": "MIT",
1811 "dependencies": {
1812 "b4a": "^1.6.0"
1813 }
1814 },
18151603 "node_modules/tmatch": {
18161604 "version": "5.0.0",
18171605 "resolved": "https://registry.npmjs.org/tmatch/-/tmatch-5.0.0.tgz",
……@@ -1826,6 +1614,7 @@
18261614 "version": "1.20.7",
18271615 "resolved": "https://registry.npmjs.org/udx-native/-/udx-native-1.20.7.tgz",
18281616 "integrity": "sha512-FNG0QpnSt0us2xbLP5mmG5Q0UKdLYjKHuh2eR9VrJSFmoZMzeszYLLhK12+iq5x3eq/rgoGG/lLwPn7IDAr6pg==",
1617 "dev": true,
18291618 "license": "Apache-2.0",
18301619 "dependencies": {
18311620 "b4a": "^1.5.0",
……@@ -1841,6 +1630,7 @@
18411630 "version": "2.0.1",
18421631 "resolved": "https://registry.npmjs.org/unordered-set/-/unordered-set-2.0.1.tgz",
18431632 "integrity": "sha512-eUmNTPzdx+q/WvOHW0bgGYLWvWHNT3PTKEQLg0MAQhc0AHASHVHoP/9YytYd4RBVariqno/mEUhVZN98CmD7bg==",
1633 "dev": true,
18441634 "license": "MIT"
18451635 },
18461636 "node_modules/unslab": {
……@@ -1883,6 +1673,7 @@
18831673 "version": "1.2.1",
18841674 "resolved": "https://registry.npmjs.org/xache/-/xache-1.2.1.tgz",
18851675 "integrity": "sha512-igRS6jPreJ54ABdzhh4mCDXcz+XMaWO2q1ABRV2yWYuk29jlp8VT7UBdCqNkX7rpYBbXsebVVKkwIuYZjyZNqA==",
1676 "dev": true,
18861677 "license": "MIT"
18871678 },
18881679 "node_modules/z32": {
package.json +1 -4
……@@ -1,6 +1,6 @@
11{
22 "name": "hyper-overlay",
3 "version": "0.3.0",
3 "version": "0.3.1",
44 "description": "Content-addressed P2P file distribution over Protomux — FastCDC chunking, multi-source fetch, resumable transfers, zero blob duplication. Files live on disk; the overlay is a thin index and transfer protocol.",
55 "type": "module",
66 "main": "index.js",
……@@ -36,9 +36,6 @@
3636 "./pointer": "./lib/pointer.js",
3737 "./ignore": "./lib/ignore.js",
3838 "./manifest": "./lib/manifest.js",
39 "./protocol-v2": "./lib/protocol.js",
40 "./overlay-v2": "./lib/overlay.js",
41 "./messages-v2": "./lib/messages.js",
4239 "./package.json": "./package.json"
4340 },
4441 "scripts": {
test/overlay-v2-corestore-mux.test.js +169 -0
……@@ -0,0 +1,169 @@
1import test from 'brittle'
2import Protomux from 'protomux'
3import SecretStream from '@hyperswarm/secret-stream'
4import { Duplex } from 'streamx'
5import crypto from 'hypercore-crypto'
6import { tmpStore, tmpDir, fs, path } from './helpers.js'
7import { HyperOverlayV2 } from '../lib/overlay-v2.js'
8import { OverlayProtocolV2 } from '../lib/protocol-v2.js'
9import { FileIndex } from '../lib/file-index.js'
10import { TransferManager } from '../lib/transfer.js'
11
12// Attach a SECOND OverlayProtocolV2 to the same mux, exactly how hyper-deploy's
13// DeployServer does on the shared forge swarm (same protocol 'hyper-overlay/v2',
14// keyed to a topic). This is the production mux condition the daemon's own
15// HyperOverlayV2 (id=null) coexists with — the variable the clean E2E never had.
16async function attachDeployStyleOverlay (store, mux, topic) {
17 const idx = new FileIndex(store.namespace('deploy-' + topic.toString('hex').slice(0, 6)))
18 await idx.ready()
19 const tm = new TransferManager(idx)
20 const stub = { _fileIndex: idx, feedKey: '0'.repeat(64), feed: { length: 0, async get () { return null } }, async markSynced () {}, async logPut () {} }
21 const proto = new OverlayProtocolV2(stub, tm, { key: topic, autoSync: false })
22 proto.attach(mux)
23 return proto
24}
25
26// #66 root-cause probe: the existing overlay-v2-fetch tests attach the overlay
27// channel on a BARE duplex (Protomux.from(stream) with nothing else on it). The
28// LIVE hyper-svc forge path is different (transports/swarm.js _onConnection):
29//
30// 1. corestore.replicate(conn) ← claims a Protomux on the stream +
31// opens corestore's own channels FIRST
32// 2. mux = Protomux.from(conn) ← REUSES that same protomux
33// 3. instance.attachProtocol(mux) ← overlay channel created on the reused mux
34//
35// On the live forge swarm, stortron's overlayV2 ends up with ZERO peers (no
36// `[proto] channel opened`, fetchFile bails at the no-peer check) while
37// tabertron's overlayV2 is active. This test reproduces the live ORDERING in
38// memory to prove/disprove that "corestore.replicate claims the mux first"
39// breaks overlay channel pairing.
40
41function makeDuplex () {
42 let aWrite, bWrite
43 const a = new Duplex({ write (d, cb) { bWrite(d); cb() }, read () {} })
44 const b = new Duplex({ write (d, cb) { aWrite(d); cb() }, read () {} })
45 aWrite = (d) => a.push(d)
46 bWrite = (d) => b.push(d)
47 return [a, b]
48}
49
50const settle = (ms = 400) => new Promise(r => setTimeout(r, ms))
51
52test('CONTROL: bare-mux attach pairs + fetches (matches existing passing tests)', async (t) => {
53 const storeA = tmpStore('ov2-ctl-a'); const storeB = tmpStore('ov2-ctl-b')
54 const alice = new HyperOverlayV2(storeA, { namespace: 'overlay-v2', destDir: tmpDir('ov2-ctl-a-dest') })
55 const bob = new HyperOverlayV2(storeB, { namespace: 'overlay-v2', destDir: tmpDir('ov2-ctl-b-dest') })
56 await alice.ready(); await bob.ready()
57 t.teardown(async () => { try { await alice.close() } catch {}; try { await bob.close() } catch {} })
58
59 const [sa, sb] = makeDuplex()
60 alice.attachProtocol(Protomux.from(sa))
61 bob.attachProtocol(Protomux.from(sb))
62 await settle()
63
64 t.is(alice.peerCount, 1, 'alice has 1 overlay peer')
65 t.is(bob.peerCount, 1, 'bob has 1 overlay peer')
66
67 const content = crypto.randomBytes(200 * 1024)
68 const diskPath = path.join(tmpDir('ov2-ctl-files'), 'f.bin')
69 fs.writeFileSync(diskPath, content)
70 const oid = crypto.data(content).toString('hex')
71 await alice.registerFile('/attachments/' + oid, diskPath, { contentHash: oid, size: content.length })
72
73 const got = await bob.fetchFile(oid)
74 t.ok(got && got.local === false, 'bob fetched from peer')
75 t.is(Buffer.compare(got.data, content), 0, 'bytes match')
76})
77
78test('LIVE ORDERING: corestore.replicate(conn) BEFORE attachProtocol — does overlay still pair?', async (t) => {
79 const storeA = tmpStore('ov2-live-a'); const storeB = tmpStore('ov2-live-b')
80 const alice = new HyperOverlayV2(storeA, { namespace: 'overlay-v2', destDir: tmpDir('ov2-live-a-dest') })
81 const bob = new HyperOverlayV2(storeB, { namespace: 'overlay-v2', destDir: tmpDir('ov2-live-b-dest') })
82 await alice.ready(); await bob.ready()
83 t.teardown(async () => { try { await alice.close() } catch {}; try { await bob.close() } catch {} })
84
85 // ── reproduce hyper-svc _onConnection ordering FAITHFULLY ──
86 // conn is a @hyperswarm/secret-stream — EXACTLY what Hyperswarm hands
87 // _onConnection. Then, per swarm.js: corestore.replicate(conn) FIRST, then
88 // Protomux.from(conn) for the overlay channel.
89 const [da, db] = makeDuplex()
90 const sa = new SecretStream(true, da)
91 const sb = new SecretStream(false, db)
92 await Promise.all([
93 new Promise(r => sa.on('connect', r)),
94 new Promise(r => sb.on('connect', r))
95 ])
96 storeA.replicate(sa) // corestore claims the conn's mux first
97 storeB.replicate(sb)
98 alice.attachProtocol(Protomux.from(sa)) // overlay on Protomux.from(conn)
99 bob.attachProtocol(Protomux.from(sb))
100 await settle()
101
102 // The decisive assertions: do the overlay channels pair under this ordering?
103 t.is(alice.peerCount, 1, 'alice overlay peer present under corestore-first ordering')
104 t.is(bob.peerCount, 1, 'bob overlay peer present under corestore-first ordering')
105
106 const content = crypto.randomBytes(200 * 1024)
107 const diskPath = path.join(tmpDir('ov2-live-files'), 'f.bin')
108 fs.writeFileSync(diskPath, content)
109 const oid = crypto.data(content).toString('hex')
110 await alice.registerFile('/attachments/' + oid, diskPath, { contentHash: oid, size: content.length })
111
112 // Channels register a peer, but with corestore sharing the mux the overlay
113 // channel never OPENS (no sync-state exchange), so the fetch can't complete.
114 // Bounded so the test fails fast instead of hanging. This currently FAILS —
115 // it documents the bug + guards the fix (it should pass once channel-open
116 // works under the shared-mux ordering).
117 const got = await bob.fetchFile(oid, { timeout: 6000 })
118 t.ok(got, 'bob resolved the file under live (corestore-replicate-first) ordering')
119 if (got) t.is(Buffer.compare(got.data, content), 0, 'bytes match')
120})
121
122// PRODUCTION MUX: the daemon's HyperOverlayV2 (id=null) coexists on the same
123// forge connection with hyper-deploy's OverlayProtocolV2 (SAME protocol
124// 'hyper-overlay/v2', keyed to a topic). Reproduce that second same-protocol
125// channel and see whether the daemon overlay (id=null) still pairs + fetches.
126test('LOADED MUX: a 2nd hyper-overlay/v2 channel (hyper-deploy-style) on the same mux', async (t) => {
127 const storeA = tmpStore('ov2-load-a'); const storeB = tmpStore('ov2-load-b')
128 const alice = new HyperOverlayV2(storeA, { namespace: 'overlay-v2', destDir: tmpDir('ov2-load-a-dest') })
129 const bob = new HyperOverlayV2(storeB, { namespace: 'overlay-v2', destDir: tmpDir('ov2-load-b-dest') })
130 await alice.ready(); await bob.ready()
131 const extra = []
132 t.teardown(async () => {
133 for (const p of extra) { try { p.destroy() } catch {} }
134 try { await alice.close() } catch {}; try { await bob.close() } catch {}
135 })
136
137 const [da, db] = makeDuplex()
138 const sa = new SecretStream(true, da)
139 const sb = new SecretStream(false, db)
140 await Promise.all([new Promise(r => sa.on('connect', r)), new Promise(r => sb.on('connect', r))])
141 storeA.replicate(sa); storeB.replicate(sb)
142 const muxA = Protomux.from(sa)
143 const muxB = Protomux.from(sb)
144
145 // Each daemon, like production, runs BOTH its own HyperOverlayV2 (id=null) AND
146 // a hyper-deploy DeployServer overlay (id=topic) on the SAME connection. The
147 // two daemons' deploy overlays use DIFFERENT topics (each = its own identity),
148 // matching prod (tabertron's deploy topic ≠ stortron's).
149 const topicA = crypto.randomBytes(32)
150 const topicB = crypto.randomBytes(32)
151 extra.push(await attachDeployStyleOverlay(storeA, muxA, topicA)) // alice's deploy overlay
152 extra.push(await attachDeployStyleOverlay(storeB, muxB, topicB)) // bob's deploy overlay
153 alice.attachProtocol(muxA) // alice's daemon overlay (id=null)
154 bob.attachProtocol(muxB) // bob's daemon overlay (id=null)
155 await settle()
156
157 t.is(alice.peerCount, 1, 'alice daemon-overlay peer present with a 2nd same-protocol channel on the mux')
158 t.is(bob.peerCount, 1, 'bob daemon-overlay peer present with a 2nd same-protocol channel on the mux')
159
160 const content = crypto.randomBytes(2 * 1024 * 1024)
161 const diskPath = path.join(tmpDir('ov2-load-files'), 'f.bin')
162 fs.writeFileSync(diskPath, content)
163 const oid = crypto.data(content).toString('hex')
164 await alice.registerFile('/attachments/' + oid, diskPath, { contentHash: oid, size: content.length })
165
166 const gotN = await bob.fetchFile(oid, { timeout: 8000 })
167 t.ok(gotN, 'bob daemon-overlay (id=null) fetched DESPITE a 2nd hyper-overlay/v2 channel on the mux')
168 if (gotN) t.is(Buffer.compare(gotN.data, content), 0, 'bytes match')
169})