@cero-base/cero 0.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.
@@ -0,0 +1,290 @@
1
+ import { RPCServer, bindCodec } from '@cero-base/core/rpc'
2
+ import { CeroError } from '@cero-base/core/errors'
3
+
4
+ import { cero, restore } from '../index.js'
5
+ import { put, set, get, del, count, watch, call } from '../lib/operators.js'
6
+
7
+ /**
8
+ * @typedef {import('@cero-base/core/rpc').RPCServer} BaseRPCServer
9
+ *
10
+ * @typedef {object} ServerOpts
11
+ * @property {string} storage Directory passed to `cero()` for the local store.
12
+ * @property {object} spec Compiled cero spec (schema + rpc + handles).
13
+ * @property {string} [name] Optional display name forwarded to `cero()`.
14
+ * @property {Array<{ host: string, port: number }>} [bootstrap] Custom DHT bootstrap.
15
+ * @property {boolean} [isMobile]
16
+ * @property {(err: Error) => void} [onerror]
17
+ *
18
+ * @typedef {object} Identity
19
+ * @property {string} id Long-lived cero identity id.
20
+ * @property {string} deviceId Per-device id (empty when no `local` spec).
21
+ * @property {string|null} phrase BIP39 recovery phrase for the identity.
22
+ *
23
+ * @typedef {{ ref: any, codec: any }} RefAndCodec
24
+ *
25
+ * @typedef {{ data: any, total?: number, size?: number }} GetResult Single-ref get omits `total`/`size`; list/handle refs include them.
26
+ */
27
+
28
+ /**
29
+ * IPC-side RPC server for cero. Bridges an `hrpc` channel to a live
30
+ * `Handle` tree: lazy-initializes the root via `cero()` on the first
31
+ * `init` call, then exposes data ops, pairing, and handle lifecycle
32
+ * over the wire using the spec-bound codec.
33
+ */
34
+ export class Server extends RPCServer {
35
+ /**
36
+ * @param {any} ipc Framed IPC stream (must be writable).
37
+ * @param {Partial<ServerOpts>} [opts]
38
+ */
39
+ constructor(ipc, { storage, spec, ...opts } = {}) {
40
+ if (!storage) throw CeroError.REQUIRED('storage')
41
+ if (!spec) throw CeroError.REQUIRED('spec')
42
+ super(ipc, spec)
43
+ this.storage = storage
44
+ this.opts = opts
45
+ this.me = null
46
+ this.handles = new Map()
47
+ this._wireInit()
48
+ }
49
+
50
+ /**
51
+ * Root cero id (null until `init` has run).
52
+ *
53
+ * @returns {string|undefined}
54
+ */
55
+ get id() {
56
+ return this.me?.id
57
+ }
58
+
59
+ /**
60
+ * Root identity object (null until `init` has run).
61
+ *
62
+ * @returns {any}
63
+ */
64
+ get identity() {
65
+ return this.me?.identity
66
+ }
67
+
68
+ async _close() {
69
+ if (this.me) {
70
+ try {
71
+ await this.me.close()
72
+ } catch {}
73
+ }
74
+ await super._close()
75
+ }
76
+
77
+ /** Wire the `init` handler that lazily constructs the root cero handle. */
78
+ _wireInit() {
79
+ this.rpc.onInit(async () => {
80
+ if (this.me) throw new CeroError('CONFLICT', 'already initialized')
81
+ this.me = await cero(this.storage, this.spec, this.opts)
82
+ this.handles.set(this.me.id, this.me)
83
+ this._wireData()
84
+ this._wirePairing()
85
+ this._wireHandles()
86
+ this._wireRestore()
87
+ return this._identity()
88
+ })
89
+ }
90
+
91
+ /** Wire the `restore` handler that rebuilds the local store from a phrase. */
92
+ _wireRestore() {
93
+ this.rpc.onRestore(async ({ phrase }) => {
94
+ if (!this.me) throw new CeroError('NOT_READY', 'init')
95
+ this.me = await restore(this.me, phrase)
96
+ this.handles = new Map([[this.me.id, this.me]])
97
+ return this._identity()
98
+ })
99
+ }
100
+
101
+ /** Register the row-level RPC handlers (put/set/get/del/count/watch/call). */
102
+ _wireData() {
103
+ this.rpc.onAddRow(async ({ handle, ref, data }) => {
104
+ const { ref: r, codec } = this._refOf(handle, ref)
105
+ const { data: row } = await put(r, codec.decodeRow(r.schema, data))
106
+ return { data: codec.encodeRow(r.schema, row) }
107
+ })
108
+
109
+ this.rpc.onSet(async ({ handle, ref, data }) => {
110
+ const { ref: r, codec } = this._refOf(handle, ref)
111
+ const { data: row } = await set(r, codec.decodeRow(r.schema, data))
112
+ return { data: codec.encodeRow(r.schema, row) }
113
+ })
114
+
115
+ this.rpc.onGet(async ({ handle, ref, query }) => {
116
+ const { ref: r, codec } = this._refOf(handle, ref)
117
+ const result = /** @type {GetResult} */ (await get(r, codec.decodeQuery(query)))
118
+ const data =
119
+ r.kind === 'single'
120
+ ? codec.encodeRow(r.schema, result.data)
121
+ : codec.encodeRows(r.schema, result.data)
122
+ return { data, total: result.total ?? 0, size: result.size ?? 0 }
123
+ })
124
+
125
+ this.rpc.onGetOne(async ({ handle, ref, id }) => {
126
+ const { ref: r, codec } = this._refOf(handle, ref)
127
+ const { data } = await get(r, id)
128
+ return { data: data ? codec.encodeRow(r.schema, data) : null }
129
+ })
130
+
131
+ this.rpc.onDel(async ({ handle, ref, id }) => {
132
+ await del(this._refOf(handle, ref).ref, id)
133
+ return {}
134
+ })
135
+
136
+ this.rpc.onCount(async ({ handle, ref, query }) => {
137
+ const { ref: r, codec } = this._refOf(handle, ref)
138
+ const { data } = await count(r, codec.decodeQuery(query))
139
+ return { count: data }
140
+ })
141
+
142
+ this.rpc.onWatch((stream) => {
143
+ const { handle, ref, query } = stream.data
144
+ let r, codec, live
145
+ try {
146
+ ;({ ref: r, codec } = this._refOf(handle, ref))
147
+ live = watch(r, codec.decodeQuery(query))
148
+ } catch (err) {
149
+ stream.destroy(err)
150
+ return
151
+ }
152
+ const onData = (snap) => {
153
+ const data =
154
+ r.kind === 'single'
155
+ ? codec.encodeRow(r.schema, snap.data)
156
+ : codec.encodeRows(r.schema, snap.data)
157
+ stream.write({ data, total: snap.total ?? 0, size: snap.size ?? 0 })
158
+ }
159
+ live.on('data', onData)
160
+ stream.on('close', () => {
161
+ live.off('data', onData)
162
+ live.destroy()
163
+ })
164
+ })
165
+
166
+ this.rpc.onCall(async ({ handle, op, data }) => {
167
+ const h = this._resolve(handle)
168
+ const r = h[op]
169
+ if (!r) throw CeroError.UNKNOWN('ref', op)
170
+ await call(r, h.spec.codec.decodeAction(h, op, data))
171
+ return { data: null }
172
+ })
173
+ }
174
+
175
+ /** Register invite/revoke/join RPC handlers. */
176
+ _wirePairing() {
177
+ this.rpc.onInvite(async ({ handle, role }) => {
178
+ const h = this._resolve(handle)
179
+ const invite = await h.invite({ role: role || undefined })
180
+ return { invite }
181
+ })
182
+
183
+ this.rpc.onRevoke(async ({ handle, invite }) => {
184
+ const ok = this._resolve(handle).revoke(invite)
185
+ return { ok }
186
+ })
187
+
188
+ this.rpc.onJoin(async ({ parent, ref, invite }) => {
189
+ if (this._resolve(parent) !== this.me) throw CeroError.UNSUPPORTED('nested handles')
190
+ const child = await this.me._join(invite, ref)
191
+ const id = child.id
192
+ this.handles.set(id, child)
193
+ return { id, type: ref, name: '' }
194
+ })
195
+ }
196
+
197
+ /** Register add/open/close/leave RPC handlers for child handles. */
198
+ _wireHandles() {
199
+ this.rpc.onAddHandle(async ({ handle, ref, data }) => {
200
+ const parent = this._resolve(handle)
201
+ const info = parent.spec.meta.refs?.[ref] || parent.spec.handles?.[ref]
202
+ if (!info) throw CeroError.UNKNOWN('handle type', ref)
203
+ const opts = parent.spec.codec.decodeCreate(data) || {}
204
+ const child = await this.me._create(ref, opts)
205
+ const id = child.id
206
+ this.handles.set(id, child)
207
+ return { id, type: ref, name: opts.name || '' }
208
+ })
209
+
210
+ this.rpc.onOpenHandle(async ({ parent, row }) => {
211
+ if (this._resolve(parent) !== this.me) throw CeroError.UNSUPPORTED('nested handles')
212
+ const { data } = await this.me.store.get('handles', row)
213
+ if (!data) throw CeroError.UNKNOWN('handle', row)
214
+ const child = await this.me._load(data.type, row)
215
+ this.handles.set(row, child)
216
+ return { id: row, type: data.type, name: data.name || '' }
217
+ })
218
+
219
+ this.rpc.onCloseHandle(async ({ handle }) => {
220
+ const h = this.handles.get(handle)
221
+ if (!h || h === this.me) return {}
222
+ this.handles.delete(handle)
223
+ await h.close()
224
+ return {}
225
+ })
226
+
227
+ this.rpc.onLeave(async ({ handle }) => {
228
+ const h = this.handles.get(handle)
229
+ if (!h || h === this.me) return {}
230
+ await this.me.store.call('del-handle', { id: handle })
231
+ this.handles.delete(handle)
232
+ await h.close()
233
+ return {}
234
+ })
235
+ }
236
+
237
+ /**
238
+ * Look up a live handle by id, throwing if unknown. Binds the handle's
239
+ * codec on first use.
240
+ *
241
+ * @param {string} id
242
+ * @returns {any}
243
+ */
244
+ _resolve(id) {
245
+ const h = this.handles.get(id)
246
+ if (!h) throw CeroError.UNKNOWN('handle', id)
247
+ if (!h.spec.codec) bindCodec(h.spec)
248
+ return h
249
+ }
250
+
251
+ /**
252
+ * Resolve a `{ handle, ref }` pair to its `Ref` and the handle's codec.
253
+ *
254
+ * @param {string} id
255
+ * @param {string} name
256
+ * @returns {RefAndCodec}
257
+ */
258
+ _refOf(id, name) {
259
+ const h = this._resolve(id)
260
+ const r = h[name]
261
+ if (!r) throw CeroError.UNKNOWN('ref', name)
262
+ return { ref: r, codec: h.spec.codec }
263
+ }
264
+
265
+ /**
266
+ * Snapshot the current identity for return to the client.
267
+ *
268
+ * @returns {Identity}
269
+ */
270
+ _identity() {
271
+ return {
272
+ id: this.me.id,
273
+ deviceId: this.me.device?.id || '',
274
+ phrase: this.me.identity.toPhrase()
275
+ }
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Construct a `Server`, wait for it to be ready, and return it.
281
+ *
282
+ * @param {any} ipc
283
+ * @param {ServerOpts} opts
284
+ * @returns {Promise<Server>}
285
+ */
286
+ export async function serve(ipc, opts) {
287
+ const server = new Server(ipc, opts)
288
+ await server.ready()
289
+ return server
290
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @typedef {import('@cero-base/core/schema').Schema} Schema
3
+ * @typedef {import('@cero-base/core/schema').SchemaDefs} SchemaDefs
4
+ * @typedef {Schema | (SchemaDefs & { local?: SchemaDefs })} SchemaInput
5
+ *
6
+ * @typedef {object} BuildOpts
7
+ * @property {string} [ns] Namespace prefix for emitted schema ids. Defaults to `'cero'`.
8
+ */
9
+ /**
10
+ * Compile a cero schema into wire-level artifacts and write them to disk.
11
+ *
12
+ * Emits a `main/` tree (schema + hyperdb + dispatch + rpc), a `local/` tree
13
+ * for per-device data, one `handles/<name>/` tree per child handle type, and
14
+ * an `index.js` that re-exports a ready-to-use `spec` object.
15
+ *
16
+ * @param {string} specDir Output directory.
17
+ * @param {SchemaInput} schema Either a `schema(...)` wrapper or its raw defs object.
18
+ * @param {BuildOpts} [opts]
19
+ * @returns {Promise<void>}
20
+ */
21
+ export function build(specDir: string, schema: SchemaInput, { ns }?: BuildOpts): Promise<void>;
22
+ export type Schema = import("@cero-base/core/schema").Schema;
23
+ export type SchemaDefs = import("@cero-base/core/schema").SchemaDefs;
24
+ export type SchemaInput = Schema | (SchemaDefs & {
25
+ local?: SchemaDefs;
26
+ });
27
+ export type BuildOpts = {
28
+ /**
29
+ * Namespace prefix for emitted schema ids. Defaults to `'cero'`.
30
+ */
31
+ ns?: string;
32
+ };
@@ -0,0 +1,353 @@
1
+ export { Ref } from "../lib/utils.js";
2
+ /**
3
+ * @typedef {import('@cero-base/core/network').Network} Network
4
+ * @typedef {import('../local/index.js').Local} Local
5
+ * @typedef {import('@cero-base/core/identity').KeyPair} KeyPair
6
+ *
7
+ * @typedef {object} HandleOpts
8
+ * @property {Handle} [parent] Parent handle when this is a child slot.
9
+ * @property {Identity} [identity] Long-lived user identity. Inherited from `parent` if omitted.
10
+ * @property {Network} [network] Shared swarm. Inherited from `parent` if omitted.
11
+ * @property {any} [store] Pre-existing Corestore. Falls back to `parent.store.store`.
12
+ * @property {any} [spec] Built cero spec.
13
+ * @property {Local} [local] Local store for per-handle keypairs.
14
+ * @property {any} [storage] Owned HypercoreStorage to close on shutdown.
15
+ * @property {any} [discovery] Owned identity Discovery to destroy on shutdown.
16
+ * @property {string} [dir] Data directory (root handles only).
17
+ * @property {any} [opts] Pass-through cero(...) options.
18
+ * @property {Record<string, Function>} [routes]
19
+ * @property {Uint8Array} [key] Existing database key.
20
+ * @property {Uint8Array} [encryptionKey] Existing encryption key.
21
+ * @property {string} [namespace] Corestore namespace.
22
+ * @property {KeyPair} [keyPair] Writer keypair.
23
+ * @property {boolean} [pair] When `false`, skips creating a `Pairing` session.
24
+ *
25
+ * @typedef {object} CreateChildOpts
26
+ * @property {string | null} [name]
27
+ * @property {Record<string, Function>} [routes]
28
+ * @property {string} [role]
29
+ * @property {boolean} [accept]
30
+ *
31
+ * @typedef {object} JoinChildOpts
32
+ * @property {Record<string, Function>} [routes]
33
+ * @property {number} [timeout]
34
+ *
35
+ * @typedef {object} StaticJoinOpts
36
+ * @property {Handle} [parent]
37
+ * @property {Network} [network]
38
+ * @property {Identity} [identity]
39
+ * @property {any} [store]
40
+ * @property {any} [spec]
41
+ * @property {string} [namespace]
42
+ * @property {Record<string, Function>} [routes]
43
+ * @property {number} [timeout]
44
+ *
45
+ * @typedef {object} AcceptOpts
46
+ * @property {string} [role] Role to grant the joining peer. Falls back to the invite's role, then `'write'`.
47
+ * @property {string | null} [name]
48
+ *
49
+ * @typedef {object} RecoverOpts
50
+ * @property {number} [timeout]
51
+ * @property {string | null} [name]
52
+ * @property {boolean} [isMobile]
53
+ *
54
+ * @typedef {object} HandleExtra
55
+ * @property {string | null} [name] Display name; set on child handles by the owner flow.
56
+ * @property {import('../lib/utils.js').Ref} [profile] `profile` ref, attached dynamically when the schema declares one.
57
+ * @property {import('../lib/utils.js').Ref} [members] `members` ref, attached dynamically when the schema declares one.
58
+ *
59
+ * @typedef {Handle & HandleExtra} Child A child handle plus its dynamically-attached refs.
60
+ */
61
+ /**
62
+ * A cero handle — a single writable database session attached to a swarm.
63
+ * The "root" handle is the user's facade; child handles (created via
64
+ * `_create`/`_join`/`_load`) live under it and share the same identity,
65
+ * network and corestore. Ref properties (`profile`, `members`, ...) are
66
+ * attached dynamically per the schema; child handles also carry a `name`.
67
+ */
68
+ export class Handle extends ReadyResource {
69
+ /**
70
+ * Pair into an existing handle via an invite, returning a brand-new
71
+ * `Handle` already configured with the resolved key + encryption key.
72
+ *
73
+ * @param {string} invite
74
+ * @param {StaticJoinOpts} [opts]
75
+ * @returns {Promise<Handle>}
76
+ */
77
+ static join(invite: string, { parent, network, identity, store, spec, namespace, routes, timeout }?: StaticJoinOpts): Promise<Handle>;
78
+ /** @param {HandleOpts} [opts] */
79
+ constructor(opts?: HandleOpts);
80
+ identity: any;
81
+ network: any;
82
+ spec: any;
83
+ parent: Handle;
84
+ local: import("../index.js").Local;
85
+ _storage: any;
86
+ _discovery: any;
87
+ _dir: string;
88
+ _opts: any;
89
+ _onerror: any;
90
+ children: Set<any>;
91
+ store: Database;
92
+ pair: Pairing;
93
+ _wantsPair: boolean;
94
+ _offUpdate: () => void;
95
+ /** Canonical id — identity id for the root handle, store key for children. */
96
+ get id(): any;
97
+ /** This device's id + name. `null` on child handles. */
98
+ get device(): {
99
+ id: string;
100
+ name: any;
101
+ };
102
+ get suspended(): boolean;
103
+ /**
104
+ * Initialise a fresh database: write the genesis claim, derive the writer.
105
+ * Forwards to `Database.bootstrap`.
106
+ *
107
+ * @param {any} [opts]
108
+ * @returns {Promise<any>}
109
+ */
110
+ bootstrap(opts?: any): Promise<any>;
111
+ /**
112
+ * Claim writer capability on an existing database (paired-device flow).
113
+ * Forwards to `Database.claim`.
114
+ *
115
+ * @param {{ name?: string | null, isMobile?: boolean }} [opts]
116
+ * @returns {Promise<void>}
117
+ */
118
+ claim(opts?: {
119
+ name?: string | null;
120
+ isMobile?: boolean;
121
+ }): Promise<void>;
122
+ /**
123
+ * Claim + wait until this peer becomes a writer + bring the bee up to date.
124
+ * Used by `restore()` after wiping local state.
125
+ *
126
+ * @param {RecoverOpts} [opts]
127
+ * @returns {Promise<void>}
128
+ */
129
+ recover({ timeout, name, isMobile }?: RecoverOpts): Promise<void>;
130
+ /**
131
+ * Mint a pairing invite for this handle.
132
+ *
133
+ * @param {{ role?: string, expiresIn?: number, data?: any }} [opts]
134
+ * @returns {Promise<string>} Z32-encoded invite string.
135
+ */
136
+ invite(opts?: {
137
+ role?: string;
138
+ expiresIn?: number;
139
+ data?: any;
140
+ }): Promise<string>;
141
+ /**
142
+ * Revoke a previously-minted invite by its string form.
143
+ *
144
+ * @param {string} invite
145
+ * @returns {boolean} `true` if the invite was found and removed.
146
+ */
147
+ revoke(invite: string): boolean;
148
+ /**
149
+ * Accept a paired candidate — adds them as a writer (or read-only member)
150
+ * and confirms the pairing so they receive this handle's keys.
151
+ *
152
+ * @param {any} candidate
153
+ * @param {AcceptOpts} [opts]
154
+ * @returns {Promise<void>}
155
+ */
156
+ accept(candidate: any, { role, name }?: AcceptOpts): Promise<void>;
157
+ /**
158
+ * Leave a child handle — removes it from the parent's `handles` collection
159
+ * and closes the session. No-op on root handles.
160
+ *
161
+ * @returns {Promise<void>}
162
+ */
163
+ leave(): Promise<void>;
164
+ /**
165
+ * Create a new child handle of `type`. Owner-flow — generates a fresh
166
+ * writer, adds it as a writer + member, and registers the child on the
167
+ * parent's `handles` collection.
168
+ *
169
+ * @param {string} type
170
+ * @param {CreateChildOpts} [opts]
171
+ * @returns {Promise<Handle>}
172
+ */
173
+ _create(type: string, { name, routes, role, accept }?: CreateChildOpts): Promise<Handle>;
174
+ /**
175
+ * Join a child handle by invite (joiner-flow). Waits for writer
176
+ * capability and registers the child on the parent's `handles`
177
+ * collection.
178
+ *
179
+ * @param {string} invite
180
+ * @param {string} type
181
+ * @param {JoinChildOpts} [opts]
182
+ * @returns {Promise<Handle>}
183
+ */
184
+ _join(invite: string, type: string, { routes, timeout }?: JoinChildOpts): Promise<Handle>;
185
+ /**
186
+ * Re-open an existing child handle by id. Reuses the stored writer
187
+ * keypair if available; otherwise generates a fresh one and claims
188
+ * writer capability.
189
+ *
190
+ * @param {string} type
191
+ * @param {string} id
192
+ * @returns {Promise<Handle>}
193
+ */
194
+ _load(type: string, id: string): Promise<Handle>;
195
+ /**
196
+ * Pause networking + storage. Idempotent; no-op on child handles.
197
+ *
198
+ * @returns {Promise<void>}
199
+ */
200
+ suspend(): Promise<void>;
201
+ _suspended: boolean;
202
+ /**
203
+ * Resume a suspended root handle. Idempotent; no-op on child handles.
204
+ *
205
+ * @returns {Promise<void>}
206
+ */
207
+ resume(): Promise<void>;
208
+ _syncMember(child: any): Promise<void>;
209
+ /**
210
+ * @param {Handle} child
211
+ * @param {{ role?: string }} [opts]
212
+ */
213
+ _wireAccept(child: Handle, { role }?: {
214
+ role?: string;
215
+ }): void;
216
+ /**
217
+ * @param {string} id
218
+ * @param {KeyPair | { publicKey: Uint8Array, secretKey: Uint8Array } | null} keyPair
219
+ * @returns {Promise<void>}
220
+ */
221
+ _saveKeyPair(id: string, keyPair: KeyPair | {
222
+ publicKey: Uint8Array;
223
+ secretKey: Uint8Array;
224
+ } | null): Promise<void>;
225
+ /**
226
+ * @param {string} id
227
+ * @returns {Promise<{ publicKey: Uint8Array, secretKey: Uint8Array } | null>}
228
+ */
229
+ _loadKeyPair(id: string): Promise<{
230
+ publicKey: Uint8Array;
231
+ secretKey: Uint8Array;
232
+ } | null>;
233
+ }
234
+ export type Network = import("@cero-base/core/network").Network;
235
+ export type Local = import("../local/index.js").Local;
236
+ export type KeyPair = import("@cero-base/core/identity").KeyPair;
237
+ export type HandleOpts = {
238
+ /**
239
+ * Parent handle when this is a child slot.
240
+ */
241
+ parent?: Handle;
242
+ /**
243
+ * Long-lived user identity. Inherited from `parent` if omitted.
244
+ */
245
+ identity?: Identity;
246
+ /**
247
+ * Shared swarm. Inherited from `parent` if omitted.
248
+ */
249
+ network?: Network;
250
+ /**
251
+ * Pre-existing Corestore. Falls back to `parent.store.store`.
252
+ */
253
+ store?: any;
254
+ /**
255
+ * Built cero spec.
256
+ */
257
+ spec?: any;
258
+ /**
259
+ * Local store for per-handle keypairs.
260
+ */
261
+ local?: Local;
262
+ /**
263
+ * Owned HypercoreStorage to close on shutdown.
264
+ */
265
+ storage?: any;
266
+ /**
267
+ * Owned identity Discovery to destroy on shutdown.
268
+ */
269
+ discovery?: any;
270
+ /**
271
+ * Data directory (root handles only).
272
+ */
273
+ dir?: string;
274
+ /**
275
+ * Pass-through cero(...) options.
276
+ */
277
+ opts?: any;
278
+ routes?: Record<string, Function>;
279
+ /**
280
+ * Existing database key.
281
+ */
282
+ key?: Uint8Array;
283
+ /**
284
+ * Existing encryption key.
285
+ */
286
+ encryptionKey?: Uint8Array;
287
+ /**
288
+ * Corestore namespace.
289
+ */
290
+ namespace?: string;
291
+ /**
292
+ * Writer keypair.
293
+ */
294
+ keyPair?: KeyPair;
295
+ /**
296
+ * When `false`, skips creating a `Pairing` session.
297
+ */
298
+ pair?: boolean;
299
+ };
300
+ export type CreateChildOpts = {
301
+ name?: string | null;
302
+ routes?: Record<string, Function>;
303
+ role?: string;
304
+ accept?: boolean;
305
+ };
306
+ export type JoinChildOpts = {
307
+ routes?: Record<string, Function>;
308
+ timeout?: number;
309
+ };
310
+ export type StaticJoinOpts = {
311
+ parent?: Handle;
312
+ network?: Network;
313
+ identity?: Identity;
314
+ store?: any;
315
+ spec?: any;
316
+ namespace?: string;
317
+ routes?: Record<string, Function>;
318
+ timeout?: number;
319
+ };
320
+ export type AcceptOpts = {
321
+ /**
322
+ * Role to grant the joining peer. Falls back to the invite's role, then `'write'`.
323
+ */
324
+ role?: string;
325
+ name?: string | null;
326
+ };
327
+ export type RecoverOpts = {
328
+ timeout?: number;
329
+ name?: string | null;
330
+ isMobile?: boolean;
331
+ };
332
+ export type HandleExtra = {
333
+ /**
334
+ * Display name; set on child handles by the owner flow.
335
+ */
336
+ name?: string | null;
337
+ /**
338
+ * `profile` ref, attached dynamically when the schema declares one.
339
+ */
340
+ profile?: import("../lib/utils.js").Ref;
341
+ /**
342
+ * `members` ref, attached dynamically when the schema declares one.
343
+ */
344
+ members?: import("../lib/utils.js").Ref;
345
+ };
346
+ /**
347
+ * A child handle plus its dynamically-attached refs.
348
+ */
349
+ export type Child = Handle & HandleExtra;
350
+ import ReadyResource from 'ready-resource';
351
+ import { Database } from '@cero-base/core/database';
352
+ import { Pairing } from '@cero-base/core/pairing';
353
+ import { Identity } from '@cero-base/core/identity';