dignity.js 0.3.0 → 0.5.1

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.
Files changed (43) hide show
  1. package/README.md +142 -4
  2. package/dist/dignity.cjs.js +768 -20
  3. package/dist/dignity.cjs.js.map +4 -4
  4. package/dist/dignity.esm.js +768 -20
  5. package/dist/dignity.esm.js.map +3 -3
  6. package/dist/dignity.min.js +18 -18
  7. package/docs/assets/dignity.esm.js +11205 -0
  8. package/docs/assets/docs.js +47 -0
  9. package/docs/assets/favicon.svg +8 -0
  10. package/docs/assets/highlight/github-dark.min.css +10 -0
  11. package/docs/assets/highlight/github.min.css +10 -0
  12. package/docs/assets/highlight/highlight.min.js +1244 -0
  13. package/docs/assets/styles.css +449 -38
  14. package/docs/chess/assets/chess-app.js +58022 -0
  15. package/docs/chess/assets/chess-app.js.map +7 -0
  16. package/docs/chess/assets/chess.css +584 -0
  17. package/docs/chess/favicon.ico +0 -0
  18. package/docs/chess/index.html +16 -0
  19. package/docs/chess/src/App.jsx +128 -0
  20. package/docs/chess/src/components/Board3D.jsx +364 -0
  21. package/docs/chess/src/components/GameView.jsx +847 -0
  22. package/docs/chess/src/components/JoinGate.jsx +68 -0
  23. package/docs/chess/src/components/LinkPanel.jsx +132 -0
  24. package/docs/chess/src/components/Lobby.jsx +154 -0
  25. package/docs/chess/src/components/MovePanel.jsx +123 -0
  26. package/docs/chess/src/lib/audio.js +50 -0
  27. package/docs/chess/src/lib/dignitySetup.js +42 -0
  28. package/docs/chess/src/lib/links.js +124 -0
  29. package/docs/chess/src/lib/localGames.js +160 -0
  30. package/docs/chess/src/lib/p2pDebug.js +192 -0
  31. package/docs/chess/src/main.jsx +5 -0
  32. package/docs/favicon.ico +0 -0
  33. package/docs/index.html +605 -81
  34. package/docs/openapi-like.json +74 -7
  35. package/examples/decentralized-chess-lite.js +52 -30
  36. package/package.json +30 -4
  37. package/src/core/dignity-p2p.js +466 -15
  38. package/src/index.js +8 -0
  39. package/src/network/peerjs-network.js +234 -0
  40. package/src/persistence/indexeddb-persistence.js +184 -0
  41. package/src/react/index.js +256 -0
  42. package/src/signaling/parse-peerjs-url.js +24 -0
  43. package/src/signaling/peerjs-signaling-provider.js +2 -8
package/docs/index.html CHANGED
@@ -3,27 +3,111 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>dignity.js v0.1.0 docs</title>
6
+ <meta name="description" content="dignity.js v0.5.1 — REST-like P2P object API for decentralized JavaScript applications." />
7
+ <title>dignity.js · Documentation</title>
8
+ <link rel="icon" href="./assets/favicon.svg" type="image/svg+xml" />
9
+ <link rel="icon" href="./favicon.ico" sizes="32x32" />
10
+ <link rel="stylesheet" href="./assets/highlight/github.min.css" media="(prefers-color-scheme: light)" />
11
+ <link rel="stylesheet" href="./assets/highlight/github-dark.min.css" media="(prefers-color-scheme: dark)" />
7
12
  <link rel="stylesheet" href="./assets/styles.css" />
8
13
  </head>
9
14
  <body>
10
- <main>
11
- <h1>dignity.js documentation</h1>
12
- <p class="subtitle">Version 0.1.0 - P2P object API for decentralized JavaScript applications</p>
13
-
14
- <section>
15
- <h2>Professional docs layout (recommended)</h2>
16
- <ul>
17
- <li><strong>Monorepo style:</strong> <code>apps/docs</code> (Next.js/Nextra or Docusaurus) + versioned routes.</li>
18
- <li><strong>Library style:</strong> top-level <code>docs/</code> for public docs and examples.</li>
19
- <li><strong>API reference:</strong> generated from source comments and published online.</li>
20
- <li><strong>Examples:</strong> runnable samples under <code>examples/</code> or linked demos.</li>
21
- </ul>
22
- </section>
23
-
24
- <section>
25
- <h2>Quick start</h2>
26
- <pre><code>const {
15
+ <header class="site-header">
16
+ <a class="site-header__brand" href="#overview">
17
+ <img src="./assets/dignity-logo.svg" alt="" width="344" height="80" />
18
+ <!-- <span>dignity.js</span> -->
19
+ <span class="site-header__version">v0.5.1</span>
20
+ </a>
21
+ <div class="site-header__links">
22
+ <a href="https://www.npmjs.com/package/dignity.js" target="_blank" rel="noopener noreferrer">npm</a>
23
+ <a href="https://github.com/jose-compu/dignity.js" target="_blank" rel="noopener noreferrer">GitHub</a>
24
+ <a href="./chess/index.html">3D Chess</a>
25
+ <a href="./openapi-like.json">API JSON</a>
26
+ </div>
27
+ <button class="menu-toggle" type="button" aria-label="Toggle navigation">Menu</button>
28
+ </header>
29
+
30
+ <div class="layout">
31
+ <aside class="sidebar">
32
+ <div class="sidebar__group">
33
+ <div class="sidebar__label">Getting started</div>
34
+ <nav>
35
+ <a href="#overview">Overview</a>
36
+ <a href="#installation">Installation</a>
37
+ <a href="#quick-start">Quick start</a>
38
+ <a href="#browser">Browser usage</a>
39
+ </nav>
40
+ </div>
41
+ <div class="sidebar__group">
42
+ <div class="sidebar__label">Guide</div>
43
+ <nav>
44
+ <a href="#object-api">Object API</a>
45
+ <a href="#discovery">Room discovery</a>
46
+ <a href="#messaging">Direct messaging</a>
47
+ <a href="#concurrency">Concurrency</a>
48
+ <a href="#security">Security model</a>
49
+ <a href="#persistence">IndexedDB persistence</a>
50
+ <a href="#react">React hooks</a>
51
+ <a href="#signaling">Signaling</a>
52
+ <a href="./chess/index.html">3D Chess demo</a>
53
+ </nav>
54
+ </div>
55
+ <div class="sidebar__group">
56
+ <div class="sidebar__label">Reference</div>
57
+ <nav>
58
+ <a href="#api-reference">API reference</a>
59
+ <a href="#events">Events</a>
60
+ <a href="#exports">Package exports</a>
61
+ <a href="#examples">Examples</a>
62
+ <a href="#development">Development</a>
63
+ </nav>
64
+ </div>
65
+ </aside>
66
+
67
+ <main class="content">
68
+ <div class="content__inner">
69
+ <section id="overview" class="section">
70
+ <h1 class="page-title">Documentation</h1>
71
+ <p class="lead">
72
+ <strong>dignity.js</strong> is a REST-like P2P object API for decentralized JavaScript
73
+ applications. Synchronize shared objects across browsers with owner authorization,
74
+ scoped broadcast encryption, and built-in anti-abuse controls.
75
+ </p>
76
+
77
+ <div class="card-grid">
78
+ <article class="card">
79
+ <h3>Object CRUD</h3>
80
+ <p><code>create</code>, <code>read</code>, <code>list</code>, <code>update</code>, <code>remove</code> over P2P replication.</p>
81
+ </article>
82
+ <article class="card">
83
+ <h3>Security default-on</h3>
84
+ <p>Signing, encryption, Sloth VDF proof-of-work, and automatic peer bans.</p>
85
+ </article>
86
+ <article class="card">
87
+ <h3>Browser-first</h3>
88
+ <p>IIFE, ESM, and CJS bundles. Optional IndexedDB persistence and React hooks.</p>
89
+ </article>
90
+ </div>
91
+ </section>
92
+
93
+ <section id="installation" class="section">
94
+ <h2>Installation</h2>
95
+ <div class="code-block">
96
+ <span class="code-block__label">npm</span>
97
+ <pre><code class="language-bash">npm install dignity.js</code></pre>
98
+ </div>
99
+ <p>For React hooks, install React 18+ as a peer dependency:</p>
100
+ <div class="code-block">
101
+ <pre><code class="language-bash">npm install dignity.js react react-dom</code></pre>
102
+ </div>
103
+ </section>
104
+
105
+ <section id="quick-start" class="section">
106
+ <h2>Quick start</h2>
107
+ <p>Create a node, join a room, and replicate an object between two peers:</p>
108
+ <div class="code-block">
109
+ <span class="code-block__label">Node.js / ESM</span>
110
+ <pre><code class="language-javascript">const {
27
111
  DignityP2P,
28
112
  InMemoryNetworkHub,
29
113
  InMemoryNetworkAdapter
@@ -33,52 +117,342 @@ const hub = new InMemoryNetworkHub();
33
117
 
34
118
  const alice = new DignityP2P({
35
119
  nodeId: 'alice',
36
- networkAdapter: new InMemoryNetworkAdapter(hub)
120
+ networkAdapter: new InMemoryNetworkAdapter(hub),
121
+ security: {
122
+ appPassword: 'shared-out-of-band-password',
123
+ powSteps: 22
124
+ }
125
+ });
126
+
127
+ const bob = new DignityP2P({
128
+ nodeId: 'bob',
129
+ networkAdapter: new InMemoryNetworkAdapter(hub),
130
+ security: {
131
+ appPassword: 'shared-out-of-band-password',
132
+ powSteps: 22
133
+ }
37
134
  });
38
135
 
39
136
  await alice.start();
40
- await alice.create('notes', { title: 'hello world' }, { id: 'note-1' });
41
- const note = alice.read('notes', 'note-1');</code></pre>
42
- </section>
43
-
44
- <section>
45
- <h2>REST-like object API</h2>
46
- <ul>
47
- <li><code>create(collection, data, options)</code> -> owner is the creator.</li>
48
- <li><code>read(collection, id)</code> -> returns object or <code>null</code>.</li>
49
- <li><code>list(collection, options)</code> -> list active objects (or include deleted markers).</li>
50
- <li><code>update(collection, id, patch)</code> -> only object owner can update.</li>
51
- <li><code>remove(collection, id)</code> -> only object owner can delete.</li>
52
- </ul>
53
- </section>
54
-
55
- <section>
56
- <h2>Room / team discovery</h2>
57
- <pre><code>await node.joinDiscovery('team:red', {\n metadata: { nickname: 'alice' },\n heartbeatIntervalMs: 15000,\n ttlMs: 45000\n});\n\nconst peers = node.listPeers('team:red', { includeSelf: false });\nawait node.leaveDiscovery('team:red');</code></pre>
58
- </section>
59
-
60
- <section>
61
- <h2>Security defaults (enabled)</h2>
62
- <ul>
63
- <li><strong>Signing:</strong> every message is signed by sender keypair.</li>
64
- <li><strong>Broadcast encryption:</strong> encrypted using shared <code>appPassword</code>.</li>
65
- <li><strong>Direct encryption:</strong> encrypted with recipient public key.</li>
66
- <li><strong>PoW:</strong> Sloth VDF proof per message, default <code>powSteps: 22</code> (~1000ms on this machine).</li>
67
- <li><strong>Peer bans:</strong> invalid signature or invalid PoW bans sender for 48h by default.</li>
68
- </ul>
69
- <pre><code>const node = new DignityP2P({\n nodeId: 'alice',\n networkAdapter,\n security: {\n appPassword: 'shared-out-of-band-password',\n powTargetMs: 1000,\n signingEnabled: true,\n encryptionEnabled: true,\n powEnabled: true\n }\n});</code></pre>
70
- <pre><code>const coopNode = new DignityP2P({\n nodeId: 'alice',\n networkAdapter,\n security: {\n appPassword: 'global-fallback-password',\n broadcastPasswords: {\n 'coop:red': 'red-team-password',\n 'coop:blue': 'blue-team-password'\n }\n }\n});\n\nawait coopNode.create('matches', { mode: 'coop' }, {\n id: 'match-1',\n broadcastScope: 'coop:red'\n});</code></pre>
71
- </section>
72
-
73
- <section>
74
- <h2>Signaling defaults and customization</h2>
75
- <pre><code>const {
137
+ await bob.start();
138
+
139
+ await alice.joinDiscovery('main', { metadata: { nickname: 'alice' } });
140
+ await bob.joinDiscovery('main', { metadata: { nickname: 'bob' } });
141
+
142
+ await alice.create('notes', { title: 'hello decentralized world' }, {
143
+ id: 'note-1',
144
+ broadcastScope: 'main'
145
+ });
146
+
147
+ console.log(bob.read('notes', 'note-1'));
148
+
149
+ await alice.leaveDiscovery('main');
150
+ await bob.leaveDiscovery('main');
151
+ await alice.stop();
152
+ await bob.stop();</code></pre>
153
+ </div>
154
+ <div class="callout">
155
+ <strong>In-memory adapter</strong>
156
+ <code>InMemoryNetworkAdapter</code> is for tests and local demos. Production browser apps use a WebRTC network adapter (see project issues for the browser transport roadmap).
157
+ </div>
158
+ </section>
159
+
160
+ <section id="browser" class="section">
161
+ <h2>Browser usage</h2>
162
+ <p>Pre-built bundles are published to npm and available via CDN:</p>
163
+ <div class="code-block">
164
+ <span class="code-block__label">IIFE (global <code>DignityJS</code>)</span>
165
+ <pre><code class="language-xml">&lt;script src="https://unpkg.com/dignity.js/dist/dignity.min.js"&gt;&lt;/script&gt;
166
+ &lt;script&gt;
167
+ const { DignityP2P } = DignityJS;
168
+ &lt;/script&gt;</code></pre>
169
+ </div>
170
+ <div class="table-wrap">
171
+ <table>
172
+ <thead>
173
+ <tr>
174
+ <th>Bundle</th>
175
+ <th>Path</th>
176
+ <th>Format</th>
177
+ </tr>
178
+ </thead>
179
+ <tbody>
180
+ <tr>
181
+ <td>Minified browser</td>
182
+ <td><code>dist/dignity.min.js</code></td>
183
+ <td>IIFE</td>
184
+ </tr>
185
+ <tr>
186
+ <td>ES modules</td>
187
+ <td><code>dist/dignity.esm.js</code></td>
188
+ <td>ESM</td>
189
+ </tr>
190
+ <tr>
191
+ <td>Node / CommonJS</td>
192
+ <td><code>dist/dignity.cjs.js</code></td>
193
+ <td>CJS</td>
194
+ </tr>
195
+ </tbody>
196
+ </table>
197
+ </div>
198
+ </section>
199
+
200
+ <section id="object-api" class="section">
201
+ <h2>Object API</h2>
202
+ <p>
203
+ The core API mirrors REST semantics. Each object belongs to a <strong>collection</strong>.
204
+ The peer that creates an object becomes its <strong>owner</strong> — only the owner may update or delete it.
205
+ </p>
206
+
207
+ <div class="table-wrap">
208
+ <table>
209
+ <thead>
210
+ <tr>
211
+ <th>Method</th>
212
+ <th>Description</th>
213
+ <th>Authorization</th>
214
+ </tr>
215
+ </thead>
216
+ <tbody>
217
+ <tr>
218
+ <td><code>create(collection, data, options?)</code></td>
219
+ <td>Create a new object. Returns the normalized record.</td>
220
+ <td>Creator becomes owner</td>
221
+ </tr>
222
+ <tr>
223
+ <td><code>read(collection, id)</code></td>
224
+ <td>Read one object, or <code>null</code> if missing/deleted.</td>
225
+ <td>—</td>
226
+ </tr>
227
+ <tr>
228
+ <td><code>list(collection, options?)</code></td>
229
+ <td>List objects. Set <code>includeDeleted: true</code> for tombstones.</td>
230
+ <td>—</td>
231
+ </tr>
232
+ <tr>
233
+ <td><code>update(collection, id, patch, options?)</code></td>
234
+ <td>Merge <code>patch</code> into object data and increment version.</td>
235
+ <td>Owner only</td>
236
+ </tr>
237
+ <tr>
238
+ <td><code>updateWithRetry(collection, id, patchFn, options?)</code></td>
239
+ <td>Read-modify-write with automatic retry on version conflicts.</td>
240
+ <td>Owner only</td>
241
+ </tr>
242
+ <tr>
243
+ <td><code>remove(collection, id, options?)</code></td>
244
+ <td>Soft-delete the object (tombstone).</td>
245
+ <td>Owner only</td>
246
+ </tr>
247
+ </tbody>
248
+ </table>
249
+ </div>
250
+
251
+ <h3>Scoped broadcast</h3>
252
+ <p>Pass <code>broadcastScope</code> on create/update to select a team or room password namespace:</p>
253
+ <div class="code-block">
254
+ <pre><code class="language-javascript">await node.create('matches', { mode: 'coop' }, {
255
+ id: 'm-1',
256
+ broadcastScope: 'coop:red'
257
+ });</code></pre>
258
+ </div>
259
+ <p>Configure per-scope passwords via <code>security.broadcastPasswords</code>.</p>
260
+ </section>
261
+
262
+ <section id="discovery" class="section">
263
+ <h2>Room / team discovery</h2>
264
+ <p>Discover active peers in a named scope (room, team, raid, etc.):</p>
265
+ <div class="code-block">
266
+ <pre><code class="language-javascript">await node.joinDiscovery('team:red', {
267
+ metadata: { nickname: 'alice' },
268
+ heartbeatIntervalMs: 15000,
269
+ ttlMs: 45000
270
+ });
271
+
272
+ const peers = node.listPeers('team:red', { includeSelf: false });
273
+
274
+ await node.leaveDiscovery('team:red');</code></pre>
275
+ </div>
276
+ </section>
277
+
278
+ <section id="messaging" class="section">
279
+ <h2>Direct secure messaging</h2>
280
+ <p>Send end-to-end encrypted messages to a specific peer:</p>
281
+ <div class="code-block">
282
+ <pre><code class="language-javascript">alice.registerPeerPublicKey('bob', bob.getPublicKey());
283
+ bob.registerPeerPublicKey('alice', alice.getPublicKey());
284
+
285
+ await alice.sendDirectMessage('bob', 'dm', { text: 'private payload' });</code></pre>
286
+ </div>
287
+ </section>
288
+
289
+ <section id="concurrency" class="section">
290
+ <h2>Optimistic concurrency</h2>
291
+ <p>
292
+ Every update carries a monotonic <code>version</code>. Stale operations are rejected when
293
+ <code>baseVersion</code> does not match. Listen for <code>conflict</code> events or use
294
+ built-in helpers:
295
+ </p>
296
+ <div class="code-block">
297
+ <pre><code class="language-javascript">node.on('conflict', (event) => {
298
+ // event.phase: 'local' | 'remote'
299
+ console.log(event.expectedVersion, event.currentVersion);
300
+ });
301
+
302
+ // Fail fast on stale local writes
303
+ await node.update('games', 'g1', { score: 10 }, { expectedVersion: 3 });
304
+
305
+ // Automatic retry for read-modify-write loops
306
+ await node.updateWithRetry('games', 'g1', (current) => ({
307
+ score: current.data.score + 1
308
+ }));</code></pre>
309
+ </div>
310
+ </section>
311
+
312
+ <section id="security" class="section">
313
+ <h2>Security model</h2>
314
+ <p>All security features are enabled by default. Configure via the <code>security</code> constructor option.</p>
315
+
316
+ <div class="table-wrap">
317
+ <table>
318
+ <thead>
319
+ <tr>
320
+ <th>Feature</th>
321
+ <th>Default</th>
322
+ <th>Details</th>
323
+ </tr>
324
+ </thead>
325
+ <tbody>
326
+ <tr>
327
+ <td>Signing</td>
328
+ <td>On</td>
329
+ <td>Ed25519 signature on every message</td>
330
+ </tr>
331
+ <tr>
332
+ <td>Broadcast encryption</td>
333
+ <td>On</td>
334
+ <td>AES secretbox; PBKDF2-SHA256 key from <code>appPassword</code> (100k iterations)</td>
335
+ </tr>
336
+ <tr>
337
+ <td>Direct encryption</td>
338
+ <td>On</td>
339
+ <td>NaCl box (X25519) — true E2E to recipient public key</td>
340
+ </tr>
341
+ <tr>
342
+ <td>Proof-of-work</td>
343
+ <td>On</td>
344
+ <td>Sloth VDF; default <code>powSteps: 22</code> (~1s on reference hardware)</td>
345
+ </tr>
346
+ <tr>
347
+ <td>Peer bans</td>
348
+ <td>On</td>
349
+ <td>Invalid signature or PoW → 48h ban (configurable)</td>
350
+ </tr>
351
+ </tbody>
352
+ </table>
353
+ </div>
354
+
355
+ <div class="callout callout--warn">
356
+ <strong>Broadcast mode is not E2E</strong>
357
+ All peers that know the scope password can decrypt broadcast traffic. Use direct mode for sensitive per-peer data.
358
+ </div>
359
+
360
+ <h3>Security configuration</h3>
361
+ <div class="code-block">
362
+ <pre><code class="language-javascript">const node = new DignityP2P({
363
+ nodeId: 'alice',
364
+ networkAdapter,
365
+ security: {
366
+ appPassword: 'shared-out-of-band-password',
367
+ broadcastPasswords: {
368
+ 'coop:red': 'red-team-secret',
369
+ 'coop:blue': 'blue-team-secret'
370
+ },
371
+ powSteps: 22,
372
+ kdfIterations: 100000,
373
+ banDurationMs: 48 * 60 * 60 * 1000
374
+ }
375
+ });</code></pre>
376
+ </div>
377
+ </section>
378
+
379
+ <section id="persistence" class="section">
380
+ <h2>IndexedDB persistence</h2>
381
+ <p>Survive page reloads by persisting replicated object state to IndexedDB:</p>
382
+ <div class="code-block">
383
+ <pre><code class="language-javascript">const { DignityP2P, IndexedDBPersistence } = require('dignity.js');
384
+
385
+ const node = new DignityP2P({ nodeId, networkAdapter, security });
386
+ const persistence = new IndexedDBPersistence({
387
+ dbName: 'my-app',
388
+ collections: ['games', 'matches'] // omit to persist all collections
389
+ });
390
+
391
+ await node.start();
392
+ await persistence.attach(node);
393
+
394
+ // Later
395
+ await persistence.detach();</code></pre>
396
+ </div>
397
+ </section>
398
+
399
+ <section id="react" class="section">
400
+ <h2>React hooks</h2>
401
+ <p>Optional integration via <code>dignity.js/react</code> (requires React ≥ 18):</p>
402
+ <div class="code-block">
403
+ <pre><code class="language-javascript">import { useDignity, useCollection, usePeers } from 'dignity.js/react';
404
+
405
+ function Room() {
406
+ const { node, status, error } = useDignity(config);
407
+ const games = useCollection(node, 'games');
408
+ const peers = usePeers(node, 'room:chess', { includeSelf: false });
409
+
410
+ if (status === 'starting') return &lt;p&gt;Connecting…&lt;/p&gt;;
411
+ if (error) return &lt;p&gt;Error: {error.message}&lt;/p&gt;;
412
+
413
+ return (
414
+ &lt;pre&gt;{JSON.stringify({ status, games, peers }, null, 2)}&lt;/pre&gt;
415
+ );
416
+ }</code></pre>
417
+ </div>
418
+
419
+ <div class="table-wrap">
420
+ <table>
421
+ <thead>
422
+ <tr>
423
+ <th>Hook</th>
424
+ <th>Returns</th>
425
+ </tr>
426
+ </thead>
427
+ <tbody>
428
+ <tr>
429
+ <td><code>useDignity(config)</code></td>
430
+ <td><code>{ node, status, error }</code> — starts/stops node on mount/unmount</td>
431
+ </tr>
432
+ <tr>
433
+ <td><code>useCollection(node, name)</code></td>
434
+ <td>Reactive array from <code>node.list(name)</code></td>
435
+ </tr>
436
+ <tr>
437
+ <td><code>usePeers(node, scope, options?)</code></td>
438
+ <td>Reactive peer list from discovery</td>
439
+ </tr>
440
+ </tbody>
441
+ </table>
442
+ </div>
443
+ </section>
444
+
445
+ <section id="signaling" class="section">
446
+ <h2>Signaling</h2>
447
+ <p>Default PeerJS-compatible signaling endpoints are included. Customize with <code>createDefaultSignalingPool</code>:</p>
448
+ <div class="code-block">
449
+ <pre><code class="language-javascript">const {
76
450
  createDefaultSignalingPool,
77
451
  WebSocketSignalingProvider
78
452
  } = require('dignity.js');
79
453
 
80
454
  const pool = createDefaultSignalingPool({
81
- cloudflareUrls: ['wss://your-cloudflare-endpoint.example'],
455
+ cloudflareUrls: ['wss://your-endpoint.example/peerjs?key=peerjs'],
82
456
  fallbackUrls: ['wss://relay-a.example', 'wss://relay-b.example'],
83
457
  customProviders: [
84
458
  new WebSocketSignalingProvider({
@@ -88,30 +462,180 @@ const pool = createDefaultSignalingPool({
88
462
  })
89
463
  ]
90
464
  });</code></pre>
91
- <p>
92
- Machine-readable API metadata is available in
93
- <a href="./openapi-like.json">openapi-like.json</a>.
94
- </p>
95
- </section>
96
-
97
- <section>
98
- <h2>Minimal examples</h2>
99
- <ul>
100
- <li><code>examples/decentralized-tictactoe.js</code> - replicated board state and owner authorization.</li>
101
- <li><code>examples/decentralized-chess-lite.js</code> - replicated move history with a compact board model.</li>
102
- </ul>
103
- <pre><code>npm run example:tictactoe\nnpm run example:chess</code></pre>
104
- </section>
105
-
106
- <section>
107
- <h2>Publish-ready browser bundles</h2>
108
- <ul>
109
- <li><code>dist/dignity.min.js</code> - minified browser IIFE bundle (global <code>DignityJS</code>).</li>
110
- <li><code>dist/dignity.esm.js</code> - browser ESM bundle.</li>
111
- <li><code>dist/dignity.cjs.js</code> - Node/CommonJS bundle.</li>
112
- </ul>
113
- <pre><code>npm test\nnpm run build\nnpm publish --access public</code></pre>
114
- </section>
115
- </main>
465
+ </div>
466
+ <p>Default public endpoints:</p>
467
+ <ul>
468
+ <li><code>wss://peerjs.92k.de/peerjs?key=peerjs</code></li>
469
+ <li><code>wss://0.peerjs.com/peerjs?key=peerjs</code></li>
470
+ </ul>
471
+ </section>
472
+
473
+ <section id="api-reference" class="section">
474
+ <h2>API reference</h2>
475
+ <p>Primary class: <code>DignityP2P</code></p>
476
+
477
+ <h3>Constructor</h3>
478
+ <div class="code-block">
479
+ <pre><code class="language-javascript">new DignityP2P({
480
+ nodeId, // required — unique peer identifier
481
+ networkAdapter, // required — transport implementation
482
+ security, // optional — MessageSecurityService options
483
+ now, // optional clock injection (tests)
484
+ idGenerator // optional custom operation id factory
485
+ })</code></pre>
486
+ </div>
487
+
488
+ <h3>Lifecycle</h3>
489
+ <div class="table-wrap">
490
+ <table>
491
+ <thead>
492
+ <tr>
493
+ <th>Method</th>
494
+ <th>Description</th>
495
+ </tr>
496
+ </thead>
497
+ <tbody>
498
+ <tr><td><code>start()</code></td><td>Connect adapter and begin receiving messages</td></tr>
499
+ <tr><td><code>stop()</code></td><td>Leave discovery scopes and disconnect</td></tr>
500
+ <tr><td><code>getPublicKey()</code></td><td>Return this node's public key bundle</td></tr>
501
+ <tr><td><code>registerPeerPublicKey(id, key)</code></td><td>Trust a remote peer's keys</td></tr>
502
+ </tbody>
503
+ </table>
504
+ </div>
505
+
506
+ <p>
507
+ Machine-readable metadata:
508
+ <a href="./openapi-like.json">openapi-like.json</a>
509
+ </p>
510
+ </section>
511
+
512
+ <section id="events" class="section">
513
+ <h2>Events</h2>
514
+ <p><code>DignityP2P</code> extends <code>EventEmitter</code>. Common events:</p>
515
+ <div class="table-wrap">
516
+ <table>
517
+ <thead>
518
+ <tr>
519
+ <th>Event</th>
520
+ <th>Payload</th>
521
+ </tr>
522
+ </thead>
523
+ <tbody>
524
+ <tr>
525
+ <td><span class="tag tag--event">change</span></td>
526
+ <td><code>{ kind, collection, id }</code> — object created, updated, or deleted</td>
527
+ </tr>
528
+ <tr>
529
+ <td><span class="tag tag--event">conflict</span></td>
530
+ <td><code>{ kind, collection, id, expectedVersion, currentVersion, phase }</code></td>
531
+ </tr>
532
+ <tr>
533
+ <td><span class="tag tag--event">peerdiscovered</span></td>
534
+ <td><code>{ scope, peerId, metadata }</code></td>
535
+ </tr>
536
+ <tr>
537
+ <td><span class="tag tag--event">peerleft</span></td>
538
+ <td><code>{ scope, peerId, reason }</code></td>
539
+ </tr>
540
+ <tr>
541
+ <td><span class="tag tag--event">message</span></td>
542
+ <td><code>{ senderId, targetId, type, payload }</code> — custom decrypted messages</td>
543
+ </tr>
544
+ <tr>
545
+ <td><span class="tag tag--event">securityerror</span></td>
546
+ <td><code>{ senderId, error }</code></td>
547
+ </tr>
548
+ <tr>
549
+ <td><span class="tag tag--event">warning</span></td>
550
+ <td><code>{ type, ... }</code> — non-fatal issues (heartbeat, persistence, etc.)</td>
551
+ </tr>
552
+ </tbody>
553
+ </table>
554
+ </div>
555
+ </section>
556
+
557
+ <section id="exports" class="section">
558
+ <h2>Package exports</h2>
559
+ <div class="table-wrap">
560
+ <table>
561
+ <thead>
562
+ <tr>
563
+ <th>Import path</th>
564
+ <th>Exports</th>
565
+ </tr>
566
+ </thead>
567
+ <tbody>
568
+ <tr>
569
+ <td><code>dignity.js</code></td>
570
+ <td><code>DignityP2P</code>, <code>IndexedDBPersistence</code>, signaling providers, in-memory adapters, security utilities</td>
571
+ </tr>
572
+ <tr>
573
+ <td><code>dignity.js/react</code></td>
574
+ <td><code>useDignity</code>, <code>useCollection</code>, <code>usePeers</code></td>
575
+ </tr>
576
+ </tbody>
577
+ </table>
578
+ </div>
579
+ </section>
580
+
581
+ <section id="examples" class="section">
582
+ <h2>Examples</h2>
583
+ <div class="table-wrap">
584
+ <table>
585
+ <thead>
586
+ <tr>
587
+ <th>Script</th>
588
+ <th>Description</th>
589
+ <th>Run</th>
590
+ </tr>
591
+ </thead>
592
+ <tbody>
593
+ <tr>
594
+ <td><code>examples/decentralized-tictactoe.js</code></td>
595
+ <td>Replicated board state and owner authorization</td>
596
+ <td><code>npm run example:tictactoe</code></td>
597
+ </tr>
598
+ <tr>
599
+ <td><code>examples/decentralized-chess-lite.js</code></td>
600
+ <td>Replicated move history with compact board model</td>
601
+ <td><code>npm run example:chess</code></td>
602
+ </tr>
603
+ </tbody>
604
+ </table>
605
+ </div>
606
+ </section>
607
+
608
+ <section id="development" class="section">
609
+ <h2>Development</h2>
610
+ <div class="code-block">
611
+ <pre><code class="language-bash"># Run tests (177+ passing, ~99.5% line coverage)
612
+ npm test
613
+
614
+ # Build browser + Node bundles
615
+ npm run build
616
+
617
+ # Serve docs locally
618
+ npm run docs:serve
619
+
620
+ # Run examples
621
+ npm run example:tictactoe
622
+ npm run example:chess</code></pre>
623
+ </div>
624
+ </section>
625
+
626
+ <footer class="site-footer">
627
+ <p>
628
+ dignity.js v0.5.1 ·
629
+ <a href="https://github.com/jose-compu/dignity.js/blob/main/LICENSE">Apache 2.0</a> ·
630
+ <a href="https://github.com/jose-compu/dignity.js">GitHub</a> ·
631
+ <a href="https://www.npmjs.com/package/dignity.js">npm</a>
632
+ </p>
633
+ </footer>
634
+ </div>
635
+ </main>
636
+ </div>
637
+
638
+ <script src="./assets/highlight/highlight.min.js"></script>
639
+ <script src="./assets/docs.js"></script>
116
640
  </body>
117
641
  </html>