@cero-base/core 0.2.0 → 0.4.1
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/LICENSE +201 -0
- package/README.md +180 -136
- package/package.json +123 -28
- package/src/blobs/index.js +297 -0
- package/src/database/CLAUDE.md +3 -0
- package/src/database/bootstrap.js +76 -0
- package/src/database/dispatch.js +156 -0
- package/src/database/index.js +572 -0
- package/src/identity/CLAUDE.md +3 -0
- package/src/identity/index.js +232 -0
- package/src/index.js +20 -1
- package/src/lib/CLAUDE.md +3 -0
- package/src/lib/constants.js +24 -4
- package/src/lib/errors.js +150 -0
- package/src/lib/schema.js +58 -440
- package/src/lib/spec/index.js +353 -0
- package/src/lib/spec/schema.json +284 -0
- package/src/lib/utils.js +54 -49
- package/src/network/discovery.js +80 -0
- package/src/network/index.js +231 -0
- package/src/pairing/index.js +482 -0
- package/src/pairing/invite.js +199 -0
- package/src/rpc/client.js +45 -0
- package/src/rpc/index.js +141 -0
- package/src/rpc/server.js +45 -0
- package/src/storage/index.js +261 -0
- package/types/blobs/index.d.ts +169 -0
- package/types/database/bootstrap.d.ts +17 -0
- package/types/database/dispatch.d.ts +8 -0
- package/types/database/index.d.ts +329 -0
- package/types/identity/index.d.ts +160 -0
- package/types/index.d.ts +11 -0
- package/types/lib/constants.d.ts +13 -0
- package/types/lib/errors.d.ts +110 -0
- package/types/lib/schema.d.ts +53 -0
- package/types/lib/spec/index.d.ts +95 -0
- package/types/lib/utils.d.ts +39 -0
- package/types/network/discovery.d.ts +44 -0
- package/types/network/index.d.ts +115 -0
- package/types/pairing/index.d.ts +194 -0
- package/types/pairing/invite.d.ts +157 -0
- package/types/rpc/client.d.ts +18 -0
- package/types/rpc/index.d.ts +67 -0
- package/types/rpc/server.d.ts +18 -0
- package/types/storage/index.d.ts +163 -0
- package/src/lib/base.js +0 -84
- package/src/lib/batch.js +0 -98
- package/src/lib/builder.js +0 -24
- package/src/lib/collection.js +0 -252
- package/src/lib/crypto.js +0 -6
- package/src/lib/index.js +0 -6
- package/src/lib/room.js +0 -145
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} Spec
|
|
3
|
+
* @property {{ encode: (type: string, value: any) => Uint8Array, decode: (type: string, buf: Uint8Array) => any, getEncoding?: (name: string) => any }} schema hyperschema-shaped module.
|
|
4
|
+
* @property {{ ns?: string }} [meta] Optional metadata; `ns` controls envelope type fqns.
|
|
5
|
+
* @property {any} [rpc] hrpc constructor used by RPCServer/RPCClient.
|
|
6
|
+
* @property {Codec} [codec] Filled in by `bindCodec`.
|
|
7
|
+
*
|
|
8
|
+
* @typedef {object} Codec
|
|
9
|
+
* @property {(type: string, row: any) => Uint8Array} encodeRow
|
|
10
|
+
* @property {(type: string, buf: Uint8Array) => any} decodeRow
|
|
11
|
+
* @property {(type: string, rows: any[]) => Uint8Array} encodeRows
|
|
12
|
+
* @property {(type: string, buf: Uint8Array) => any[]} decodeRows
|
|
13
|
+
* @property {(q: any) => Uint8Array} encodeQuery
|
|
14
|
+
* @property {(buf: Uint8Array) => any} decodeQuery
|
|
15
|
+
* @property {(row: any) => Uint8Array} encodeCreate
|
|
16
|
+
* @property {(buf: Uint8Array) => any} decodeCreate
|
|
17
|
+
* @property {(handle: any, op: string, data: any) => Uint8Array} encodeAction
|
|
18
|
+
* @property {(handle: any, op: string, buf: Uint8Array) => any} decodeAction
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Attach a `codec` namespace to a hyperschema-shaped `spec`. Looks up
|
|
22
|
+
* envelope types using the spec's namespace (`@<ns>/rows` etc.) and falls
|
|
23
|
+
* back to the bundled `@cero/*` envelopes when the spec has not declared
|
|
24
|
+
* its own. Returns the spec for chaining.
|
|
25
|
+
*
|
|
26
|
+
* @param {Spec} spec
|
|
27
|
+
* @returns {Spec}
|
|
28
|
+
*/
|
|
29
|
+
export function bindCodec(spec: Spec): Spec;
|
|
30
|
+
export { RPCServer } from "./server.js";
|
|
31
|
+
export { RPCClient } from "./client.js";
|
|
32
|
+
export type Spec = {
|
|
33
|
+
/**
|
|
34
|
+
* hyperschema-shaped module.
|
|
35
|
+
*/
|
|
36
|
+
schema: {
|
|
37
|
+
encode: (type: string, value: any) => Uint8Array;
|
|
38
|
+
decode: (type: string, buf: Uint8Array) => any;
|
|
39
|
+
getEncoding?: (name: string) => any;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Optional metadata; `ns` controls envelope type fqns.
|
|
43
|
+
*/
|
|
44
|
+
meta?: {
|
|
45
|
+
ns?: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* hrpc constructor used by RPCServer/RPCClient.
|
|
49
|
+
*/
|
|
50
|
+
rpc?: any;
|
|
51
|
+
/**
|
|
52
|
+
* Filled in by `bindCodec`.
|
|
53
|
+
*/
|
|
54
|
+
codec?: Codec;
|
|
55
|
+
};
|
|
56
|
+
export type Codec = {
|
|
57
|
+
encodeRow: (type: string, row: any) => Uint8Array;
|
|
58
|
+
decodeRow: (type: string, buf: Uint8Array) => any;
|
|
59
|
+
encodeRows: (type: string, rows: any[]) => Uint8Array;
|
|
60
|
+
decodeRows: (type: string, buf: Uint8Array) => any[];
|
|
61
|
+
encodeQuery: (q: any) => Uint8Array;
|
|
62
|
+
decodeQuery: (buf: Uint8Array) => any;
|
|
63
|
+
encodeCreate: (row: any) => Uint8Array;
|
|
64
|
+
decodeCreate: (buf: Uint8Array) => any;
|
|
65
|
+
encodeAction: (handle: any, op: string, data: any) => Uint8Array;
|
|
66
|
+
decodeAction: (handle: any, op: string, buf: Uint8Array) => any;
|
|
67
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side RPC adapter. Wraps an IPC duplex in a length-framed stream
|
|
3
|
+
* and instantiates the spec's hrpc binding once `bindCodec` has populated
|
|
4
|
+
* envelope encoders. Reads are paused until `_open` runs so the
|
|
5
|
+
* application has a chance to register handlers before frames flow.
|
|
6
|
+
*/
|
|
7
|
+
export class RPCServer extends ReadyResource {
|
|
8
|
+
/**
|
|
9
|
+
* @param {any} ipc Duplex IPC stream (e.g. a socket or pipe).
|
|
10
|
+
* @param {import('./index.js').Spec} spec Spec object exposing `rpc` and `schema`.
|
|
11
|
+
*/
|
|
12
|
+
constructor(ipc: any, spec: import("./index.js").Spec);
|
|
13
|
+
ipc: any;
|
|
14
|
+
spec: import("./index.js").Spec;
|
|
15
|
+
framed: any;
|
|
16
|
+
rpc: any;
|
|
17
|
+
}
|
|
18
|
+
import ReadyResource from 'ready-resource';
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} StorageOpts
|
|
3
|
+
* @property {{ database: any, meta?: { ns?: string, refs?: Record<string, { kind?: string }> } }} spec
|
|
4
|
+
* @property {'rocks' | 'bee'} backend
|
|
5
|
+
* @property {any} [root] Pre-existing HypercoreStorage to reuse.
|
|
6
|
+
* @property {any} [store] Pre-existing Corestore to reuse.
|
|
7
|
+
*
|
|
8
|
+
* @typedef {{ name: string, kind: string }} Ref
|
|
9
|
+
* @typedef {{ id?: string, createdAt: number, updatedAt: number, [k: string]: any }} StoredRow
|
|
10
|
+
* @typedef {{ data: any }} SingleResult
|
|
11
|
+
* @typedef {{ data: any[], total: number, size: number }} ListResult
|
|
12
|
+
* @typedef {{ data: any | null }} GetByIdResult
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Local, single-writer storage. Backed by either RocksDB (`rocks`) or a
|
|
16
|
+
* Hyperbee on top of corestore (`bee`). Exposes the same `put/get/...`
|
|
17
|
+
* surface as `Database` but without networking or multi-writer apply.
|
|
18
|
+
*/
|
|
19
|
+
export class Storage extends ReadyResource {
|
|
20
|
+
/**
|
|
21
|
+
* Construct a RocksDB-backed Storage.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} dir
|
|
24
|
+
* @param {Omit<StorageOpts, 'backend'>} opts
|
|
25
|
+
*/
|
|
26
|
+
static rocks(dir: string, opts: Omit<StorageOpts, "backend">): Storage;
|
|
27
|
+
/**
|
|
28
|
+
* Construct a Hyperbee-backed Storage.
|
|
29
|
+
*
|
|
30
|
+
* @param {string} dir
|
|
31
|
+
* @param {Omit<StorageOpts, 'backend'>} opts
|
|
32
|
+
*/
|
|
33
|
+
static bee(dir: string, opts: Omit<StorageOpts, "backend">): Storage;
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} dir
|
|
36
|
+
* @param {StorageOpts} [opts]
|
|
37
|
+
*/
|
|
38
|
+
constructor(dir: string, { spec, backend, root, store }?: StorageOpts);
|
|
39
|
+
dir: string;
|
|
40
|
+
spec: {
|
|
41
|
+
database: any;
|
|
42
|
+
meta?: {
|
|
43
|
+
ns?: string;
|
|
44
|
+
refs?: Record<string, {
|
|
45
|
+
kind?: string;
|
|
46
|
+
}>;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
backend: "rocks" | "bee";
|
|
50
|
+
ns: string;
|
|
51
|
+
refs: Record<string, {
|
|
52
|
+
kind?: string;
|
|
53
|
+
}>;
|
|
54
|
+
_cf: string;
|
|
55
|
+
_ownsRoot: boolean;
|
|
56
|
+
_ownsStore: boolean;
|
|
57
|
+
root: any;
|
|
58
|
+
store: any;
|
|
59
|
+
db: any;
|
|
60
|
+
/**
|
|
61
|
+
* Insert (or overwrite by id) a row, stamping `id`/`createdAt`/`updatedAt`.
|
|
62
|
+
*
|
|
63
|
+
* @param {string} name
|
|
64
|
+
* @param {Record<string, any>} row
|
|
65
|
+
* @returns {Promise<SingleResult>}
|
|
66
|
+
*/
|
|
67
|
+
put(name: string, row: Record<string, any>): Promise<SingleResult>;
|
|
68
|
+
/**
|
|
69
|
+
* Upsert by merging with the existing row, preserving `createdAt`.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} name
|
|
72
|
+
* @param {Record<string, any>} row
|
|
73
|
+
* @returns {Promise<SingleResult>}
|
|
74
|
+
*/
|
|
75
|
+
set(name: string, row: Record<string, any>): Promise<SingleResult>;
|
|
76
|
+
/**
|
|
77
|
+
* Delete by id (collection) or wipe the whole single-row table.
|
|
78
|
+
*
|
|
79
|
+
* @param {string} name
|
|
80
|
+
* @param {string} [id]
|
|
81
|
+
* @returns {Promise<void>}
|
|
82
|
+
*/
|
|
83
|
+
del(name: string, id?: string): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Read a row. With no `query`: list all (collection) or fetch the one
|
|
86
|
+
* record (single). With a string id: fetch that specific row.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} name
|
|
89
|
+
* @param {string | Record<string, any>} [query]
|
|
90
|
+
* @returns {Promise<SingleResult | ListResult | GetByIdResult>}
|
|
91
|
+
*/
|
|
92
|
+
get(name: string, query?: string | Record<string, any>): Promise<SingleResult | ListResult | GetByIdResult>;
|
|
93
|
+
/**
|
|
94
|
+
* Number of rows that match `query` (or total if omitted).
|
|
95
|
+
*
|
|
96
|
+
* @param {string} name
|
|
97
|
+
* @param {Record<string, any>} [query]
|
|
98
|
+
* @returns {Promise<{ data: number }>}
|
|
99
|
+
*/
|
|
100
|
+
count(name: string, query?: Record<string, any>): Promise<{
|
|
101
|
+
data: number;
|
|
102
|
+
}>;
|
|
103
|
+
/**
|
|
104
|
+
* Live snapshot stream — re-emits the latest `get()` result on every
|
|
105
|
+
* underlying mutation. Destroy the stream to stop watching.
|
|
106
|
+
*
|
|
107
|
+
* @param {string} name
|
|
108
|
+
* @param {Record<string, any>} [query]
|
|
109
|
+
* @returns {import('streamx').Readable}
|
|
110
|
+
*/
|
|
111
|
+
watch(name: string, query?: Record<string, any>): any;
|
|
112
|
+
_guard(): void;
|
|
113
|
+
/** @param {string} name @returns {Ref} */
|
|
114
|
+
_ref(name: string): Ref;
|
|
115
|
+
/** @param {Ref} ref @returns {string} */
|
|
116
|
+
_col(ref: Ref): string;
|
|
117
|
+
/** @param {Ref} ref @param {string} [id] @returns {Promise<any | null>} */
|
|
118
|
+
_read(ref: Ref, id?: string): Promise<any | null>;
|
|
119
|
+
/** @param {Ref} ref @param {Record<string, any>} row @returns {Promise<void>} */
|
|
120
|
+
_write(ref: Ref, row: Record<string, any>): Promise<void>;
|
|
121
|
+
}
|
|
122
|
+
export type StorageOpts = {
|
|
123
|
+
spec: {
|
|
124
|
+
database: any;
|
|
125
|
+
meta?: {
|
|
126
|
+
ns?: string;
|
|
127
|
+
refs?: Record<string, {
|
|
128
|
+
kind?: string;
|
|
129
|
+
}>;
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
backend: "rocks" | "bee";
|
|
133
|
+
/**
|
|
134
|
+
* Pre-existing HypercoreStorage to reuse.
|
|
135
|
+
*/
|
|
136
|
+
root?: any;
|
|
137
|
+
/**
|
|
138
|
+
* Pre-existing Corestore to reuse.
|
|
139
|
+
*/
|
|
140
|
+
store?: any;
|
|
141
|
+
};
|
|
142
|
+
export type Ref = {
|
|
143
|
+
name: string;
|
|
144
|
+
kind: string;
|
|
145
|
+
};
|
|
146
|
+
export type StoredRow = {
|
|
147
|
+
id?: string;
|
|
148
|
+
createdAt: number;
|
|
149
|
+
updatedAt: number;
|
|
150
|
+
[k: string]: any;
|
|
151
|
+
};
|
|
152
|
+
export type SingleResult = {
|
|
153
|
+
data: any;
|
|
154
|
+
};
|
|
155
|
+
export type ListResult = {
|
|
156
|
+
data: any[];
|
|
157
|
+
total: number;
|
|
158
|
+
size: number;
|
|
159
|
+
};
|
|
160
|
+
export type GetByIdResult = {
|
|
161
|
+
data: any | null;
|
|
162
|
+
};
|
|
163
|
+
import ReadyResource from 'ready-resource';
|
package/src/lib/base.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { Cero } from '@lekinox/cero'
|
|
2
|
-
import { SCOPE_PRIVATE, SCOPE_SHARED } from '../lib/constants.js'
|
|
3
|
-
import { Collection } from '../lib/collection.js'
|
|
4
|
-
import { Batch } from '../lib/batch.js'
|
|
5
|
-
|
|
6
|
-
const SEED_WORD_COUNT = 12
|
|
7
|
-
|
|
8
|
-
export class CeroBase extends Cero {
|
|
9
|
-
constructor(dir, schema, spec, opts = {}) {
|
|
10
|
-
super(
|
|
11
|
-
dir,
|
|
12
|
-
{
|
|
13
|
-
...spec,
|
|
14
|
-
identity: {
|
|
15
|
-
...spec.identity,
|
|
16
|
-
routes: schema.routes(SCOPE_PRIVATE),
|
|
17
|
-
counters: schema.counterNames(SCOPE_PRIVATE)
|
|
18
|
-
},
|
|
19
|
-
room: {
|
|
20
|
-
...spec.room,
|
|
21
|
-
ns: schema.namespace || undefined,
|
|
22
|
-
routes: schema.routes(SCOPE_SHARED),
|
|
23
|
-
counters: schema.counterNames(SCOPE_SHARED)
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
opts
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
this.schema = schema
|
|
30
|
-
this._baseUpdateHandler = null
|
|
31
|
-
|
|
32
|
-
// Expose cero's local-scope tables (rooms cache, files, settings, …) and
|
|
33
|
-
// user-declared `scope: 'local'` collections via the unified Collection API.
|
|
34
|
-
// db.local already has cero's find/insert/delete; we just add .collection.
|
|
35
|
-
if (this.local) {
|
|
36
|
-
this.local.collection = (name) => new Collection(this, name, { local: true })
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
this.once('ready', () => {
|
|
40
|
-
this._bindIdentityBase()
|
|
41
|
-
})
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
_bindIdentityBase() {
|
|
45
|
-
if (this._baseUpdateHandler && this._prevBase) {
|
|
46
|
-
this._prevBase.removeListener('update', this._baseUpdateHandler)
|
|
47
|
-
}
|
|
48
|
-
this._baseUpdateHandler = () => this.emit('update')
|
|
49
|
-
this._prevBase = this.identity?.base
|
|
50
|
-
if (this._prevBase) this._prevBase.on('update', this._baseUpdateHandler)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async _swapIdentity(handler, opts) {
|
|
54
|
-
const result = await super._swapIdentity(handler, opts)
|
|
55
|
-
this._bindIdentityBase()
|
|
56
|
-
return result
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
seed() {
|
|
60
|
-
return this.identity?.seed?.get() || null
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async join(input, opts = {}) {
|
|
64
|
-
const isSeed = typeof input === 'string' && input.trim().split(/\s+/).length >= SEED_WORD_COUNT
|
|
65
|
-
if (isSeed) return this.recover(input, opts)
|
|
66
|
-
return this.pair(input, opts)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** Create a device-pairing invite string for this identity. */
|
|
70
|
-
async invite(opts = {}) {
|
|
71
|
-
if (!this.opened) await this.ready()
|
|
72
|
-
const { invite } = await this.invites.create(opts)
|
|
73
|
-
return invite
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
collection(name) {
|
|
77
|
-
this.schema.require(name, 'db')
|
|
78
|
-
return new Collection(this, name)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
batch() {
|
|
82
|
-
return new Batch(this)
|
|
83
|
-
}
|
|
84
|
-
}
|
package/src/lib/batch.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { randomId } from './crypto.js'
|
|
2
|
-
import { isLocal, isPrivate, isShared } from './utils.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Batch — buffer multiple put/del operations and flush as single dispatch
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* const batch = db.batch()
|
|
9
|
-
* batch.put('settings', { key: 'a', value: '1' })
|
|
10
|
-
* await batch.flush()
|
|
11
|
-
*/
|
|
12
|
-
export class Batch {
|
|
13
|
-
constructor(owner) {
|
|
14
|
-
this.owner = owner
|
|
15
|
-
this.schema = owner.schema
|
|
16
|
-
this.operations = []
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
put(name, doc) {
|
|
20
|
-
const scope = this._validate(name)
|
|
21
|
-
|
|
22
|
-
const data = doc.id ? doc : { ...doc, id: randomId() }
|
|
23
|
-
if (this.schema.hasTimestamps(name)) {
|
|
24
|
-
data.createdAt = data.createdAt ?? Date.now()
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// If cero doesn't have add-${type}, fall back to set-${type} which is
|
|
28
|
-
// itself an upsert.
|
|
29
|
-
const action = this.schema.hasAdd(name) ? 'add' : 'set'
|
|
30
|
-
this.operations.push({ action, name, data, scope })
|
|
31
|
-
return data
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async del(name, query) {
|
|
35
|
-
const scope = this._validate(name)
|
|
36
|
-
|
|
37
|
-
const col = this.owner.collection(name)
|
|
38
|
-
const [existing] = await col.get(query)
|
|
39
|
-
if (!existing) return false
|
|
40
|
-
|
|
41
|
-
const keys = this.schema.keysOf(name)
|
|
42
|
-
const keyData = keys.reduce((acc, k) => ((acc[k] = existing[k]), acc), {})
|
|
43
|
-
|
|
44
|
-
this.operations.push({ action: 'del', name, data: keyData, scope })
|
|
45
|
-
return true
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async flush() {
|
|
49
|
-
if (this.operations.length === 0) return
|
|
50
|
-
|
|
51
|
-
const localOps = this.operations.filter((op) => isLocal(op.scope))
|
|
52
|
-
const privateOps = this.operations.filter((op) => isPrivate(op.scope))
|
|
53
|
-
const sharedOps = this.operations.filter((op) => isShared(op.scope))
|
|
54
|
-
|
|
55
|
-
for (const op of localOps) {
|
|
56
|
-
const path = this.schema.getPath(op.name)
|
|
57
|
-
if (op.action === 'del') {
|
|
58
|
-
await this.owner.local.delete(path, op.data)
|
|
59
|
-
} else {
|
|
60
|
-
await this.owner.local.insert(path, op.data)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (privateOps.length > 0) {
|
|
65
|
-
const identity = this.owner.identity
|
|
66
|
-
const ns = identity.ns
|
|
67
|
-
await identity.dispatch(`@${ns}/batch`, {
|
|
68
|
-
operations: privateOps.map((op) => {
|
|
69
|
-
const route = `@${ns}/${op.action}-${this.schema.types.get(op.name)}`
|
|
70
|
-
return identity.spec.dispatch.encode(route, op.data)
|
|
71
|
-
})
|
|
72
|
-
})
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (sharedOps.length > 0) {
|
|
76
|
-
const room = this.owner.room
|
|
77
|
-
const ns = room.ns
|
|
78
|
-
await room.dispatch(`@${ns}/batch`, {
|
|
79
|
-
operations: sharedOps.map((op) => {
|
|
80
|
-
const route = `@${ns}/${op.action}-${this.schema.types.get(op.name)}`
|
|
81
|
-
return room.spec.dispatch.encode(route, op.data)
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
this.operations = []
|
|
87
|
-
|
|
88
|
-
if (localOps.length > 0) {
|
|
89
|
-
this.owner.emit('update')
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
_validate(name) {
|
|
94
|
-
const scope = this.schema.getScope(name)
|
|
95
|
-
if (!scope) throw new Error(`Unknown collection: '${name}'`)
|
|
96
|
-
return scope
|
|
97
|
-
}
|
|
98
|
-
}
|
package/src/lib/builder.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { build as ceroBuild } from '@lekinox/cero'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Build all specs in one output directory.
|
|
5
|
-
*
|
|
6
|
-
* @param {string} dir - Output directory
|
|
7
|
-
* @param {object} [schema] - Schema from t.schema()
|
|
8
|
-
* @param {object} [opts] - Options
|
|
9
|
-
* @param {function} [opts.rpc] - RPC builder function ({ register, ns }) => void
|
|
10
|
-
*/
|
|
11
|
-
export async function build(dir, schema, opts = {}) {
|
|
12
|
-
const ns = schema?.namespace || null
|
|
13
|
-
const builders = {
|
|
14
|
-
local: ({ register, ns }) => schema?.build('local', register, ns),
|
|
15
|
-
identity: ({ register, ns }) => schema?.build('private', register, ns),
|
|
16
|
-
room: ({ register, ns }) => schema?.build('shared', register, ns),
|
|
17
|
-
...(opts.rpc ? { rpc: opts.rpc } : {})
|
|
18
|
-
}
|
|
19
|
-
if (ns) {
|
|
20
|
-
await ceroBuild(dir, ns, builders)
|
|
21
|
-
} else {
|
|
22
|
-
await ceroBuild(dir, builders)
|
|
23
|
-
}
|
|
24
|
-
}
|