@cero-base/cero 2.0.0 → 2.1.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/build/index.js +45 -14
- package/src/build/internal.js +4 -2
- package/src/build/schemas.js +4 -3
- package/src/extensions/handle-sync.js +0 -1
- package/src/extensions/index.js +82 -2
- package/src/extensions/profile-sync.js +15 -11
- package/src/handle/index.js +52 -21
- package/src/index.js +12 -38
- package/src/lib/operators.js +19 -68
- package/src/lib/refs.js +8 -3
- package/src/rpc/client.js +34 -43
- package/src/rpc/server.js +17 -8
- package/types/build/index.d.ts +11 -1
- package/types/build/schemas.d.ts +4 -3
- package/types/extensions/handle-sync.d.ts +0 -1
- package/types/extensions/index.d.ts +83 -3
- package/types/extensions/profile-sync.d.ts +0 -1
- package/types/handle/index.d.ts +11 -11
- package/types/index.d.ts +19 -11
- package/types/lib/operators.d.ts +18 -43
- package/types/lib/refs.d.ts +4 -2
- package/types/rpc/client.d.ts +19 -8
- package/types/rpc/server.d.ts +1 -1
package/types/index.d.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Identity } from '@cero-base/core/identity';
|
|
2
2
|
import { Handle, Ref } from './handle/index.js';
|
|
3
3
|
import { Local } from './local/index.js';
|
|
4
|
-
import { put, set, get, del,
|
|
4
|
+
import { put, set, get, del, watch, changes, call, open, rotate, before, after } from './lib/operators.js';
|
|
5
5
|
import { peek } from './lib/peek.js';
|
|
6
6
|
import { t, schema } from './lib/spec.js';
|
|
7
|
-
import { registry } from './extensions/index.js';
|
|
8
7
|
export { Handle, Ref, Local };
|
|
9
|
-
export { put, set, get, del,
|
|
8
|
+
export { put, set, get, del, watch, changes, call, open, rotate, before, after } from './lib/operators.js';
|
|
10
9
|
export { peek } from './lib/peek.js';
|
|
11
10
|
export { t, schema } from './lib/spec.js';
|
|
12
11
|
export type CeroHandle = import('./handle/index.js').CeroHandle;
|
|
@@ -54,6 +53,14 @@ export type CeroOpts = {
|
|
|
54
53
|
* Blind-peer public keys. Rooms and files are mirrored through them so peers sync even when never online at the same time. Mirrors hold only encrypted blocks — they never read your data.
|
|
55
54
|
*/
|
|
56
55
|
mirrors?: Array<string | Uint8Array>;
|
|
56
|
+
/**
|
|
57
|
+
* How many rooms search, how many only announce, and the idle ms before the rest leave the swarm.
|
|
58
|
+
*/
|
|
59
|
+
presence?: {
|
|
60
|
+
active?: number;
|
|
61
|
+
announced?: number;
|
|
62
|
+
idle?: number;
|
|
63
|
+
};
|
|
57
64
|
/**
|
|
58
65
|
* Existing database key to recover into, skipping the pointer lookup.
|
|
59
66
|
*/
|
|
@@ -79,9 +86,13 @@ export type CeroOpts = {
|
|
|
79
86
|
*/
|
|
80
87
|
storageKey?: Uint8Array;
|
|
81
88
|
/**
|
|
82
|
-
*
|
|
89
|
+
* The extensions this instance runs, instead of the ones the spec carries. Build with the same list.
|
|
90
|
+
*/
|
|
91
|
+
extensions?: import('./extensions/index.js').Extension[];
|
|
92
|
+
/**
|
|
93
|
+
* The operators to bind, instead of the ones the spec carries.
|
|
83
94
|
*/
|
|
84
|
-
|
|
95
|
+
operators?: Record<string, any>;
|
|
85
96
|
/**
|
|
86
97
|
* `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). `maxOutbound`/`maxInbound` cap concurrent outbound links and inbound sessions. `pipe` picks the data pipe — `'l2cap'` (default, faster) or `'gatt'`; both peers must match. Absent backend on an unsupported host → `me.bluetooth.state === 'unsupported'`.
|
|
87
98
|
*/
|
|
@@ -108,13 +119,15 @@ export type CeroOpts = {
|
|
|
108
119
|
* @property {number[]} [backoffs] Swarm reconnect backoff tiers in ms (testing/tuning).
|
|
109
120
|
* @property {string} [channel] Optional network-isolation label; only same-channel peers connect.
|
|
110
121
|
* @property {Array<string | Uint8Array>} [mirrors] Blind-peer public keys. Rooms and files are mirrored through them so peers sync even when never online at the same time. Mirrors hold only encrypted blocks — they never read your data.
|
|
122
|
+
* @property {{ active?: number, announced?: number, idle?: number }} [presence] How many rooms search, how many only announce, and the idle ms before the rest leave the swarm.
|
|
111
123
|
* @property {Uint8Array} [key] Existing database key to recover into, skipping the pointer lookup.
|
|
112
124
|
* @property {Uint8Array} [encryptionKey] Pre-existing encryption key.
|
|
113
125
|
* @property {Record<string, Function>} [routes] Custom RPC routes for the database dispatcher.
|
|
114
126
|
* @property {(err: any) => void} [onerror] Background-task error handler.
|
|
115
127
|
* @property {number} [recoveryTimeout] Max wait to find another device and be admitted, in ms. Defaults to 30000.
|
|
116
128
|
* @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.
|
|
117
|
-
* @property {
|
|
129
|
+
* @property {import('./extensions/index.js').Extension[]} [extensions] The extensions this instance runs, instead of the ones the spec carries. Build with the same list.
|
|
130
|
+
* @property {Record<string, any>} [operators] The operators to bind, instead of the ones the spec carries.
|
|
118
131
|
* @property {boolean | { autoStart?: boolean, backend?: any, maxOutbound?: number, maxInbound?: number, pipe?: 'l2cap' | 'gatt' }} [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). `maxOutbound`/`maxInbound` cap concurrent outbound links and inbound sessions. `pipe` picks the data pipe — `'l2cap'` (default, faster) or `'gatt'`; both peers must match. Absent backend on an unsupported host → `me.bluetooth.state === 'unsupported'`.
|
|
119
132
|
*/
|
|
120
133
|
/**
|
|
@@ -132,7 +145,6 @@ export declare namespace cero {
|
|
|
132
145
|
export { set };
|
|
133
146
|
export { get };
|
|
134
147
|
export { del };
|
|
135
|
-
export { count };
|
|
136
148
|
export { watch };
|
|
137
149
|
export { changes };
|
|
138
150
|
export { call };
|
|
@@ -143,10 +155,6 @@ export declare namespace cero {
|
|
|
143
155
|
export { peek };
|
|
144
156
|
export { restore };
|
|
145
157
|
export { schema };
|
|
146
|
-
export { bind };
|
|
147
|
-
export { define };
|
|
148
|
-
export { registry as _registry };
|
|
149
|
-
export var use: (...exts: any[]) => void;
|
|
150
158
|
}
|
|
151
159
|
/**
|
|
152
160
|
* Restore a cero instance from a mnemonic phrase.
|
package/types/lib/operators.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type Ref = import('./refs.js').Ref;
|
|
2
|
+
export type HookContext = import('@cero-base/core/database').HookContext;
|
|
2
3
|
export type CeroHandle = import('../handle/index.js').CeroHandle;
|
|
3
4
|
export type SingleResult = {
|
|
4
5
|
data: any;
|
|
@@ -13,6 +14,7 @@ export type GetByIdResult = {
|
|
|
13
14
|
};
|
|
14
15
|
/**
|
|
15
16
|
* @typedef {import('./refs.js').Ref} Ref
|
|
17
|
+
* @typedef {import('@cero-base/core/database').HookContext} HookContext
|
|
16
18
|
* @typedef {import('../handle/index.js').CeroHandle} CeroHandle
|
|
17
19
|
* @typedef {{ data: any }} SingleResult
|
|
18
20
|
* @typedef {{ data: any[], total: number, size: number }} ListResult
|
|
@@ -61,16 +63,6 @@ export declare function set(ref: Ref, row: Record<string, any>, opts?: {
|
|
|
61
63
|
* @returns {Promise<void>}
|
|
62
64
|
*/
|
|
63
65
|
export declare function del(ref: Ref, id?: string): Promise<void>;
|
|
64
|
-
/**
|
|
65
|
-
* Count rows on `ref`, optionally filtered.
|
|
66
|
-
*
|
|
67
|
-
* @param {Ref} ref
|
|
68
|
-
* @param {Record<string, any>} [q]
|
|
69
|
-
* @returns {Promise<{ data: number }>}
|
|
70
|
-
*/
|
|
71
|
-
export declare function count(ref: Ref, q?: Record<string, any>): Promise<{
|
|
72
|
-
data: number;
|
|
73
|
-
}>;
|
|
74
66
|
/**
|
|
75
67
|
* Invoke an `action`-kind ref (a custom mutation declared in the schema).
|
|
76
68
|
*
|
|
@@ -80,34 +72,35 @@ export declare function count(ref: Ref, q?: Record<string, any>): Promise<{
|
|
|
80
72
|
*/
|
|
81
73
|
export declare function call(ref: Ref, d?: Record<string, any>): Promise<any>;
|
|
82
74
|
/**
|
|
83
|
-
*
|
|
75
|
+
* Rule that runs before a write to `ref` lands — at apply, on every peer, inside the op's
|
|
76
|
+
* transaction. Return `false` to refuse it: the writer's own call rejects with `REFUSED`.
|
|
77
|
+
* `ctx` is `{ op, name, row, existing, id, memberId, role, get, put, set, del }`; mutate
|
|
78
|
+
* `ctx.row` to rewrite what is stored. `op` is the op as it applies, so an upsert on a
|
|
79
|
+
* collection is a `put`. The four operators on `ctx` read and write the room as it stands at
|
|
80
|
+
* this op, inside the transaction. Must be deterministic — read only `ctx`, never a clock or
|
|
81
|
+
* local state — and registered before any op applies, in the process that owns the data. The
|
|
82
|
+
* imported operators throw inside a hook; use the ones on `ctx`. Not available over RPC.
|
|
84
83
|
*
|
|
85
84
|
* @param {Ref} ref
|
|
86
|
-
* @param {(ctx:
|
|
85
|
+
* @param {(ctx: HookContext) => unknown} fn
|
|
87
86
|
* @param {{ signal?: AbortSignal }} [opts]
|
|
88
87
|
* @returns {() => void}
|
|
89
88
|
*/
|
|
90
|
-
export declare function before(ref: Ref, fn: (ctx: {
|
|
91
|
-
op: string;
|
|
92
|
-
name: string;
|
|
93
|
-
row: any;
|
|
94
|
-
}) => any, opts?: {
|
|
89
|
+
export declare function before(ref: Ref, fn: (ctx: HookContext) => unknown, opts?: {
|
|
95
90
|
signal?: AbortSignal;
|
|
96
91
|
}): () => void;
|
|
97
92
|
/**
|
|
98
|
-
*
|
|
99
|
-
*
|
|
93
|
+
* Rule that runs after a write to `ref` lands — at apply, on every peer, inside the op's
|
|
94
|
+
* transaction. Write derived rows through `ctx.put` / `ctx.set` / `ctx.del`; a throw refuses
|
|
95
|
+
* the whole op. Same `ctx` and the same determinism and registration rules as `before`. Use
|
|
96
|
+
* `changes(ref)` instead to observe writes locally.
|
|
100
97
|
*
|
|
101
98
|
* @param {Ref} ref
|
|
102
|
-
* @param {(ctx:
|
|
99
|
+
* @param {(ctx: HookContext) => unknown} fn
|
|
103
100
|
* @param {{ signal?: AbortSignal }} [opts]
|
|
104
101
|
* @returns {() => void}
|
|
105
102
|
*/
|
|
106
|
-
export declare function after(ref: Ref, fn: (ctx: {
|
|
107
|
-
op: string;
|
|
108
|
-
name: string;
|
|
109
|
-
row: any;
|
|
110
|
-
}) => void, opts?: {
|
|
103
|
+
export declare function after(ref: Ref, fn: (ctx: HookContext) => unknown, opts?: {
|
|
111
104
|
signal?: AbortSignal;
|
|
112
105
|
}): () => void;
|
|
113
106
|
/**
|
|
@@ -162,21 +155,3 @@ export declare function open(ref: Ref, arg?: string | {
|
|
|
162
155
|
export declare function rotate(handle: any): Promise<{
|
|
163
156
|
epoch: number;
|
|
164
157
|
}>;
|
|
165
|
-
/**
|
|
166
|
-
* Put custom operators on `handle`, currying it as their first argument so
|
|
167
|
-
* `handle.ns.fn(args)` calls `fn(handle, args)`.
|
|
168
|
-
*
|
|
169
|
-
* @param {any} handle
|
|
170
|
-
* @param {Record<string, any> | string | null} arg
|
|
171
|
-
* @returns {any} handle
|
|
172
|
-
*/
|
|
173
|
-
export declare function bind(handle: any, arg: Record<string, any> | string | null): any;
|
|
174
|
-
/**
|
|
175
|
-
* Register custom operators by scope. A bare key binds on the root handle; a key that
|
|
176
|
-
* names a child-handle type binds on every handle of that type.
|
|
177
|
-
*
|
|
178
|
-
* @param {Record<string, any>} map
|
|
179
|
-
*/
|
|
180
|
-
export declare function define(map: Record<string, any>): void;
|
|
181
|
-
/** Test seam: clear all registered operators. */
|
|
182
|
-
export declare function _clearDefined(): void;
|
package/types/lib/refs.d.ts
CHANGED
|
@@ -18,19 +18,21 @@ export declare class Ref {
|
|
|
18
18
|
name: string;
|
|
19
19
|
kind: string;
|
|
20
20
|
schema: string;
|
|
21
|
+
type: any;
|
|
21
22
|
/**
|
|
22
23
|
* @param {any} handle Owner — a `Handle` (or `Local`) the ref lives on.
|
|
23
24
|
* @param {string} name Ref name as declared in the schema.
|
|
24
25
|
* @param {string} kind Ref kind: `'collection'`, `'single'`, `'action'`, or `'handle'`.
|
|
25
26
|
* @param {string | null} [schema] Fully-qualified schema id, if any.
|
|
26
27
|
*/
|
|
27
|
-
constructor(handle: any, name: string, kind: string, schema?: string | null);
|
|
28
|
+
constructor(handle: any, name: string, kind: string, schema?: string | null, type?: any);
|
|
28
29
|
/**
|
|
29
30
|
* Attach a `Ref` property to `target` for every entry in `refs`, so callers
|
|
30
31
|
* write `handle.someRef` instead of looking refs up by name.
|
|
31
32
|
*
|
|
32
33
|
* @param {any} target
|
|
33
34
|
* @param {Record<string, RefInfo>} refs
|
|
35
|
+
* @param {Record<string, any>} [handles] The handle types, so `target.room.notes` names every room's notes.
|
|
34
36
|
*/
|
|
35
|
-
static attach(target: any, refs: Record<string, RefInfo>): void;
|
|
37
|
+
static attach(target: any, refs: Record<string, RefInfo>, handles?: Record<string, any>): void;
|
|
36
38
|
}
|
package/types/rpc/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RPCClient } from '@cero-base/core/rpc';
|
|
2
|
-
import { put, set, get, del,
|
|
2
|
+
import { put, set, get, del, watch, changes, call, open, rotate } from '../lib/operators.js';
|
|
3
3
|
import { t, schema } from '../lib/spec.js';
|
|
4
|
-
export { put, set, get, del,
|
|
4
|
+
export { put, set, get, del, watch, changes, call, open, rotate, t, schema };
|
|
5
5
|
export type BaseRPCClient = import('@cero-base/core/rpc').RPCClient;
|
|
6
6
|
export type RefInfo = {
|
|
7
7
|
kind?: 'single' | 'collection' | 'action' | 'handle';
|
|
@@ -70,6 +70,7 @@ declare class LocalRefs {
|
|
|
70
70
|
* across the wire.
|
|
71
71
|
*/
|
|
72
72
|
export declare class Client extends RPCClient {
|
|
73
|
+
operators: Record<string, any>;
|
|
73
74
|
id: any;
|
|
74
75
|
deviceId: any;
|
|
75
76
|
store: this;
|
|
@@ -83,9 +84,16 @@ export declare class Client extends RPCClient {
|
|
|
83
84
|
/**
|
|
84
85
|
* @param {any} ipc Framed IPC stream (must be writable).
|
|
85
86
|
* @param {Spec} spec Compiled cero spec (schema + rpc + handles).
|
|
87
|
+
* @param {{ operators?: Record<string, any> }} [opts] The operators to bind, instead of the ones the spec carries.
|
|
86
88
|
*/
|
|
87
|
-
constructor(ipc: any, spec: Spec
|
|
89
|
+
constructor(ipc: any, spec: Spec, opts?: {
|
|
90
|
+
operators?: Record<string, any>;
|
|
91
|
+
});
|
|
88
92
|
_open(): Promise<void>;
|
|
93
|
+
/** Pause networking and storage on the server. Idempotent. */
|
|
94
|
+
suspend(): Promise<void>;
|
|
95
|
+
/** Resume a suspended server. Idempotent. */
|
|
96
|
+
resume(): Promise<void>;
|
|
89
97
|
/**
|
|
90
98
|
* Create a new child handle of the given type.
|
|
91
99
|
*
|
|
@@ -142,18 +150,24 @@ declare class Handle {
|
|
|
142
150
|
*
|
|
143
151
|
* @param {any} ipc
|
|
144
152
|
* @param {object} spec
|
|
153
|
+
* @param {{ operators?: Record<string, any> }} [opts]
|
|
145
154
|
* @returns {Promise<Client>}
|
|
146
155
|
*/
|
|
147
|
-
export declare function connect(ipc: any, spec: object
|
|
156
|
+
export declare function connect(ipc: any, spec: object, opts?: {
|
|
157
|
+
operators?: Record<string, any>;
|
|
158
|
+
}): Promise<Client>;
|
|
148
159
|
/**
|
|
149
160
|
* Symmetric client entry. Mirrors the main `cero`, but `cero(ipc, spec)` connects to a
|
|
150
161
|
* server (via `connect`) instead of opening a local store.
|
|
151
162
|
*
|
|
152
163
|
* @param {any} ipc Framed IPC duplex stream.
|
|
153
164
|
* @param {any} spec Built cero spec.
|
|
165
|
+
* @param {{ operators?: Record<string, any> }} [opts]
|
|
154
166
|
* @returns {Promise<Client>}
|
|
155
167
|
*/
|
|
156
|
-
export declare function cero(ipc: any, spec: any
|
|
168
|
+
export declare function cero(ipc: any, spec: any, opts?: {
|
|
169
|
+
operators?: Record<string, any>;
|
|
170
|
+
}): Promise<Client>;
|
|
157
171
|
export declare namespace cero {
|
|
158
172
|
export { connect };
|
|
159
173
|
export { restore };
|
|
@@ -162,13 +176,10 @@ export declare namespace cero {
|
|
|
162
176
|
export { set };
|
|
163
177
|
export { get };
|
|
164
178
|
export { del };
|
|
165
|
-
export { count };
|
|
166
179
|
export { watch };
|
|
167
180
|
export { changes };
|
|
168
181
|
export { call };
|
|
169
182
|
export { open };
|
|
170
183
|
export { rotate };
|
|
171
|
-
export { bind };
|
|
172
|
-
export { define };
|
|
173
184
|
export { schema };
|
|
174
185
|
}
|
package/types/rpc/server.d.ts
CHANGED
|
@@ -101,7 +101,7 @@ export declare class Server extends RPCServer {
|
|
|
101
101
|
_wireInit(): void;
|
|
102
102
|
/** Wire the `restore` handler that rebuilds the local store from a phrase. */
|
|
103
103
|
_wireRestore(): void;
|
|
104
|
-
/** Register the row-level RPC handlers (put/set/get/del/
|
|
104
|
+
/** Register the row-level RPC handlers (put/set/get/del/watch/call). */
|
|
105
105
|
_wireData(): void;
|
|
106
106
|
/** Register invite/revoke/join RPC handlers. */
|
|
107
107
|
_wirePairing(): void;
|