@cero-base/cero 1.18.2 → 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 (44) hide show
  1. package/README.md +38 -644
  2. package/package.json +16 -12
  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 +255 -300
  10. package/src/index.js +65 -112
  11. package/src/lib/bluetooth.js +25 -56
  12. package/src/lib/constants.js +0 -15
  13. package/src/lib/operators.js +24 -74
  14. package/src/lib/peek.js +4 -8
  15. package/src/lib/refs.js +46 -0
  16. package/src/lib/spec.js +2 -3
  17. package/src/local/index.js +4 -5
  18. package/src/rpc/client.js +27 -39
  19. package/src/rpc/index.js +3 -3
  20. package/src/rpc/server.js +29 -40
  21. package/types/build/index.d.ts +19 -7
  22. package/types/build/internal.d.ts +78 -0
  23. package/types/build/schemas.d.ts +3 -3
  24. package/types/extensions/handle-sync.d.ts +4 -9
  25. package/types/extensions/index.d.ts +24 -2
  26. package/types/extensions/profile-sync.d.ts +2 -6
  27. package/types/handle/index.d.ts +218 -254
  28. package/types/index.d.ts +78 -102
  29. package/types/lib/bluetooth.d.ts +24 -46
  30. package/types/lib/constants.d.ts +5 -16
  31. package/types/lib/operators.d.ts +49 -77
  32. package/types/lib/peek.d.ts +3 -4
  33. package/types/lib/refs.d.ts +36 -0
  34. package/types/lib/spec.d.ts +5 -1
  35. package/types/local/index.d.ts +24 -23
  36. package/types/rpc/client.d.ts +107 -127
  37. package/types/rpc/index.d.ts +7 -2
  38. package/types/rpc/server.d.ts +62 -76
  39. package/src/build/builtins.js +0 -174
  40. package/src/lib/internal.js +0 -9
  41. package/src/lib/utils.js +0 -67
  42. package/types/build/builtins.d.ts +0 -100
  43. package/types/lib/internal.d.ts +0 -24
  44. package/types/lib/utils.d.ts +0 -55
@@ -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()] }
package/src/lib/utils.js DELETED
@@ -1,67 +0,0 @@
1
- import { CeroError } from '@cero-base/core/errors'
2
-
3
- /**
4
- * @typedef {'collection' | 'single' | 'action' | 'handle'} RefKind
5
- * @typedef {{ kind?: string, schema?: string }} RefInfo
6
- * Shape of the entries in `meta.refs` — describes a single ref name.
7
- * `kind` is one of {@link RefKind}, kept as `string` since it originates
8
- * from a generated spec.
9
- */
10
-
11
- /**
12
- * Typed pointer to a single ref (table or handle slot) on a `Handle` or
13
- * `Local`. Operators (`put`/`get`/`open`/...) take a `Ref` as their first
14
- * argument and dispatch through the owning handle's store.
15
- */
16
- export class Ref {
17
- /**
18
- * @param {any} handle Owner — a `Handle` (or `Local`) the ref lives on.
19
- * @param {string} name Ref name as declared in the schema.
20
- * @param {string} kind Ref kind: `'collection'`, `'single'`, `'action'`, or `'handle'`.
21
- * @param {string | null} [schema] Fully-qualified schema id, if any.
22
- */
23
- constructor(handle, name, kind, schema = null) {
24
- this.handle = handle
25
- this.name = name
26
- this.kind = kind
27
- this.schema = schema
28
- }
29
- }
30
-
31
- /**
32
- * Attach a `Ref` property to `target` for every entry in `refs`. Used by
33
- * `Handle` and `Local` during `_open()` so callers can write
34
- * `handle.someRef` instead of looking refs up by name.
35
- *
36
- * @param {any} target
37
- * @param {Record<string, RefInfo>} refs
38
- */
39
- export function attachRefs(target, refs) {
40
- for (const [name, info] of Object.entries(refs || {})) {
41
- // Fail loud rather than silently overwrite a method/property (close, on,
42
- // store, …) when a schema declares a ref named like a reserved member.
43
- if (name in target) {
44
- throw CeroError.INVALID(
45
- `schema ref '${name}' collides with a reserved ${target.constructor?.name || 'handle'} member — rename it`
46
- )
47
- }
48
- target[name] = new Ref(target, name, info.kind, info.schema)
49
- }
50
- }
51
-
52
- /**
53
- * Run `cb` when `signal` aborts — or immediately if it already has. No-op
54
- * without a signal. The listener removes itself on fire. Returns a disposer that
55
- * detaches the listener early, so a manual unsubscribe doesn't leave it lingering
56
- * on a long-lived signal.
57
- *
58
- * @param {AbortSignal | undefined} signal
59
- * @param {() => void} cb
60
- * @returns {(() => void) | undefined}
61
- */
62
- export function onAbort(signal, cb) {
63
- if (!signal) return
64
- if (signal.aborted) return void cb()
65
- signal.addEventListener('abort', cb, { once: true })
66
- return () => signal.removeEventListener('abort', cb)
67
- }
@@ -1,100 +0,0 @@
1
- export function getHyperdbType(prim: any): any;
2
- export function builtinRefs(ns: any, scope: any): {
3
- [k: string]: {
4
- schema: string;
5
- verb: any;
6
- kind: any;
7
- path: string[];
8
- builtin: boolean;
9
- };
10
- };
11
- export function builtinTypes(scope: any, extend: any): {
12
- name: string;
13
- compact: boolean;
14
- fields: {
15
- name: string;
16
- type: any;
17
- required: boolean;
18
- }[];
19
- }[];
20
- export function rpcTypes(): {
21
- name: string;
22
- compact: boolean;
23
- fields: {
24
- name: string;
25
- type: any;
26
- required: boolean;
27
- }[];
28
- }[];
29
- export function builtinCollections(ns: any, scope: any): {
30
- name: string;
31
- schema: string;
32
- key: string[];
33
- }[];
34
- export function builtinDispatches(ns: any): {
35
- name: string;
36
- requestType: string;
37
- }[];
38
- export function rotateDispatch(ns: any): {
39
- name: string;
40
- requestType: string;
41
- };
42
- export function rpcCommands(ns: any): ({
43
- name: string;
44
- request: {
45
- name: string;
46
- };
47
- response: {
48
- name: string;
49
- stream?: undefined;
50
- };
51
- } | {
52
- name: string;
53
- request: {
54
- name: string;
55
- };
56
- response: {
57
- name: string;
58
- stream: boolean;
59
- };
60
- })[];
61
- export namespace refs {
62
- namespace main {
63
- namespace members {
64
- let type: string;
65
- }
66
- namespace devices {
67
- let type_1: string;
68
- export { type_1 as type };
69
- }
70
- namespace invites {
71
- let type_2: string;
72
- export { type_2 as type };
73
- }
74
- namespace handles {
75
- let type_3: string;
76
- export { type_3 as type };
77
- }
78
- namespace files {
79
- let type_4: string;
80
- export { type_4 as type };
81
- }
82
- }
83
- let local: {
84
- master: {
85
- type: string;
86
- kind: string;
87
- };
88
- keypair: {
89
- type: string;
90
- kind: string;
91
- };
92
- 'handle-keypairs': {
93
- type: string;
94
- };
95
- environment: {
96
- type: string;
97
- kind: string;
98
- };
99
- };
100
- }
@@ -1,24 +0,0 @@
1
- export namespace internal {
2
- let 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
- }
@@ -1,55 +0,0 @@
1
- /**
2
- * Attach a `Ref` property to `target` for every entry in `refs`. Used by
3
- * `Handle` and `Local` during `_open()` so callers can write
4
- * `handle.someRef` instead of looking refs up by name.
5
- *
6
- * @param {any} target
7
- * @param {Record<string, RefInfo>} refs
8
- */
9
- export function attachRefs(target: any, refs: Record<string, RefInfo>): void;
10
- /**
11
- * Run `cb` when `signal` aborts — or immediately if it already has. No-op
12
- * without a signal. The listener removes itself on fire. Returns a disposer that
13
- * detaches the listener early, so a manual unsubscribe doesn't leave it lingering
14
- * on a long-lived signal.
15
- *
16
- * @param {AbortSignal | undefined} signal
17
- * @param {() => void} cb
18
- * @returns {(() => void) | undefined}
19
- */
20
- export function onAbort(signal: AbortSignal | undefined, cb: () => void): (() => void) | undefined;
21
- /**
22
- * @typedef {'collection' | 'single' | 'action' | 'handle'} RefKind
23
- * @typedef {{ kind?: string, schema?: string }} RefInfo
24
- * Shape of the entries in `meta.refs` — describes a single ref name.
25
- * `kind` is one of {@link RefKind}, kept as `string` since it originates
26
- * from a generated spec.
27
- */
28
- /**
29
- * Typed pointer to a single ref (table or handle slot) on a `Handle` or
30
- * `Local`. Operators (`put`/`get`/`open`/...) take a `Ref` as their first
31
- * argument and dispatch through the owning handle's store.
32
- */
33
- export class Ref {
34
- /**
35
- * @param {any} handle Owner — a `Handle` (or `Local`) the ref lives on.
36
- * @param {string} name Ref name as declared in the schema.
37
- * @param {string} kind Ref kind: `'collection'`, `'single'`, `'action'`, or `'handle'`.
38
- * @param {string | null} [schema] Fully-qualified schema id, if any.
39
- */
40
- constructor(handle: any, name: string, kind: string, schema?: string | null);
41
- handle: any;
42
- name: string;
43
- kind: string;
44
- schema: string;
45
- }
46
- export type RefKind = "collection" | "single" | "action" | "handle";
47
- /**
48
- * Shape of the entries in `meta.refs` — describes a single ref name.
49
- * `kind` is one of {@link RefKind}, kept as `string` since it originates
50
- * from a generated spec.
51
- */
52
- export type RefInfo = {
53
- kind?: string;
54
- schema?: string;
55
- };