@cero-base/cero 1.2.0 → 1.4.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 +2 -2
- package/src/bluetooth.js +36 -13
- package/src/index.js +11 -3
- package/types/bluetooth.d.ts +4 -3
- package/types/index.d.ts +6 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cero-base/cero",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "The ideal p2p API — everything is a handle, handles contain refs, refs contain rows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"test:bare": "npx bare test/bare-smoke.js"
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@cero-base/core": "^1.
|
|
89
|
+
"@cero-base/core": "^1.4.0",
|
|
90
90
|
"b4a": "^1.8.1",
|
|
91
91
|
"bare-abort-controller": "^1.1.2",
|
|
92
92
|
"bare-crypto": "^1.15.3",
|
package/src/bluetooth.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ReadyResource from 'ready-resource'
|
|
2
2
|
import safetyCatch from 'safety-catch'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { BLETransport } from '@cero-base/core/network/transports/ble'
|
|
5
5
|
import { Pairing } from '@cero-base/core/pairing'
|
|
6
6
|
import { Invite } from '@cero-base/core/invite'
|
|
7
7
|
|
|
@@ -48,6 +48,7 @@ export class Bluetooth extends ReadyResource {
|
|
|
48
48
|
this._backend = backend || null
|
|
49
49
|
this._autoStart = autoStart === true
|
|
50
50
|
this._transport = null
|
|
51
|
+
this._name = null
|
|
51
52
|
this._announces = new Set()
|
|
52
53
|
/** @type {'unsupported'|'unauthorized'|'off'|'waiting'|'starting'|'on'} */
|
|
53
54
|
this.state = 'off'
|
|
@@ -70,7 +71,7 @@ export class Bluetooth extends ReadyResource {
|
|
|
70
71
|
const topic = Pairing.inviteTopic(invite)
|
|
71
72
|
if (!topic) return () => {}
|
|
72
73
|
|
|
73
|
-
const transport = new
|
|
74
|
+
const transport = new BLETransport({
|
|
74
75
|
backend: this._backend,
|
|
75
76
|
network: this._handle.network,
|
|
76
77
|
uuid: topic,
|
|
@@ -114,12 +115,21 @@ export class Bluetooth extends ReadyResource {
|
|
|
114
115
|
*
|
|
115
116
|
* @returns {Promise<void>}
|
|
116
117
|
*/
|
|
117
|
-
async start() {
|
|
118
|
+
async start({ name } = {}) {
|
|
119
|
+
if (name !== undefined) this._name = name
|
|
118
120
|
if (this.state === 'unsupported') return
|
|
119
|
-
if (this._transport)
|
|
121
|
+
if (this._transport) {
|
|
122
|
+
// reuse one transport across toggles — recreating leaks iOS CoreBluetooth
|
|
123
|
+
// managers (can't destroy()) and their stale GATT service
|
|
124
|
+
this._transport.name = this._name || ''
|
|
125
|
+
this._transport.resume()
|
|
126
|
+
this.state = this._transport.state
|
|
127
|
+
this.emit('update')
|
|
128
|
+
return
|
|
129
|
+
}
|
|
120
130
|
const handle = this._handle
|
|
121
131
|
|
|
122
|
-
this._transport = new
|
|
132
|
+
this._transport = new BLETransport({
|
|
123
133
|
backend: this._backend,
|
|
124
134
|
network: handle.network,
|
|
125
135
|
// channel isolation for free: same channel → same UUID, like the swarm.
|
|
@@ -127,7 +137,13 @@ export class Bluetooth extends ReadyResource {
|
|
|
127
137
|
uuid: handle.network.channel
|
|
128
138
|
? Buffer.from(handle.network.channel)
|
|
129
139
|
: handle.identity.publicKey,
|
|
130
|
-
nodeId: handle.identity.publicKey
|
|
140
|
+
nodeId: handle.identity.publicKey,
|
|
141
|
+
name: this._name || '',
|
|
142
|
+
// Android scans in a battery-saver mode by default — too slow for a mesh
|
|
143
|
+
scanOptions:
|
|
144
|
+
typeof Bare !== 'undefined' && Bare.platform === 'android'
|
|
145
|
+
? { scanMode: this._backend.Central.SCAN_MODE_LOW_LATENCY }
|
|
146
|
+
: undefined
|
|
131
147
|
})
|
|
132
148
|
this._transport.on('update', () => {
|
|
133
149
|
this.state = this._transport.state
|
|
@@ -156,17 +172,24 @@ export class Bluetooth extends ReadyResource {
|
|
|
156
172
|
await t.close().catch(safetyCatch)
|
|
157
173
|
}
|
|
158
174
|
if (!this._transport) return
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
this._transport = null
|
|
175
|
+
// suspend, don't close: keep the transport (and its GATT service) so a later
|
|
176
|
+
// start() resumes the same instance instead of leaking a new one. suspend()
|
|
177
|
+
// is async (it says goodbye + drains before hanging up); await it.
|
|
178
|
+
await this._transport.suspend()
|
|
165
179
|
this.state = 'off'
|
|
166
180
|
this.emit('update')
|
|
167
181
|
}
|
|
168
182
|
|
|
169
183
|
async _close() {
|
|
170
|
-
|
|
184
|
+
for (const t of [...this._announces]) {
|
|
185
|
+
this._announces.delete(t)
|
|
186
|
+
await t.close().catch(safetyCatch)
|
|
187
|
+
}
|
|
188
|
+
if (this._transport) {
|
|
189
|
+
await this._transport.close().catch(safetyCatch)
|
|
190
|
+
this._transport = null
|
|
191
|
+
}
|
|
192
|
+
this.state = 'off'
|
|
193
|
+
this.emit('update')
|
|
171
194
|
}
|
|
172
195
|
}
|
package/src/index.js
CHANGED
|
@@ -69,7 +69,7 @@ export { t, schema } from './lib/spec.js'
|
|
|
69
69
|
* @property {number} [recoveryTimeout] Max wait for peer data + writer capability during recovery.
|
|
70
70
|
* @property {Uint8Array} [storageKey] 32-byte key encrypting local key material (master seed, device keypairs) at rest. Source it from the OS keychain — cero never stores it.
|
|
71
71
|
* @property {boolean} [extensions] `false` disables the bundled extensions (profileSync, handleSync) for this instance. Build with `{ extensions: false }` too so the spec matches.
|
|
72
|
-
* @property {boolean | any} [bluetooth]
|
|
72
|
+
* @property {boolean | { autoStart?: boolean, backend?: any }} [bluetooth] `true` enables nearby (Bluetooth) sync via `me.bluetooth` (auto-started). `{ autoStart: false }` creates the facade without starting the radio — the app calls `me.bluetooth.start()`/`stop()` (user toggle). `backend` injects a bare-bluetooth-shaped backend (tests); absent backend on an unsupported host → `me.bluetooth.state === 'unsupported'`.
|
|
73
73
|
*/
|
|
74
74
|
|
|
75
75
|
/**
|
|
@@ -177,9 +177,17 @@ export async function cero(dir, spec, opts = {}) {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
if (opts.bluetooth) {
|
|
180
|
+
// `true` → defaults; `{ autoStart, backend }` → options. A bare backend
|
|
181
|
+
// object (pre-1.3 shape, has Central/Server) is still accepted.
|
|
182
|
+
const bt =
|
|
183
|
+
opts.bluetooth === true
|
|
184
|
+
? {}
|
|
185
|
+
: opts.bluetooth.Central
|
|
186
|
+
? { backend: opts.bluetooth }
|
|
187
|
+
: opts.bluetooth
|
|
180
188
|
me.bluetooth = new Bluetooth(me, {
|
|
181
|
-
backend:
|
|
182
|
-
autoStart:
|
|
189
|
+
backend: bt.backend || null,
|
|
190
|
+
autoStart: bt.autoStart !== false
|
|
183
191
|
})
|
|
184
192
|
me.once('close', () => me.bluetooth.close().catch(safetyCatch))
|
|
185
193
|
await me.bluetooth.ready()
|
package/types/bluetooth.d.ts
CHANGED
|
@@ -27,7 +27,8 @@ export class Bluetooth extends ReadyResource {
|
|
|
27
27
|
_handle: any;
|
|
28
28
|
_backend: any;
|
|
29
29
|
_autoStart: boolean;
|
|
30
|
-
_transport:
|
|
30
|
+
_transport: BLETransport;
|
|
31
|
+
_name: any;
|
|
31
32
|
_announces: Set<any>;
|
|
32
33
|
/** @type {'unsupported'|'unauthorized'|'off'|'waiting'|'starting'|'on'} */
|
|
33
34
|
state: "unsupported" | "unauthorized" | "off" | "waiting" | "starting" | "on";
|
|
@@ -52,7 +53,7 @@ export class Bluetooth extends ReadyResource {
|
|
|
52
53
|
*
|
|
53
54
|
* @returns {Promise<void>}
|
|
54
55
|
*/
|
|
55
|
-
start(): Promise<void>;
|
|
56
|
+
start({ name }?: {}): Promise<void>;
|
|
56
57
|
/**
|
|
57
58
|
* Stop advertising/scanning and drop links. Idempotent. Sync stops; local
|
|
58
59
|
* data and the rest of the network (DHT) are untouched.
|
|
@@ -62,4 +63,4 @@ export class Bluetooth extends ReadyResource {
|
|
|
62
63
|
stop(): Promise<void>;
|
|
63
64
|
}
|
|
64
65
|
import ReadyResource from 'ready-resource';
|
|
65
|
-
import {
|
|
66
|
+
import { BLETransport } from '@cero-base/core/network/transports/ble';
|
package/types/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* @property {number} [recoveryTimeout] Max wait for peer data + writer capability during recovery.
|
|
20
20
|
* @property {Uint8Array} [storageKey] 32-byte key encrypting local key material (master seed, device keypairs) at rest. Source it from the OS keychain — cero never stores it.
|
|
21
21
|
* @property {boolean} [extensions] `false` disables the bundled extensions (profileSync, handleSync) for this instance. Build with `{ extensions: false }` too so the spec matches.
|
|
22
|
-
* @property {boolean | any} [bluetooth]
|
|
22
|
+
* @property {boolean | { autoStart?: boolean, backend?: any }} [bluetooth] `true` enables nearby (Bluetooth) sync via `me.bluetooth` (auto-started). `{ autoStart: false }` creates the facade without starting the radio — the app calls `me.bluetooth.start()`/`stop()` (user toggle). `backend` injects a bare-bluetooth-shaped backend (tests); absent backend on an unsupported host → `me.bluetooth.state === 'unsupported'`.
|
|
23
23
|
*/
|
|
24
24
|
/**
|
|
25
25
|
* Open (or create) a cero handle at `dir`. Sets up storage, network and
|
|
@@ -133,9 +133,12 @@ export type CeroOpts = {
|
|
|
133
133
|
*/
|
|
134
134
|
extensions?: boolean;
|
|
135
135
|
/**
|
|
136
|
-
* `true` enables nearby (Bluetooth) sync via `me.bluetooth
|
|
136
|
+
* `true` enables nearby (Bluetooth) sync via `me.bluetooth` (auto-started). `{ autoStart: false }` creates the facade without starting the radio — the app calls `me.bluetooth.start()`/`stop()` (user toggle). `backend` injects a bare-bluetooth-shaped backend (tests); absent backend on an unsupported host → `me.bluetooth.state === 'unsupported'`.
|
|
137
137
|
*/
|
|
138
|
-
bluetooth?: boolean |
|
|
138
|
+
bluetooth?: boolean | {
|
|
139
|
+
autoStart?: boolean;
|
|
140
|
+
backend?: any;
|
|
141
|
+
};
|
|
139
142
|
};
|
|
140
143
|
import { t } from './lib/spec.js';
|
|
141
144
|
import { put } from './lib/operators.js';
|