@cero-base/core 1.7.0 → 1.8.0
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/package.json +8 -8
- package/src/pairing/index.js +19 -8
- package/types/pairing/index.d.ts +10 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cero-base/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "cero p2p primitives — identity, storage, network, database, blobs, rpc, pairing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"build:types": "rm -rf types && tsc -p .",
|
|
138
138
|
"pretest": "npm run build:test",
|
|
139
139
|
"prepublishOnly": "npm run build:types",
|
|
140
|
-
"test": "npm run test:
|
|
140
|
+
"test": "npm run test:bare",
|
|
141
141
|
"test:bare": "brittle-bare test/bare.js test/*.test.js",
|
|
142
142
|
"pretest:bare": "npm run build:test",
|
|
143
143
|
"test:node": "brittle-node test/*.test.js"
|
|
@@ -152,20 +152,20 @@
|
|
|
152
152
|
"bare-path": "^3.1.1",
|
|
153
153
|
"bip39-mnemonic": "^2.5.0",
|
|
154
154
|
"blind-pairing": "^2.3.1",
|
|
155
|
-
"blind-peering": "^2.5.
|
|
155
|
+
"blind-peering": "^2.5.3",
|
|
156
156
|
"compact-encoding": "^3.3.0",
|
|
157
|
-
"corestore": "^7.
|
|
157
|
+
"corestore": "^7.12.0",
|
|
158
158
|
"framed-stream": "^1.0.1",
|
|
159
159
|
"hrpc": "^4.3.0",
|
|
160
160
|
"hyperblobs": "^2.12.1",
|
|
161
|
-
"hypercore": "^11.
|
|
161
|
+
"hypercore": "^11.35.1",
|
|
162
162
|
"hypercore-blob-server": "^1.15.0",
|
|
163
163
|
"hypercore-crypto": "^3.7.0",
|
|
164
164
|
"hypercore-id-encoding": "^1.3.0",
|
|
165
165
|
"hypercore-storage": "^3.2.0",
|
|
166
|
-
"hyperdb": "^6.
|
|
166
|
+
"hyperdb": "^6.8.0",
|
|
167
167
|
"hyperdispatch": "^1.6.0",
|
|
168
|
-
"hyperschema": "^1.
|
|
168
|
+
"hyperschema": "^1.22.0",
|
|
169
169
|
"hyperswarm": "^4.17.0",
|
|
170
170
|
"keet-identity-key": "^3.2.0",
|
|
171
171
|
"protomux-wakeup": "^2.9.0",
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
"bare-fetch": "^3.2.0",
|
|
183
183
|
"bare-process": "^4.5.1",
|
|
184
184
|
"bare-url": "^2.4.6",
|
|
185
|
-
"blind-peer": "^3.12.
|
|
185
|
+
"blind-peer": "^3.12.5",
|
|
186
186
|
"brittle": "^4.1.0",
|
|
187
187
|
"typescript": "^5.9.3",
|
|
188
188
|
"which-runtime": "^1.4.0"
|
package/src/pairing/index.js
CHANGED
|
@@ -23,6 +23,7 @@ const Response = getEncoding('@cero/confirm')
|
|
|
23
23
|
* @property {import('../network/index.js').Network} network Network to host the BlindPairing member.
|
|
24
24
|
* @property {import('../identity/index.js').Identity} identity Identity used to sign invites and derive the topic.
|
|
25
25
|
* @property {Uint8Array} [topic] Optional override topic; defaults to `identity.publicKey`.
|
|
26
|
+
* @property {boolean} [host] Register the member listener that serves invites (default `true`). Join-only pairings pass `false` — a listener is one-per-topic, so a joiner registering one collides with any concurrent join.
|
|
26
27
|
* @property {any} [inviteEncoding] compact-encoding type for the invite payload `data`.
|
|
27
28
|
* @property {any} [joinerEncoding] compact-encoding type for the joiner-supplied `userData`.
|
|
28
29
|
* @property {(err: Error) => void} [onerror] Called when a background candidate fails to process.
|
|
@@ -31,7 +32,7 @@ const Response = getEncoding('@cero/confirm')
|
|
|
31
32
|
* @property {string} [role] Role tag bound into the invite.
|
|
32
33
|
* @property {number} [expiresIn] TTL in ms; `0`/omitted = no expiry.
|
|
33
34
|
* @property {any} [data] Arbitrary payload (encoded via `inviteEncoding` when set).
|
|
34
|
-
* @property {boolean} [
|
|
35
|
+
* @property {boolean} [reuse] Reusable until expiry/revoke; default `false` (consumed on first settle).
|
|
35
36
|
*
|
|
36
37
|
* @typedef {object} JoinOpts
|
|
37
38
|
* @property {any} [userData] Payload sent with the candidate request.
|
|
@@ -65,6 +66,7 @@ export class Pairing extends ReadyResource {
|
|
|
65
66
|
network,
|
|
66
67
|
identity,
|
|
67
68
|
topic,
|
|
69
|
+
host = true,
|
|
68
70
|
inviteEncoding = null,
|
|
69
71
|
joinerEncoding = null,
|
|
70
72
|
onerror = safetyCatch
|
|
@@ -76,6 +78,7 @@ export class Pairing extends ReadyResource {
|
|
|
76
78
|
this.network = network
|
|
77
79
|
this.identity = identity
|
|
78
80
|
this.topic = topic || identity.publicKey
|
|
81
|
+
this.host = host
|
|
79
82
|
this.inviteEncoding = inviteEncoding
|
|
80
83
|
this.joinerEncoding = joinerEncoding
|
|
81
84
|
this._onerror = onerror
|
|
@@ -91,10 +94,15 @@ export class Pairing extends ReadyResource {
|
|
|
91
94
|
// shared instance — one set of swarm/DHT listeners for every handle
|
|
92
95
|
this._blind = await this.network.blind()
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
// blind-pairing allows ONE member listener per discovery key — a join-only
|
|
98
|
+
// pairing must not register one, or concurrent joins under the same
|
|
99
|
+
// identity throw 'Active member already exist'
|
|
100
|
+
if (this.host) {
|
|
101
|
+
this._member = this._blind.addMember({
|
|
102
|
+
discoveryKey: discoveryKey(this.topic),
|
|
103
|
+
onadd: (req) => this._onCandidate(req).catch(this._onerror)
|
|
104
|
+
})
|
|
105
|
+
}
|
|
98
106
|
await this.network.refreshInjected()
|
|
99
107
|
}
|
|
100
108
|
|
|
@@ -133,8 +141,11 @@ export class Pairing extends ReadyResource {
|
|
|
133
141
|
* @param {CreateInviteOpts} [opts]
|
|
134
142
|
* @returns {Promise<string>}
|
|
135
143
|
*/
|
|
136
|
-
async createInvite({ role = '', expiresIn = 0, data = null,
|
|
144
|
+
async createInvite({ role = '', expiresIn = 0, data = null, reuse = false } = {}) {
|
|
137
145
|
if (this.closing || this.closed) throw CeroError.CLOSED('Pairing')
|
|
146
|
+
// a join-only pairing has no member listener — an invite it mints would
|
|
147
|
+
// never be served, so fail loudly instead of handing out a dead invite
|
|
148
|
+
if (!this.host) throw CeroError.INVALID('cannot create invites on a join-only Pairing')
|
|
138
149
|
if (!this.opened) await this.ready()
|
|
139
150
|
|
|
140
151
|
// Rendezvous key matches the Member topic so candidates land on the right
|
|
@@ -157,7 +168,7 @@ export class Pairing extends ReadyResource {
|
|
|
157
168
|
seed: blind.seed,
|
|
158
169
|
publicKey: blind.publicKey,
|
|
159
170
|
invite,
|
|
160
|
-
|
|
171
|
+
reuse
|
|
161
172
|
})
|
|
162
173
|
|
|
163
174
|
return invite.toString()
|
|
@@ -281,7 +292,7 @@ export class Pairing extends ReadyResource {
|
|
|
281
292
|
seed: record.seed,
|
|
282
293
|
userData,
|
|
283
294
|
onsettle: () => {
|
|
284
|
-
if (!record.
|
|
295
|
+
if (!record.reuse) this._invites.delete(id)
|
|
285
296
|
}
|
|
286
297
|
})
|
|
287
298
|
|
package/types/pairing/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @property {import('../network/index.js').Network} network Network to host the BlindPairing member.
|
|
4
4
|
* @property {import('../identity/index.js').Identity} identity Identity used to sign invites and derive the topic.
|
|
5
5
|
* @property {Uint8Array} [topic] Optional override topic; defaults to `identity.publicKey`.
|
|
6
|
+
* @property {boolean} [host] Register the member listener that serves invites (default `true`). Join-only pairings pass `false` — a listener is one-per-topic, so a joiner registering one collides with any concurrent join.
|
|
6
7
|
* @property {any} [inviteEncoding] compact-encoding type for the invite payload `data`.
|
|
7
8
|
* @property {any} [joinerEncoding] compact-encoding type for the joiner-supplied `userData`.
|
|
8
9
|
* @property {(err: Error) => void} [onerror] Called when a background candidate fails to process.
|
|
@@ -11,7 +12,7 @@
|
|
|
11
12
|
* @property {string} [role] Role tag bound into the invite.
|
|
12
13
|
* @property {number} [expiresIn] TTL in ms; `0`/omitted = no expiry.
|
|
13
14
|
* @property {any} [data] Arbitrary payload (encoded via `inviteEncoding` when set).
|
|
14
|
-
* @property {boolean} [
|
|
15
|
+
* @property {boolean} [reuse] Reusable until expiry/revoke; default `false` (consumed on first settle).
|
|
15
16
|
*
|
|
16
17
|
* @typedef {object} JoinOpts
|
|
17
18
|
* @property {any} [userData] Payload sent with the candidate request.
|
|
@@ -56,10 +57,11 @@ export class Pairing extends ReadyResource {
|
|
|
56
57
|
*/
|
|
57
58
|
static isInvite(str: unknown): boolean;
|
|
58
59
|
/** @param {PairingOpts} [opts] */
|
|
59
|
-
constructor({ network, identity, topic, inviteEncoding, joinerEncoding, onerror }?: PairingOpts);
|
|
60
|
+
constructor({ network, identity, topic, host, inviteEncoding, joinerEncoding, onerror }?: PairingOpts);
|
|
60
61
|
network: import("../index.js").Network;
|
|
61
62
|
identity: import("../index.js").Identity;
|
|
62
63
|
topic: Uint8Array<ArrayBufferLike>;
|
|
64
|
+
host: boolean;
|
|
63
65
|
inviteEncoding: any;
|
|
64
66
|
joinerEncoding: any;
|
|
65
67
|
_onerror: (err: Error) => void;
|
|
@@ -73,7 +75,7 @@ export class Pairing extends ReadyResource {
|
|
|
73
75
|
* @param {CreateInviteOpts} [opts]
|
|
74
76
|
* @returns {Promise<string>}
|
|
75
77
|
*/
|
|
76
|
-
createInvite({ role, expiresIn, data,
|
|
78
|
+
createInvite({ role, expiresIn, data, reuse }?: CreateInviteOpts): Promise<string>;
|
|
77
79
|
/**
|
|
78
80
|
* Forget a previously-minted invite. New candidates carrying it will be
|
|
79
81
|
* dropped silently.
|
|
@@ -124,6 +126,10 @@ export type PairingOpts = {
|
|
|
124
126
|
* Optional override topic; defaults to `identity.publicKey`.
|
|
125
127
|
*/
|
|
126
128
|
topic?: Uint8Array;
|
|
129
|
+
/**
|
|
130
|
+
* Register the member listener that serves invites (default `true`). Join-only pairings pass `false` — a listener is one-per-topic, so a joiner registering one collides with any concurrent join.
|
|
131
|
+
*/
|
|
132
|
+
host?: boolean;
|
|
127
133
|
/**
|
|
128
134
|
* compact-encoding type for the invite payload `data`.
|
|
129
135
|
*/
|
|
@@ -153,7 +159,7 @@ export type CreateInviteOpts = {
|
|
|
153
159
|
/**
|
|
154
160
|
* Reusable until expiry/revoke; default `false` (consumed on first settle).
|
|
155
161
|
*/
|
|
156
|
-
|
|
162
|
+
reuse?: boolean;
|
|
157
163
|
};
|
|
158
164
|
export type JoinOpts = {
|
|
159
165
|
/**
|