@gethashd/bytecave-browser 1.0.12 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -31,45 +31,47 @@ yarn build
31
31
  - `dist/react/index.js` - React-specific exports
32
32
  - `dist/*.d.ts` - TypeScript type definitions
33
33
 
34
- ## **CRITICAL: Git Workflow**
34
+ ## **CRITICAL: npm Publishing Workflow**
35
35
 
36
36
  ### After Making Changes
37
37
  **YOU MUST FOLLOW THIS WORKFLOW:**
38
38
 
39
- 1. **Build the package**
39
+ 1. **Build and publish to npm**
40
40
  ```bash
41
+ cd bytecave-browser
41
42
  yarn build
43
+ npm publish --access public
42
44
  ```
45
+ - This automatically builds, commits to git, and publishes to npm registry
46
+ - Version is controlled in `package.json`
43
47
 
44
- 2. **Commit changes to git**
45
- ```bash
46
- git add .
47
- git commit -m "Description of changes"
48
- ```
49
-
50
- 3. **Push to git**
51
- ```bash
52
- git push
53
- ```
54
-
55
- 4. **Update dependent packages**
48
+ 2. **Update dependent packages**
56
49
  In `web/` or `dashboard/`:
57
50
  ```bash
58
- yarn upgrade @hashd/bytecave-browser
51
+ yarn upgrade @gethashd/bytecave-browser@<version>
59
52
  ```
53
+ - Use specific version number from `package.json`
54
+ - Example: `yarn upgrade @gethashd/bytecave-browser@1.0.13`
60
55
 
61
56
  ### Why This Is Critical
62
- - `web` and `dashboard` install bytecave-browser from **git**, not from local files
63
- - If you don't push to git, dependent packages will use stale code
64
- - Even after rebuilding, changes won't appear until pushed and upgraded
57
+ - `web` and `dashboard` install bytecave-browser from **npm registry**, not from git
58
+ - If you don't publish to npm, dependent packages will use stale code
59
+ - Even after rebuilding locally, changes won't appear until published and upgraded
65
60
 
66
61
  ### Common Mistake
67
62
  ❌ **WRONG**: Build bytecave-browser → Rebuild web/dashboard → Test
68
- - This will use OLD code because web/dashboard pull from git
63
+ - This will use OLD code because web/dashboard pull from npm
69
64
 
70
- ✅ **CORRECT**: Build bytecave-browser Git commit & push → Upgrade in web/dashboard → Test
65
+ ✅ **CORRECT**: Build & publish to npm → Upgrade in web/dashboard → Test
71
66
  - This ensures latest code is used
72
67
 
68
+ ### Version Management
69
+ - Bump version in `package.json` before publishing
70
+ - Follow semantic versioning: MAJOR.MINOR.PATCH
71
+ - Patch (1.0.x): Bug fixes
72
+ - Minor (1.x.0): New features, backward compatible
73
+ - Major (x.0.0): Breaking changes
74
+
73
75
  ## Key Architecture Concepts
74
76
 
75
77
  ### ByteCaveClient
@@ -98,20 +100,20 @@ Main client class for P2P storage operations:
98
100
 
99
101
  ### Web App (`/web`)
100
102
  - Uses bytecave-browser for vault storage
101
- - Installs from git: `@hashd/bytecave-browser`
102
- - After bytecave-browser changes: `yarn upgrade @hashd/bytecave-browser`
103
+ - Installs from npm: `@gethashd/bytecave-browser`
104
+ - After bytecave-browser changes: `yarn upgrade @gethashd/bytecave-browser@<version>`
103
105
 
104
106
  ### Dashboard (`/dashboard`)
105
107
  - Uses bytecave-browser for test storage
106
- - Installs from git: `@hashd/bytecave-browser`
107
- - After bytecave-browser changes: `yarn upgrade @hashd/bytecave-browser`
108
+ - Installs from npm: `@gethashd/bytecave-browser`
109
+ - After bytecave-browser changes: `yarn upgrade @gethashd/bytecave-browser@<version>`
108
110
 
109
111
  ## Testing Workflow
110
112
 
111
113
  ### After Code Changes
112
- 1. Build: `yarn build`
113
- 2. Commit and push to git
114
- 3. In web/dashboard: `yarn upgrade @hashd/bytecave-browser`
114
+ 1. Bump version in `package.json`
115
+ 2. Build and publish: `yarn build && npm publish --access public`
116
+ 3. In web/dashboard: `yarn upgrade @gethashd/bytecave-browser@<version>`
115
117
  4. Rebuild web/dashboard: `yarn build`
116
118
  5. Hard refresh browser (Cmd+Shift+R) to clear cache
117
119
  6. Test storage functionality
@@ -121,9 +123,9 @@ Main client class for P2P storage operations:
121
123
  #### Stale Code in Web/Dashboard
122
124
  **Symptom**: Changes to bytecave-browser don't appear in web/dashboard
123
125
  **Solution**:
124
- 1. Verify bytecave-browser was pushed to git
125
- 2. Run `yarn upgrade @hashd/bytecave-browser` in web/dashboard
126
- 3. Check `node_modules/@hashd/bytecave-browser/package.json` version/commit
126
+ 1. Verify bytecave-browser was published to npm (check version on npmjs.com)
127
+ 2. Run `yarn upgrade @gethashd/bytecave-browser@<version>` in web/dashboard
128
+ 3. Check `node_modules/@gethashd/bytecave-browser/package.json` version matches
127
129
  4. Hard refresh browser
128
130
 
129
131
  #### Type Errors After Changes
@@ -6120,12 +6120,43 @@ var ByteCaveClient = class {
6120
6120
  }
6121
6121
  });
6122
6122
  await Promise.allSettled(peerPromises);
6123
+ } else {
6124
+ console.log("[ByteCave] Relay returned 0 peers, trying direct addresses from localStorage...");
6125
+ if (this.config.directNodeAddrs && this.config.directNodeAddrs.length > 0) {
6126
+ console.log("[ByteCave] Attempting direct connections to", this.config.directNodeAddrs.length, "cached peers...");
6127
+ for (const addr of this.config.directNodeAddrs) {
6128
+ try {
6129
+ console.log("[ByteCave] Dialing direct address:", addr.slice(0, 60) + "...");
6130
+ const ma = multiaddr(addr);
6131
+ await this.node.dial(ma);
6132
+ console.log("[ByteCave] \u2713 Connected directly to peer");
6133
+ } catch (dialErr) {
6134
+ console.warn("[ByteCave] Direct dial failed:", dialErr.message);
6135
+ }
6136
+ }
6137
+ } else {
6138
+ console.log("[ByteCave] No direct addresses in localStorage");
6139
+ }
6123
6140
  }
6124
6141
  } catch (err) {
6125
- console.warn("[ByteCave] HTTP relay discovery failed, falling back to P2P directory:", err.message);
6142
+ console.warn("[ByteCave] HTTP relay discovery failed:", err.message);
6143
+ if (this.config.directNodeAddrs && this.config.directNodeAddrs.length > 0) {
6144
+ console.log("[ByteCave] Attempting direct connections to cached peers...");
6145
+ for (const addr of this.config.directNodeAddrs) {
6146
+ try {
6147
+ console.log("[ByteCave] Dialing direct address:", addr.slice(0, 60) + "...");
6148
+ const ma = multiaddr(addr);
6149
+ await this.node.dial(ma);
6150
+ console.log("[ByteCave] \u2713 Connected directly to peer");
6151
+ } catch (dialErr) {
6152
+ console.warn("[ByteCave] Direct dial failed:", dialErr.message);
6153
+ }
6154
+ }
6155
+ }
6126
6156
  }
6127
6157
  }
6128
6158
  console.log("[ByteCave] Querying relay for peer directory via P2P...");
6159
+ let gotPeersFromDirectory = false;
6129
6160
  for (const relayAddr of bootstrapPeers) {
6130
6161
  try {
6131
6162
  const parts = relayAddr.split("/p2p/");
@@ -6134,6 +6165,7 @@ var ByteCaveClient = class {
6134
6165
  const directory = await p2pProtocolClient.getPeerDirectoryFromRelay(relayPeerId);
6135
6166
  if (directory && directory.peers.length > 0) {
6136
6167
  console.log("[ByteCave] Got", directory.peers.length, "peers from relay directory");
6168
+ gotPeersFromDirectory = true;
6137
6169
  for (const peer of directory.peers) {
6138
6170
  try {
6139
6171
  console.log("[ByteCave] Dialing peer from directory:", peer.peerId.slice(0, 12) + "...");
@@ -6175,6 +6207,23 @@ var ByteCaveClient = class {
6175
6207
  console.warn("[ByteCave] Failed to get directory from relay:", err.message);
6176
6208
  }
6177
6209
  }
6210
+ if (!gotPeersFromDirectory && this.knownPeers.size === 0) {
6211
+ if (this.config.directNodeAddrs && this.config.directNodeAddrs.length > 0) {
6212
+ console.log("[ByteCave] No peers from relay, attempting direct connections to", this.config.directNodeAddrs.length, "cached peers...");
6213
+ for (const addr of this.config.directNodeAddrs) {
6214
+ try {
6215
+ console.log("[ByteCave] Dialing direct address:", addr.slice(0, 60) + "...");
6216
+ const ma = multiaddr(addr);
6217
+ await this.node.dial(ma);
6218
+ console.log("[ByteCave] \u2713 Connected directly to peer");
6219
+ } catch (dialErr) {
6220
+ console.warn("[ByteCave] Direct dial failed:", dialErr.message);
6221
+ }
6222
+ }
6223
+ } else {
6224
+ console.log("[ByteCave] No direct addresses in localStorage and no relay available");
6225
+ }
6226
+ }
6178
6227
  this.setConnectionState("connected");
6179
6228
  console.log("[ByteCave] Client started", {
6180
6229
  peerId: this.node.peerId.toString(),
package/dist/index.cjs CHANGED
@@ -6173,12 +6173,43 @@ var ByteCaveClient = class {
6173
6173
  }
6174
6174
  });
6175
6175
  await Promise.allSettled(peerPromises);
6176
+ } else {
6177
+ console.log("[ByteCave] Relay returned 0 peers, trying direct addresses from localStorage...");
6178
+ if (this.config.directNodeAddrs && this.config.directNodeAddrs.length > 0) {
6179
+ console.log("[ByteCave] Attempting direct connections to", this.config.directNodeAddrs.length, "cached peers...");
6180
+ for (const addr of this.config.directNodeAddrs) {
6181
+ try {
6182
+ console.log("[ByteCave] Dialing direct address:", addr.slice(0, 60) + "...");
6183
+ const ma = (0, import_multiaddr.multiaddr)(addr);
6184
+ await this.node.dial(ma);
6185
+ console.log("[ByteCave] \u2713 Connected directly to peer");
6186
+ } catch (dialErr) {
6187
+ console.warn("[ByteCave] Direct dial failed:", dialErr.message);
6188
+ }
6189
+ }
6190
+ } else {
6191
+ console.log("[ByteCave] No direct addresses in localStorage");
6192
+ }
6176
6193
  }
6177
6194
  } catch (err) {
6178
- console.warn("[ByteCave] HTTP relay discovery failed, falling back to P2P directory:", err.message);
6195
+ console.warn("[ByteCave] HTTP relay discovery failed:", err.message);
6196
+ if (this.config.directNodeAddrs && this.config.directNodeAddrs.length > 0) {
6197
+ console.log("[ByteCave] Attempting direct connections to cached peers...");
6198
+ for (const addr of this.config.directNodeAddrs) {
6199
+ try {
6200
+ console.log("[ByteCave] Dialing direct address:", addr.slice(0, 60) + "...");
6201
+ const ma = (0, import_multiaddr.multiaddr)(addr);
6202
+ await this.node.dial(ma);
6203
+ console.log("[ByteCave] \u2713 Connected directly to peer");
6204
+ } catch (dialErr) {
6205
+ console.warn("[ByteCave] Direct dial failed:", dialErr.message);
6206
+ }
6207
+ }
6208
+ }
6179
6209
  }
6180
6210
  }
6181
6211
  console.log("[ByteCave] Querying relay for peer directory via P2P...");
6212
+ let gotPeersFromDirectory = false;
6182
6213
  for (const relayAddr of bootstrapPeers) {
6183
6214
  try {
6184
6215
  const parts = relayAddr.split("/p2p/");
@@ -6187,6 +6218,7 @@ var ByteCaveClient = class {
6187
6218
  const directory = await p2pProtocolClient.getPeerDirectoryFromRelay(relayPeerId);
6188
6219
  if (directory && directory.peers.length > 0) {
6189
6220
  console.log("[ByteCave] Got", directory.peers.length, "peers from relay directory");
6221
+ gotPeersFromDirectory = true;
6190
6222
  for (const peer of directory.peers) {
6191
6223
  try {
6192
6224
  console.log("[ByteCave] Dialing peer from directory:", peer.peerId.slice(0, 12) + "...");
@@ -6228,6 +6260,23 @@ var ByteCaveClient = class {
6228
6260
  console.warn("[ByteCave] Failed to get directory from relay:", err.message);
6229
6261
  }
6230
6262
  }
6263
+ if (!gotPeersFromDirectory && this.knownPeers.size === 0) {
6264
+ if (this.config.directNodeAddrs && this.config.directNodeAddrs.length > 0) {
6265
+ console.log("[ByteCave] No peers from relay, attempting direct connections to", this.config.directNodeAddrs.length, "cached peers...");
6266
+ for (const addr of this.config.directNodeAddrs) {
6267
+ try {
6268
+ console.log("[ByteCave] Dialing direct address:", addr.slice(0, 60) + "...");
6269
+ const ma = (0, import_multiaddr.multiaddr)(addr);
6270
+ await this.node.dial(ma);
6271
+ console.log("[ByteCave] \u2713 Connected directly to peer");
6272
+ } catch (dialErr) {
6273
+ console.warn("[ByteCave] Direct dial failed:", dialErr.message);
6274
+ }
6275
+ }
6276
+ } else {
6277
+ console.log("[ByteCave] No direct addresses in localStorage and no relay available");
6278
+ }
6279
+ }
6231
6280
  this.setConnectionState("connected");
6232
6281
  console.log("[ByteCave] Client started", {
6233
6282
  peerId: this.node.peerId.toString(),
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  useHashdImage,
14
14
  useHashdMedia,
15
15
  useHashdUrl
16
- } from "./chunk-XC5Z2TQH.js";
16
+ } from "./chunk-ZFKOXO6W.js";
17
17
  import {
18
18
  clearHashdCache,
19
19
  createHashdUrl,
@@ -8,7 +8,7 @@ import {
8
8
  useHashdImage,
9
9
  useHashdMedia,
10
10
  useHashdUrl
11
- } from "../chunk-XC5Z2TQH.js";
11
+ } from "../chunk-ZFKOXO6W.js";
12
12
  import "../chunk-EEZWRIUI.js";
13
13
  export {
14
14
  HashdAudio,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gethashd/bytecave-browser",
3
- "version": "1.0.12",
3
+ "version": "1.0.15",
4
4
  "description": "ByteCave browser client for WebRTC P2P connections to storage nodes",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
package/src/client.ts CHANGED
@@ -192,14 +192,48 @@ export class ByteCaveClient {
192
192
 
193
193
  // Wait for all peer connections and health queries to complete
194
194
  await Promise.allSettled(peerPromises);
195
+ } else {
196
+ // Relay returned 0 peers - try direct addresses from localStorage
197
+ console.log('[ByteCave] Relay returned 0 peers, trying direct addresses from localStorage...');
198
+ if (this.config.directNodeAddrs && this.config.directNodeAddrs.length > 0) {
199
+ console.log('[ByteCave] Attempting direct connections to', this.config.directNodeAddrs.length, 'cached peers...');
200
+ for (const addr of this.config.directNodeAddrs) {
201
+ try {
202
+ console.log('[ByteCave] Dialing direct address:', addr.slice(0, 60) + '...');
203
+ const ma = multiaddr(addr);
204
+ await this.node!.dial(ma as any);
205
+ console.log('[ByteCave] ✓ Connected directly to peer');
206
+ } catch (dialErr: any) {
207
+ console.warn('[ByteCave] Direct dial failed:', dialErr.message);
208
+ }
209
+ }
210
+ } else {
211
+ console.log('[ByteCave] No direct addresses in localStorage');
212
+ }
195
213
  }
196
214
  } catch (err: any) {
197
- console.warn('[ByteCave] HTTP relay discovery failed, falling back to P2P directory:', err.message);
215
+ console.warn('[ByteCave] HTTP relay discovery failed:', err.message);
216
+
217
+ // Fallback: Try direct node addresses from localStorage
218
+ if (this.config.directNodeAddrs && this.config.directNodeAddrs.length > 0) {
219
+ console.log('[ByteCave] Attempting direct connections to cached peers...');
220
+ for (const addr of this.config.directNodeAddrs) {
221
+ try {
222
+ console.log('[ByteCave] Dialing direct address:', addr.slice(0, 60) + '...');
223
+ const ma = multiaddr(addr);
224
+ await this.node!.dial(ma as any);
225
+ console.log('[ByteCave] ✓ Connected directly to peer');
226
+ } catch (dialErr: any) {
227
+ console.warn('[ByteCave] Direct dial failed:', dialErr.message);
228
+ }
229
+ }
230
+ }
198
231
  }
199
232
  }
200
233
 
201
234
  // Fallback: Query relay for peer directory via P2P protocol
202
235
  console.log('[ByteCave] Querying relay for peer directory via P2P...');
236
+ let gotPeersFromDirectory = false;
203
237
  for (const relayAddr of bootstrapPeers) {
204
238
  try {
205
239
  // Extract relay peer ID from multiaddr
@@ -210,6 +244,7 @@ export class ByteCaveClient {
210
244
  const directory = await p2pProtocolClient.getPeerDirectoryFromRelay(relayPeerId);
211
245
  if (directory && directory.peers.length > 0) {
212
246
  console.log('[ByteCave] Got', directory.peers.length, 'peers from relay directory');
247
+ gotPeersFromDirectory = true;
213
248
 
214
249
  // Dial each peer and fetch health data
215
250
  for (const peer of directory.peers) {
@@ -260,6 +295,25 @@ export class ByteCaveClient {
260
295
  }
261
296
  }
262
297
 
298
+ // Final fallback: If no peers from relay (HTTP or P2P), try direct addresses
299
+ if (!gotPeersFromDirectory && this.knownPeers.size === 0) {
300
+ if (this.config.directNodeAddrs && this.config.directNodeAddrs.length > 0) {
301
+ console.log('[ByteCave] No peers from relay, attempting direct connections to', this.config.directNodeAddrs.length, 'cached peers...');
302
+ for (const addr of this.config.directNodeAddrs) {
303
+ try {
304
+ console.log('[ByteCave] Dialing direct address:', addr.slice(0, 60) + '...');
305
+ const ma = multiaddr(addr);
306
+ await this.node!.dial(ma as any);
307
+ console.log('[ByteCave] ✓ Connected directly to peer');
308
+ } catch (dialErr: any) {
309
+ console.warn('[ByteCave] Direct dial failed:', dialErr.message);
310
+ }
311
+ }
312
+ } else {
313
+ console.log('[ByteCave] No direct addresses in localStorage and no relay available');
314
+ }
315
+ }
316
+
263
317
  this.setConnectionState('connected');
264
318
  console.log('[ByteCave] Client started', {
265
319
  peerId: this.node.peerId.toString(),