@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.
Files changed (40) hide show
  1. package/README.md +38 -643
  2. package/package.json +9 -6
  3. package/src/build/index.js +21 -50
  4. package/src/build/internal.js +121 -0
  5. package/src/build/schemas.js +2 -8
  6. package/src/extensions/handle-sync.js +3 -10
  7. package/src/extensions/index.js +6 -0
  8. package/src/extensions/profile-sync.js +0 -5
  9. package/src/handle/index.js +241 -266
  10. package/src/index.js +20 -51
  11. package/src/lib/bluetooth.js +25 -56
  12. package/src/lib/constants.js +0 -15
  13. package/src/lib/operators.js +22 -72
  14. package/src/lib/peek.js +4 -8
  15. package/src/lib/refs.js +2 -5
  16. package/src/lib/spec.js +2 -3
  17. package/src/local/index.js +2 -3
  18. package/src/rpc/client.js +20 -34
  19. package/src/rpc/index.js +3 -3
  20. package/src/rpc/server.js +23 -35
  21. package/types/build/index.d.ts +1 -9
  22. package/types/build/{builtins.d.ts → internal.d.ts} +20 -38
  23. package/types/extensions/handle-sync.d.ts +2 -7
  24. package/types/extensions/index.d.ts +22 -0
  25. package/types/extensions/profile-sync.d.ts +0 -4
  26. package/types/handle/index.d.ts +83 -101
  27. package/types/index.d.ts +4 -8
  28. package/types/lib/bluetooth.d.ts +8 -32
  29. package/types/lib/constants.d.ts +0 -11
  30. package/types/lib/operators.d.ts +18 -46
  31. package/types/lib/peek.d.ts +2 -3
  32. package/types/lib/refs.d.ts +1 -3
  33. package/types/lib/spec.d.ts +2 -3
  34. package/types/local/index.d.ts +2 -3
  35. package/types/rpc/client.d.ts +10 -18
  36. package/types/rpc/index.d.ts +3 -3
  37. package/types/rpc/server.d.ts +6 -9
  38. package/src/build/builtins.js +0 -174
  39. package/src/lib/internal.js +0 -9
  40. package/types/lib/internal.d.ts +0 -24
@@ -57,10 +57,9 @@ export type GetResult = {
57
57
  * @typedef {{ data: any, total?: number, size?: number }} GetResult Single-ref get omits `total`/`size`; list/handle refs include them.
58
58
  */
59
59
  /**
60
- * IPC-side RPC server for cero. Bridges an `hrpc` channel to a live
61
- * `Handle` tree: lazy-initializes the root via `cero()` on the first
62
- * `init` call, then exposes data ops, pairing, and handle lifecycle
63
- * over the wire using the spec-bound codec.
60
+ * IPC-side RPC server for cero. Bridges an `hrpc` channel to a live `Handle` tree:
61
+ * lazy-initializes the root via `cero()` on the first `init` call, then exposes data ops,
62
+ * pairing, and handle lifecycle.
64
63
  */
65
64
  export declare class Server extends RPCServer {
66
65
  storage: string;
@@ -83,8 +82,6 @@ export declare class Server extends RPCServer {
83
82
  * @param {Partial<ServerOpts>} [opts]
84
83
  */
85
84
  constructor(ipc: any, spec: object, { storage, ...opts }?: Partial<ServerOpts>);
86
- /** End every watch stream bound to a handle (e.g. when it closes or leaves). */
87
- _endWatches(handle: any): void;
88
85
  /**
89
86
  * Root cero id (null until `init` has run).
90
87
  *
@@ -98,6 +95,8 @@ export declare class Server extends RPCServer {
98
95
  */
99
96
  get identity(): any;
100
97
  _close(): Promise<void>;
98
+ /** End every watch stream bound to a handle (e.g. when it closes or leaves). */
99
+ _endWatches(handle: any): void;
101
100
  /** Wire the `init` handler that lazily constructs the root cero handle. */
102
101
  _wireInit(): void;
103
102
  /** Wire the `restore` handler that rebuilds the local store from a phrase. */
@@ -117,9 +116,7 @@ export declare class Server extends RPCServer {
117
116
  */
118
117
  _resolve(id: string): any;
119
118
  /**
120
- * Resolve a `{ handle, ref }` pair to its `Ref` and codec. When `local` is
121
- * set, the ref is resolved against the root's per-device `local` store and
122
- * paired with the codec bound from the local schema.
119
+ * Resolve a `{ handle, ref }` pair to its `Ref` and codec.
123
120
  *
124
121
  * @param {string} id
125
122
  * @param {string} name
@@ -1,174 +0,0 @@
1
- // Build wiring for the builtin schemas (schemas.js): turns the grouped field
2
- // maps into the type / collection / dispatch / command descriptors the builder
3
- // registers. Every cero schema includes these; app refs are added on top.
4
- import { CeroError } from '@cero-base/core/errors'
5
- import { COUNTERS, EPOCHS, DB_TYPE } from '../lib/constants.js'
6
- import * as schemas from './schemas.js'
7
-
8
- // Builtin collections by scope — ref name → { type, kind? }. kind defaults to
9
- // 'collection' (id-keyed); 'single' has no key. Dispatches are derived for
10
- // main; counters is internal (a collection with no add/set/del).
11
- export const refs = {
12
- main: {
13
- members: { type: 'member' },
14
- devices: { type: 'device' },
15
- invites: { type: 'invite' },
16
- handles: { type: 'handle' },
17
- files: { type: 'file' }
18
- },
19
- local: {
20
- master: { type: 'master', kind: 'single' },
21
- keypair: { type: 'keypair', kind: 'single' },
22
- 'handle-keypairs': { type: 'handle-keypair' },
23
- environment: { type: 'environment', kind: 'single' }
24
- }
25
- }
26
-
27
- export function getHyperdbType(prim) {
28
- return DB_TYPE[prim] || 'string'
29
- }
30
-
31
- const at = (ns, n) => `@${ns}/${n}`
32
- const keyOf = (def) => (def.kind === 'single' ? [] : ['id'])
33
-
34
- const fields = (map) =>
35
- Object.entries(map).map(([name, m]) => ({
36
- name,
37
- type: getHyperdbType(m.prim),
38
- required: m.required === true
39
- }))
40
-
41
- // Merge app `t.extend` fields into a builtin's base fields — base can't be redeclared.
42
- const merge = (type, base, extra) => {
43
- if (!extra) return base
44
- for (const k in extra) {
45
- if (k in base) {
46
- throw CeroError.INVALID(`'${k}' is a base field of '${type}' and cannot be redeclared`)
47
- }
48
- }
49
- return { ...base, ...extra }
50
- }
51
-
52
- const descriptors = (group, extend = {}) =>
53
- Object.entries(group).map(([name, base]) => ({
54
- name,
55
- compact: false,
56
- fields: fields(merge(name, base, extend[name]))
57
- }))
58
-
59
- // meta.refs entries for a scope's builtins.
60
- export function builtinRefs(ns, scope) {
61
- return Object.fromEntries(
62
- Object.entries(refs[scope]).map(([name, def]) => [
63
- name,
64
- {
65
- kind: def.kind || 'collection',
66
- path: [name],
67
- builtin: true,
68
- ...(scope === 'main' && { verb: def.type }),
69
- schema: at(ns, def.type)
70
- }
71
- ])
72
- )
73
- }
74
-
75
- // hyperschema type descriptors. scope is 'main' | 'local' | 'rpc'; `extend`
76
- // merges app `t.extend` fields into the matching type.
77
- export function builtinTypes(scope, extend) {
78
- return descriptors(schemas[scope], extend)
79
- }
80
- export function rpcTypes() {
81
- return descriptors(schemas.rpc)
82
- }
83
-
84
- // hyperdb collection descriptors for a scope.
85
- export function builtinCollections(ns, scope) {
86
- const out = Object.entries(refs[scope]).map(([name, def]) => ({
87
- name,
88
- schema: at(ns, def.type),
89
- key: keyOf(def)
90
- }))
91
- if (scope === 'main') {
92
- out.push({ name: COUNTERS, schema: at(ns, 'counter'), key: ['name'] })
93
- out.push({ name: EPOCHS, schema: at(ns, 'epoch'), key: ['epoch'] })
94
- }
95
- return out
96
- }
97
-
98
- // hyperdispatch descriptors (main scope only).
99
- export function builtinDispatches(ns) {
100
- return [
101
- { name: 'add-writer', requestType: at(ns, 'writer') },
102
- { name: 'del-writer', requestType: at(ns, 'writer') },
103
- { name: 'claim-writer', requestType: at(ns, 'claim') },
104
- ...Object.values(refs.main).flatMap(({ type }) => [
105
- { name: `add-${type}`, requestType: at(ns, type) },
106
- { name: `set-${type}`, requestType: at(ns, type) },
107
- { name: `del-${type}`, requestType: at(ns, 'del-by-id') }
108
- ])
109
- ]
110
- }
111
-
112
- // Registered AFTER the app's own dispatches (see build/index.js): hyperdispatch
113
- // numbers routes positionally and persists them, so a spec built before
114
- // rotation must see rotate-key appended at the end — inserting it into the
115
- // builtin group would collide with the app's persisted route ids on an
116
- // incremental rebuild.
117
- export function rotateDispatch(ns) {
118
- return { name: 'rotate-key', requestType: at(ns, 'epoch') }
119
- }
120
-
121
- export function rpcCommands(ns) {
122
- const ref = (n) => at(ns, n)
123
- return [
124
- { name: 'init', request: { name: ref('req-empty') }, response: { name: ref('res-identity') } },
125
- {
126
- name: 'restore',
127
- request: { name: ref('req-restore') },
128
- response: { name: ref('res-identity') }
129
- },
130
- { name: 'seed', request: { name: ref('req-empty') }, response: { name: ref('res-seed') } },
131
- { name: 'add-row', request: { name: ref('req-row') }, response: { name: ref('res-data') } },
132
- {
133
- name: 'add-file',
134
- request: { name: ref('req-add-file') },
135
- response: { name: ref('res-data') }
136
- },
137
- {
138
- name: 'add-handle',
139
- request: { name: ref('req-row') },
140
- response: { name: ref('res-handle') }
141
- },
142
- { name: 'set', request: { name: ref('req-row') }, response: { name: ref('res-data') } },
143
- { name: 'get', request: { name: ref('req-query') }, response: { name: ref('res-rows') } },
144
- { name: 'get-one', request: { name: ref('req-id') }, response: { name: ref('res-data') } },
145
- { name: 'del', request: { name: ref('req-id') }, response: { name: ref('res-ok') } },
146
- { name: 'count', request: { name: ref('req-query') }, response: { name: ref('res-count') } },
147
- {
148
- name: 'watch',
149
- request: { name: ref('req-query') },
150
- response: { name: ref('res-rows'), stream: true }
151
- },
152
- { name: 'call', request: { name: ref('req-call') }, response: { name: ref('res-data') } },
153
- { name: 'invite', request: { name: ref('req-invite') }, response: { name: ref('res-invite') } },
154
- { name: 'revoke', request: { name: ref('req-revoke') }, response: { name: ref('res-ok') } },
155
- { name: 'join', request: { name: ref('req-join') }, response: { name: ref('res-handle') } },
156
- {
157
- name: 'open-handle',
158
- request: { name: ref('req-open') },
159
- response: { name: ref('res-handle') }
160
- },
161
- {
162
- name: 'close-handle',
163
- request: { name: ref('req-handle') },
164
- response: { name: ref('res-ok') }
165
- },
166
- { name: 'leave', request: { name: ref('req-handle') }, response: { name: ref('res-ok') } },
167
- {
168
- name: 'changes',
169
- request: { name: ref('req-query') },
170
- response: { name: ref('res-changes'), stream: true }
171
- },
172
- { name: 'rotate', request: { name: ref('req-handle') }, response: { name: ref('res-epoch') } }
173
- ]
174
- }
@@ -1,9 +0,0 @@
1
- // Process-wide registry for extensions registered via `cero.use()`.
2
- // `build()` folds in each extension's schema; `cero()` runs each setup.
3
- // The bundled extensions are on by default — `cero.use(profileSync({...}))`
4
- // replaces a default by name, `{ extensions: false }` (on build and cero)
5
- // leaves them out entirely.
6
- import { profileSync } from '../extensions/profile-sync.js'
7
- import { handleSync } from '../extensions/handle-sync.js'
8
-
9
- export const internal = { extensions: [profileSync(), handleSync()] }
@@ -1,24 +0,0 @@
1
- export declare const internal: {
2
- extensions: ({
3
- name: string;
4
- bundled: boolean;
5
- schema: {
6
- profile: import("@cero-base/core").TypeDef;
7
- members: {
8
- kind: 'extend';
9
- fields: Record<string, import("@cero-base/core").Prim>;
10
- };
11
- };
12
- setup(me: any): void;
13
- } | {
14
- name: string;
15
- bundled: boolean;
16
- schema: {
17
- handles: {
18
- kind: 'extend';
19
- fields: Record<string, import("@cero-base/core").Prim>;
20
- };
21
- };
22
- setup(me: any): void;
23
- })[];
24
- };