@cero-base/cero 1.19.0 → 2.0.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/README.md +38 -643
- package/package.json +9 -6
- package/src/build/index.js +21 -50
- package/src/build/internal.js +121 -0
- package/src/build/schemas.js +2 -8
- package/src/extensions/handle-sync.js +3 -10
- package/src/extensions/index.js +6 -0
- package/src/extensions/profile-sync.js +0 -5
- package/src/handle/index.js +241 -266
- package/src/index.js +20 -51
- package/src/lib/bluetooth.js +25 -56
- package/src/lib/constants.js +0 -15
- package/src/lib/operators.js +22 -72
- package/src/lib/peek.js +4 -8
- package/src/lib/refs.js +2 -5
- package/src/lib/spec.js +2 -3
- package/src/local/index.js +2 -3
- package/src/rpc/client.js +20 -34
- package/src/rpc/index.js +3 -3
- package/src/rpc/server.js +23 -35
- package/types/build/index.d.ts +1 -9
- package/types/build/{builtins.d.ts → internal.d.ts} +20 -38
- package/types/extensions/handle-sync.d.ts +2 -7
- package/types/extensions/index.d.ts +22 -0
- package/types/extensions/profile-sync.d.ts +0 -4
- package/types/handle/index.d.ts +83 -101
- package/types/index.d.ts +4 -8
- package/types/lib/bluetooth.d.ts +8 -32
- package/types/lib/constants.d.ts +0 -11
- package/types/lib/operators.d.ts +18 -46
- package/types/lib/peek.d.ts +2 -3
- package/types/lib/refs.d.ts +1 -3
- package/types/lib/spec.d.ts +2 -3
- package/types/local/index.d.ts +2 -3
- package/types/rpc/client.d.ts +10 -18
- package/types/rpc/index.d.ts +3 -3
- package/types/rpc/server.d.ts +6 -9
- package/src/build/builtins.js +0 -174
- package/src/lib/internal.js +0 -9
- package/types/lib/internal.d.ts +0 -24
package/src/rpc/client.js
CHANGED
|
@@ -30,7 +30,7 @@ export { put, set, get, del, count, watch, changes, call, open, rotate, bind, de
|
|
|
30
30
|
* @property {'single'|'collection'|'action'|'handle'} [kind]
|
|
31
31
|
* @property {string} [schema]
|
|
32
32
|
* @property {string} [type]
|
|
33
|
-
* @property {boolean} [
|
|
33
|
+
* @property {boolean} [internal]
|
|
34
34
|
*
|
|
35
35
|
* @typedef {import('@cero-base/core/rpc').Spec & { meta: { ns?: string, refs: Record<string, RefInfo>, local?: { refs: Record<string, RefInfo> }, handles?: Record<string, Spec> }, handles: Record<string, Spec> }} Spec Built cero spec (schema + rpc + per-handle child specs).
|
|
36
36
|
*
|
|
@@ -48,7 +48,6 @@ export { put, set, get, del, count, watch, changes, call, open, rotate, bind, de
|
|
|
48
48
|
* @property {string|null} name
|
|
49
49
|
*/
|
|
50
50
|
|
|
51
|
-
// Compact-encoding blobId struct matching hypercore-blob-server's wire format.
|
|
52
51
|
const blobIdEnc = {
|
|
53
52
|
preencode(state, b) {
|
|
54
53
|
c.uint.preencode(state, b.blockOffset)
|
|
@@ -72,9 +71,7 @@ const blobIdEnc = {
|
|
|
72
71
|
}
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
//
|
|
76
|
-
// row-ops surface as a local cero handle but routed over the wire. `_local`
|
|
77
|
-
// selects the per-device store + JSON codec; main refs use the schema codec.
|
|
74
|
+
// the same row-ops surface as a local handle, routed over the wire
|
|
78
75
|
const operators = {
|
|
79
76
|
_local: false,
|
|
80
77
|
|
|
@@ -113,9 +110,8 @@ const operators = {
|
|
|
113
110
|
},
|
|
114
111
|
|
|
115
112
|
/**
|
|
116
|
-
* Augment a decoded row (or array of rows) to resolve file-typed fields to
|
|
117
|
-
*
|
|
118
|
-
* file id; other refs declare file fields in `meta.refs[name].files`.
|
|
113
|
+
* Augment a decoded row (or array of rows) to resolve file-typed fields to `{ id, type,
|
|
114
|
+
* size, url }` objects.
|
|
119
115
|
*
|
|
120
116
|
* @param {string} name
|
|
121
117
|
* @param {any} data
|
|
@@ -130,7 +126,7 @@ const operators = {
|
|
|
130
126
|
|
|
131
127
|
_resolveRow(name, info, row) {
|
|
132
128
|
if (!row || typeof row !== 'object') return row
|
|
133
|
-
if (info?.
|
|
129
|
+
if (info?.internal && info?.verb === 'file') {
|
|
134
130
|
if (!row.id) return row
|
|
135
131
|
try {
|
|
136
132
|
const { type, blobId } = decodeId(row.id)
|
|
@@ -318,15 +314,14 @@ const operators = {
|
|
|
318
314
|
wire.on('end', end)
|
|
319
315
|
wire.on('close', end)
|
|
320
316
|
// the channel tears the stream down on client close — that is an end,
|
|
321
|
-
// not a failure
|
|
317
|
+
// not a failure
|
|
322
318
|
wire.on('error', (err) => (err.code === 'CHANNEL_CLOSED' ? end() : out.destroy(err)))
|
|
323
319
|
return out
|
|
324
320
|
},
|
|
325
321
|
|
|
326
322
|
/**
|
|
327
|
-
* Delta subscription over the wire — same contract as the local operator:
|
|
328
|
-
*
|
|
329
|
-
* a full replay. Lossless: server-side the cursor folds under backpressure.
|
|
323
|
+
* Delta subscription over the wire — same contract as the local operator: batches of `{
|
|
324
|
+
* prev, next }` with file fields resolved, `reset` marks a full replay.
|
|
330
325
|
*/
|
|
331
326
|
changes(name, query) {
|
|
332
327
|
const refInfo = this._refInfo(name)
|
|
@@ -358,8 +353,7 @@ const operators = {
|
|
|
358
353
|
}
|
|
359
354
|
pump().catch((err) => {
|
|
360
355
|
if (out.destroyed) return
|
|
361
|
-
//
|
|
362
|
-
// client close — both are ends, not failures (same contract as watch)
|
|
356
|
+
// both are ends, not failures
|
|
363
357
|
if (err.code === 'PREMATURE_CLOSE' || err.code === 'CHANNEL_CLOSED') out.push(null)
|
|
364
358
|
else out.destroy(err)
|
|
365
359
|
})
|
|
@@ -435,10 +429,7 @@ export async function restore(me, phrase) {
|
|
|
435
429
|
}
|
|
436
430
|
|
|
437
431
|
/**
|
|
438
|
-
* Per-device `local`-namespace surface on a Client.
|
|
439
|
-
* local ref (e.g. `client.local.settings`) and routes ops over RPC with
|
|
440
|
-
* `local: true`, so they hit the server's per-device store and never
|
|
441
|
-
* replicate. Built-in local refs (identity master/keypair) are not exposed.
|
|
432
|
+
* Per-device `local`-namespace surface on a Client.
|
|
442
433
|
*/
|
|
443
434
|
class LocalRefs {
|
|
444
435
|
/** @param {Client} client */
|
|
@@ -449,7 +440,7 @@ class LocalRefs {
|
|
|
449
440
|
this.store = this
|
|
450
441
|
this._local = true
|
|
451
442
|
const refs = client.spec.meta.local?.refs || {}
|
|
452
|
-
const exposed = Object.fromEntries(Object.entries(refs).filter(([, info]) => !info.
|
|
443
|
+
const exposed = Object.fromEntries(Object.entries(refs).filter(([, info]) => !info.internal))
|
|
453
444
|
Ref.attach(this, exposed)
|
|
454
445
|
}
|
|
455
446
|
|
|
@@ -465,9 +456,9 @@ class LocalRefs {
|
|
|
465
456
|
}
|
|
466
457
|
|
|
467
458
|
/**
|
|
468
|
-
* IPC-side RPC client for cero. Wraps an `hrpc` channel and exposes the
|
|
469
|
-
*
|
|
470
|
-
*
|
|
459
|
+
* IPC-side RPC client for cero. Wraps an `hrpc` channel and exposes the same
|
|
460
|
+
* handle/ref/row API as a local cero instance, transparently routing every operation
|
|
461
|
+
* across the wire.
|
|
471
462
|
*/
|
|
472
463
|
export class Client extends RPCClient {
|
|
473
464
|
/**
|
|
@@ -505,7 +496,7 @@ export class Client extends RPCClient {
|
|
|
505
496
|
* @returns {Promise<Handle>}
|
|
506
497
|
*/
|
|
507
498
|
async _create(type, opts = {}) {
|
|
508
|
-
//
|
|
499
|
+
// routes are functions and cannot cross the wire
|
|
509
500
|
const wire = { ...opts, noAccept: opts.accept === false || undefined }
|
|
510
501
|
const stub = await this.rpc.addHandle({
|
|
511
502
|
ref: type,
|
|
@@ -541,9 +532,9 @@ export class Client extends RPCClient {
|
|
|
541
532
|
}
|
|
542
533
|
|
|
543
534
|
/**
|
|
544
|
-
* Client-side proxy for a remote handle. Exposes the same row-ops surface
|
|
545
|
-
*
|
|
546
|
-
*
|
|
535
|
+
* Client-side proxy for a remote handle. Exposes the same row-ops surface as `Client` but
|
|
536
|
+
* scoped to a single child handle id, and routes every call through the parent's RPC
|
|
537
|
+
* channel.
|
|
547
538
|
*/
|
|
548
539
|
class Handle {
|
|
549
540
|
/**
|
|
@@ -595,13 +586,8 @@ export async function connect(ipc, spec) {
|
|
|
595
586
|
}
|
|
596
587
|
|
|
597
588
|
/**
|
|
598
|
-
* Symmetric client entry. Mirrors the main `cero`, but `cero(ipc, spec)` connects
|
|
599
|
-
*
|
|
600
|
-
* surface is attached, so `import { cero } from '@cero-base/cero/client'` works
|
|
601
|
-
* just like `import { cero } from '@cero-base/cero'`.
|
|
602
|
-
*
|
|
603
|
-
* Note: `before`/`after`/`peek` are intentionally not exposed here — they hook the
|
|
604
|
-
* local write path / probe a local store, which a client proxy has no notion of.
|
|
589
|
+
* Symmetric client entry. Mirrors the main `cero`, but `cero(ipc, spec)` connects to a
|
|
590
|
+
* server (via `connect`) instead of opening a local store.
|
|
605
591
|
*
|
|
606
592
|
* @param {any} ipc Framed IPC duplex stream.
|
|
607
593
|
* @param {any} spec Built cero spec.
|
package/src/rpc/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* RPC barrel — re-exports the `Server`/`Client` classes and their
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* RPC barrel — re-exports the `Server`/`Client` classes and their `serve()`/`connect()`
|
|
3
|
+
* helpers so consumers can spin up either side of the cero IPC bridge from a single
|
|
4
|
+
* import.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
export { Server, serve } from './server.js'
|
package/src/rpc/server.js
CHANGED
|
@@ -27,10 +27,9 @@ import { put, set, get, del, count, watch, changes, call } from '../lib/operator
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* IPC-side RPC server for cero. Bridges an `hrpc` channel to a live
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* over the wire using the spec-bound codec.
|
|
30
|
+
* IPC-side RPC server for cero. Bridges an `hrpc` channel to a live `Handle` tree:
|
|
31
|
+
* lazy-initializes the root via `cero()` on the first `init` call, then exposes data ops,
|
|
32
|
+
* pairing, and handle lifecycle.
|
|
34
33
|
*/
|
|
35
34
|
export class Server extends RPCServer {
|
|
36
35
|
/**
|
|
@@ -52,14 +51,6 @@ export class Server extends RPCServer {
|
|
|
52
51
|
this._wireInit()
|
|
53
52
|
}
|
|
54
53
|
|
|
55
|
-
/** End every watch stream bound to a handle (e.g. when it closes or leaves). */
|
|
56
|
-
_endWatches(handle) {
|
|
57
|
-
const set = this._watchStreams.get(handle)
|
|
58
|
-
if (!set) return
|
|
59
|
-
for (const s of set) s.destroy()
|
|
60
|
-
this._watchStreams.delete(handle)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
54
|
/**
|
|
64
55
|
* Root cero id (null until `init` has run).
|
|
65
56
|
*
|
|
@@ -87,6 +78,14 @@ export class Server extends RPCServer {
|
|
|
87
78
|
await super._close()
|
|
88
79
|
}
|
|
89
80
|
|
|
81
|
+
/** End every watch stream bound to a handle (e.g. when it closes or leaves). */
|
|
82
|
+
_endWatches(handle) {
|
|
83
|
+
const set = this._watchStreams.get(handle)
|
|
84
|
+
if (!set) return
|
|
85
|
+
for (const s of set) s.destroy()
|
|
86
|
+
this._watchStreams.delete(handle)
|
|
87
|
+
}
|
|
88
|
+
|
|
90
89
|
/** Wire the `init` handler that lazily constructs the root cero handle. */
|
|
91
90
|
_wireInit() {
|
|
92
91
|
this.rpc.onInit(async () => {
|
|
@@ -147,7 +146,7 @@ export class Server extends RPCServer {
|
|
|
147
146
|
r.kind === 'single'
|
|
148
147
|
? codec.encodeRow(r.schema, result.data)
|
|
149
148
|
: codec.encodeRows(r.schema, result.data)
|
|
150
|
-
// total is int on the wire: -1 encodes
|
|
149
|
+
// total is int on the wire: -1 encodes null
|
|
151
150
|
return { data, total: result.total ?? -1, size: result.size ?? 0 }
|
|
152
151
|
})
|
|
153
152
|
|
|
@@ -175,17 +174,13 @@ export class Server extends RPCServer {
|
|
|
175
174
|
;({ ref: r, codec } = this._refOf(handle, ref, local))
|
|
176
175
|
live = watch(r, codec.decodeQuery(query))
|
|
177
176
|
} catch (err) {
|
|
178
|
-
//
|
|
179
|
-
// underlying response stream with it (emits a CLOSE|ERROR frame). The
|
|
180
|
-
// local RPCStream's 'error' is swallowed so it doesn't crash the server.
|
|
177
|
+
// forward the error over the wire by destroying the response stream with it
|
|
181
178
|
stream.once('error', () => {})
|
|
182
179
|
stream.writeStream.destroy(err)
|
|
183
180
|
stream.destroy()
|
|
184
181
|
return
|
|
185
182
|
}
|
|
186
|
-
// keep-latest under
|
|
187
|
-
// un-drained wire holds one pending snapshot (newest wins) instead of
|
|
188
|
-
// queueing every intermediate result set — encode only what ships
|
|
183
|
+
// keep-latest under backpressure: snapshots are idempotent
|
|
189
184
|
let pending = null
|
|
190
185
|
let blocked = false
|
|
191
186
|
const onData = (snap) => {
|
|
@@ -212,8 +207,7 @@ export class Server extends RPCServer {
|
|
|
212
207
|
if (!set) this._watchStreams.set(handle, (set = new Set()))
|
|
213
208
|
set.add(stream)
|
|
214
209
|
live.on('data', onData)
|
|
215
|
-
// channel teardown destroys the stream with CHANNEL_CLOSED
|
|
216
|
-
// below does the cleanup; the error itself must not crash the server
|
|
210
|
+
// channel teardown destroys the stream with CHANNEL_CLOSED; 'close' cleans up
|
|
217
211
|
stream.on('error', safetyCatch)
|
|
218
212
|
stream.on('close', () => {
|
|
219
213
|
live.off('data', onData)
|
|
@@ -237,8 +231,7 @@ export class Server extends RPCServer {
|
|
|
237
231
|
let set = this._watchStreams.get(handle)
|
|
238
232
|
if (!set) this._watchStreams.set(handle, (set = new Set()))
|
|
239
233
|
set.add(stream)
|
|
240
|
-
//
|
|
241
|
-
// on wire backpressure instead; the cursor folds everything missed
|
|
234
|
+
// deltas are not idempotent: hold the iteration on backpressure instead
|
|
242
235
|
const pump = async () => {
|
|
243
236
|
for await (const batch of live) {
|
|
244
237
|
const ok = stream.write({
|
|
@@ -282,13 +275,10 @@ export class Server extends RPCServer {
|
|
|
282
275
|
return { ok }
|
|
283
276
|
})
|
|
284
277
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
return { epoch }
|
|
290
|
-
})
|
|
291
|
-
}
|
|
278
|
+
this.rpc.onRotate(async ({ handle }) => {
|
|
279
|
+
const { epoch } = await this._resolve(handle).store.rotate()
|
|
280
|
+
return { epoch }
|
|
281
|
+
})
|
|
292
282
|
|
|
293
283
|
this.rpc.onJoin(async ({ parent, ref, invite }) => {
|
|
294
284
|
if (this._resolve(parent) !== this.me) throw CeroError.UNSUPPORTED('nested handles')
|
|
@@ -306,7 +296,7 @@ export class Server extends RPCServer {
|
|
|
306
296
|
const info = parent.spec.meta.refs?.[ref] || parent.spec.handles?.[ref]
|
|
307
297
|
if (!info) throw CeroError.UNKNOWN('handle type', ref)
|
|
308
298
|
const wire = parent.spec.codec.decodeCreate(data) || {}
|
|
309
|
-
// routes
|
|
299
|
+
// routes are functions and cannot cross the wire
|
|
310
300
|
const opts = { name: wire.name, role: wire.role, accept: wire.noAccept ? false : undefined }
|
|
311
301
|
const child = await this.me._create(ref, opts)
|
|
312
302
|
const id = child.id
|
|
@@ -358,9 +348,7 @@ export class Server extends RPCServer {
|
|
|
358
348
|
}
|
|
359
349
|
|
|
360
350
|
/**
|
|
361
|
-
* Resolve a `{ handle, ref }` pair to its `Ref` and codec.
|
|
362
|
-
* set, the ref is resolved against the root's per-device `local` store and
|
|
363
|
-
* paired with the codec bound from the local schema.
|
|
351
|
+
* Resolve a `{ handle, ref }` pair to its `Ref` and codec.
|
|
364
352
|
*
|
|
365
353
|
* @param {string} id
|
|
366
354
|
* @param {string} name
|
|
@@ -370,7 +358,7 @@ export class Server extends RPCServer {
|
|
|
370
358
|
_refOf(id, name, local) {
|
|
371
359
|
if (local) {
|
|
372
360
|
const info = this.spec.meta.local?.refs?.[name]
|
|
373
|
-
if (!info || info.
|
|
361
|
+
if (!info || info.internal) throw CeroError.UNKNOWN('local ref', name)
|
|
374
362
|
const r = this.me.local?.[name]
|
|
375
363
|
if (!r) throw CeroError.UNKNOWN('local ref', name)
|
|
376
364
|
return { ref: r, codec: this.spec.local.codec }
|
package/types/build/index.d.ts
CHANGED
|
@@ -20,17 +20,9 @@ export type BuildOpts = {
|
|
|
20
20
|
/**
|
|
21
21
|
* Compile a cero schema into wire-level artifacts and write them to disk.
|
|
22
22
|
*
|
|
23
|
-
* Emits a `main/` tree (schema + hyperdb + dispatch + rpc), a `local/` tree
|
|
24
|
-
* for per-device data, one `handles/<name>/` tree per child handle type, and
|
|
25
|
-
* an `index.js` that re-exports a ready-to-use `spec` object.
|
|
26
|
-
*
|
|
27
23
|
* @param {string} specDir Output directory.
|
|
28
24
|
* @param {SchemaInput} schema Either a `schema(...)` wrapper or its raw defs object.
|
|
29
25
|
* @param {BuildOpts} [opts]
|
|
30
26
|
* @returns {Promise<void>}
|
|
31
27
|
*/
|
|
32
|
-
export {
|
|
33
|
-
export declare function build(specDir: any, schema: any, { ns, extensions }?: {
|
|
34
|
-
extensions?: boolean;
|
|
35
|
-
ns?: string;
|
|
36
|
-
}): Promise<void>;
|
|
28
|
+
export declare function build(specDir: string, schema: SchemaInput, { ns, extensions }?: BuildOpts): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const defs: {
|
|
2
2
|
main: {
|
|
3
3
|
members: {
|
|
4
4
|
type: string;
|
|
@@ -34,26 +34,12 @@ export declare const refs: {
|
|
|
34
34
|
};
|
|
35
35
|
};
|
|
36
36
|
};
|
|
37
|
-
export declare function
|
|
38
|
-
export declare function builtinRefs(ns: any, scope: any): {
|
|
39
|
-
[k: string]: {
|
|
40
|
-
kind: any;
|
|
41
|
-
path: string[];
|
|
42
|
-
builtin: boolean;
|
|
43
|
-
verb: any;
|
|
44
|
-
schema: string;
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
export declare function builtinTypes(scope: any, extend: any): {
|
|
37
|
+
export declare function fields(map: any): {
|
|
48
38
|
name: string;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
name: string;
|
|
52
|
-
type: any;
|
|
53
|
-
required: boolean;
|
|
54
|
-
}[];
|
|
39
|
+
type: any;
|
|
40
|
+
required: boolean;
|
|
55
41
|
}[];
|
|
56
|
-
export declare function
|
|
42
|
+
export declare function types(scope: any, extend?: {}): {
|
|
57
43
|
name: string;
|
|
58
44
|
compact: boolean;
|
|
59
45
|
fields: {
|
|
@@ -62,35 +48,31 @@ export declare function rpcTypes(): {
|
|
|
62
48
|
required: boolean;
|
|
63
49
|
}[];
|
|
64
50
|
}[];
|
|
65
|
-
export declare function
|
|
51
|
+
export declare function refs(ns: any, scope: any): {
|
|
52
|
+
[k: string]: {
|
|
53
|
+
kind: any;
|
|
54
|
+
path: string[];
|
|
55
|
+
internal: boolean;
|
|
56
|
+
verb: any;
|
|
57
|
+
schema: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
export declare function collections(ns: any, scope: any): {
|
|
66
61
|
name: string;
|
|
67
62
|
schema: string;
|
|
68
63
|
key: string[];
|
|
69
64
|
}[];
|
|
70
|
-
export declare function
|
|
65
|
+
export declare function dispatches(ns: any): {
|
|
71
66
|
name: string;
|
|
72
67
|
requestType: string;
|
|
73
68
|
}[];
|
|
74
|
-
export declare function
|
|
75
|
-
name: string;
|
|
76
|
-
requestType: string;
|
|
77
|
-
};
|
|
78
|
-
export declare function rpcCommands(ns: any): ({
|
|
79
|
-
name: string;
|
|
69
|
+
export declare function commands(ns: any): {
|
|
70
|
+
name: string | boolean;
|
|
80
71
|
request: {
|
|
81
72
|
name: string;
|
|
82
73
|
};
|
|
83
74
|
response: {
|
|
84
75
|
name: string;
|
|
85
|
-
stream
|
|
76
|
+
stream: string | true;
|
|
86
77
|
};
|
|
87
|
-
}
|
|
88
|
-
name: string;
|
|
89
|
-
request: {
|
|
90
|
-
name: string;
|
|
91
|
-
};
|
|
92
|
-
response: {
|
|
93
|
-
name: string;
|
|
94
|
-
stream: boolean;
|
|
95
|
-
};
|
|
96
|
-
})[];
|
|
78
|
+
}[];
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Mirror a child handle's `profile` (name + avatar) onto its row in the parent's
|
|
3
|
-
*
|
|
4
|
-
* one. Adds the synced `fields` to the `handle` builtin.
|
|
5
|
-
*
|
|
6
|
-
* On create it seeds the handle's `profile.name` from the open `{ name }`, then
|
|
7
|
-
* reflects the (app-owned) `profile` onto the row. Requires your handle types to
|
|
8
|
-
* declare a `profile` single — handles without one are left untouched.
|
|
2
|
+
* Mirror a child handle's `profile` (name + avatar) onto its row in the parent's `handles`
|
|
3
|
+
* list — so a handle list shows names + avatars without opening each one.
|
|
9
4
|
*
|
|
10
5
|
* @param {{ fields?: Record<string, any> }} [opts]
|
|
11
6
|
*/
|
|
@@ -1,2 +1,24 @@
|
|
|
1
1
|
export * from './profile-sync.js';
|
|
2
2
|
export * from './handle-sync.js';
|
|
3
|
+
export declare const registry: ({
|
|
4
|
+
name: string;
|
|
5
|
+
bundled: boolean;
|
|
6
|
+
schema: {
|
|
7
|
+
profile: import("@cero-base/core").TypeDef;
|
|
8
|
+
members: {
|
|
9
|
+
kind: 'extend';
|
|
10
|
+
fields: Record<string, import("@cero-base/core").Prim>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
setup(me: any): void;
|
|
14
|
+
} | {
|
|
15
|
+
name: string;
|
|
16
|
+
bundled: boolean;
|
|
17
|
+
schema: {
|
|
18
|
+
handles: {
|
|
19
|
+
kind: 'extend';
|
|
20
|
+
fields: Record<string, import("@cero-base/core").Prim>;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
setup(me: any): void;
|
|
24
|
+
})[];
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Mirror your `profile` onto your `member` row in every handle you're in.
|
|
3
|
-
* Declares a `profile` single (`name`, `avatar`, plus any extra `fields`) and
|
|
4
|
-
* mirrors them onto the `member` builtin, then publishes when you open/join a
|
|
5
|
-
* handle and whenever your profile changes. An app may declare its own richer
|
|
6
|
-
* `profile` instead — the app schema wins.
|
|
7
3
|
*
|
|
8
4
|
* @param {{ fields?: Record<string, any> }} [opts]
|
|
9
5
|
*/
|