@cero-base/cero 0.4.1 → 0.5.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 +1 -1
- package/src/builder.js +2 -1
- package/src/lib/builtins.js +6 -3
- package/src/rpc/client.js +79 -20
- package/src/rpc/server.js +27 -16
- package/types/rpc/client.d.ts +23 -0
- package/types/rpc/server.d.ts +5 -2
package/package.json
CHANGED
package/src/builder.js
CHANGED
|
@@ -257,6 +257,7 @@ import * as dispatch from './main/dispatch/index.js'
|
|
|
257
257
|
import * as schema from './main/schema/index.js'
|
|
258
258
|
import rpc from './main/rpc/index.js'
|
|
259
259
|
import localDatabase from './local/db/index.js'
|
|
260
|
+
import * as localSchema from './local/schema/index.js'
|
|
260
261
|
${handleImports(names, kinds)}
|
|
261
262
|
|
|
262
263
|
export const meta = ${JSON.stringify(meta, null, 2)}
|
|
@@ -266,7 +267,7 @@ export const spec = {
|
|
|
266
267
|
dispatch,
|
|
267
268
|
schema,
|
|
268
269
|
rpc,
|
|
269
|
-
local: { database: localDatabase },
|
|
270
|
+
local: { database: localDatabase, schema: localSchema, meta: meta.local },
|
|
270
271
|
meta,
|
|
271
272
|
handles: {
|
|
272
273
|
${handleEntries(names, kinds)}
|
package/src/lib/builtins.js
CHANGED
|
@@ -254,7 +254,8 @@ export function rpcTypes() {
|
|
|
254
254
|
fields: [
|
|
255
255
|
{ name: 'handle', type: 'string', required: true },
|
|
256
256
|
{ name: 'ref', type: 'string', required: true },
|
|
257
|
-
{ name: 'data', type: 'buffer', required: true }
|
|
257
|
+
{ name: 'data', type: 'buffer', required: true },
|
|
258
|
+
{ name: 'local', type: 'bool', required: false }
|
|
258
259
|
]
|
|
259
260
|
},
|
|
260
261
|
{
|
|
@@ -263,7 +264,8 @@ export function rpcTypes() {
|
|
|
263
264
|
fields: [
|
|
264
265
|
{ name: 'handle', type: 'string', required: true },
|
|
265
266
|
{ name: 'ref', type: 'string', required: true },
|
|
266
|
-
{ name: 'id', type: 'string', required: true }
|
|
267
|
+
{ name: 'id', type: 'string', required: true },
|
|
268
|
+
{ name: 'local', type: 'bool', required: false }
|
|
267
269
|
]
|
|
268
270
|
},
|
|
269
271
|
{
|
|
@@ -272,7 +274,8 @@ export function rpcTypes() {
|
|
|
272
274
|
fields: [
|
|
273
275
|
{ name: 'handle', type: 'string', required: true },
|
|
274
276
|
{ name: 'ref', type: 'string', required: true },
|
|
275
|
-
{ name: 'query', type: 'buffer', required: false }
|
|
277
|
+
{ name: 'query', type: 'buffer', required: false },
|
|
278
|
+
{ name: 'local', type: 'bool', required: false }
|
|
276
279
|
]
|
|
277
280
|
},
|
|
278
281
|
{
|
package/src/rpc/client.js
CHANGED
|
@@ -12,8 +12,9 @@ export { put, set, get, del, count, watch, call, open } from '../lib/operators.j
|
|
|
12
12
|
* @property {'single'|'collection'|'action'|'handle'} [kind]
|
|
13
13
|
* @property {string} [schema]
|
|
14
14
|
* @property {string} [type]
|
|
15
|
+
* @property {boolean} [builtin]
|
|
15
16
|
*
|
|
16
|
-
* @typedef {import('@cero-base/core/rpc').Spec & { meta: { ns?: string, refs: Record<string, RefInfo>, handles?: Record<string, Spec> }, handles: Record<string, Spec> }} Spec Built cero spec (schema + rpc + per-handle child specs).
|
|
17
|
+
* @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).
|
|
17
18
|
*
|
|
18
19
|
* @typedef {{ data: any }} SingleResult
|
|
19
20
|
* @typedef {{ data: any[], total: number, size: number }} ListResult
|
|
@@ -29,12 +30,26 @@ export { put, set, get, del, count, watch, call, open } from '../lib/operators.j
|
|
|
29
30
|
* @property {string|null} name
|
|
30
31
|
*/
|
|
31
32
|
|
|
32
|
-
// Mixin applied to
|
|
33
|
-
// surface as a local cero handle but routed over the wire.
|
|
33
|
+
// Mixin applied to Client, Handle and LocalRefs so they expose the same
|
|
34
|
+
// row-ops surface as a local cero handle but routed over the wire. `_local`
|
|
35
|
+
// selects the per-device store + JSON codec; main refs use the schema codec.
|
|
34
36
|
const operators = {
|
|
37
|
+
_local: false,
|
|
38
|
+
|
|
39
|
+
/** @param {string} name @returns {RefInfo|undefined} */
|
|
40
|
+
_refInfo(name) {
|
|
41
|
+
const refs = this._local ? this.spec.meta.local?.refs : this.spec.meta.refs
|
|
42
|
+
return refs?.[name]
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
/** @returns {any} */
|
|
46
|
+
_codec() {
|
|
47
|
+
return this._local ? this.spec.local.codec : this.spec.codec
|
|
48
|
+
},
|
|
49
|
+
|
|
35
50
|
/** @param {string} name @returns {string|undefined} */
|
|
36
51
|
schemaOf(name) {
|
|
37
|
-
return this.
|
|
52
|
+
return this._refInfo(name)?.schema
|
|
38
53
|
},
|
|
39
54
|
|
|
40
55
|
/**
|
|
@@ -45,13 +60,14 @@ const operators = {
|
|
|
45
60
|
* @returns {Promise<SingleResult>}
|
|
46
61
|
*/
|
|
47
62
|
async put(name, row) {
|
|
63
|
+
const codec = this._codec()
|
|
48
64
|
const schema = this.schemaOf(name)
|
|
49
|
-
const codec = this.spec.codec
|
|
50
65
|
const input = row?.id ? row : { id: '', ...row }
|
|
51
66
|
const res = await this.rpc.addRow({
|
|
52
67
|
handle: this.id,
|
|
53
68
|
ref: name,
|
|
54
|
-
data: codec.encodeRow(schema, input)
|
|
69
|
+
data: codec.encodeRow(schema, input),
|
|
70
|
+
local: this._local
|
|
55
71
|
})
|
|
56
72
|
return { data: codec.decodeRow(schema, res.data) }
|
|
57
73
|
},
|
|
@@ -64,12 +80,13 @@ const operators = {
|
|
|
64
80
|
* @returns {Promise<SingleResult>}
|
|
65
81
|
*/
|
|
66
82
|
async set(name, row) {
|
|
83
|
+
const codec = this._codec()
|
|
67
84
|
const schema = this.schemaOf(name)
|
|
68
|
-
const codec = this.spec.codec
|
|
69
85
|
const res = await this.rpc.set({
|
|
70
86
|
handle: this.id,
|
|
71
87
|
ref: name,
|
|
72
|
-
data: codec.encodeRow(schema, row)
|
|
88
|
+
data: codec.encodeRow(schema, row),
|
|
89
|
+
local: this._local
|
|
73
90
|
})
|
|
74
91
|
return { data: codec.decodeRow(schema, res.data) }
|
|
75
92
|
},
|
|
@@ -83,20 +100,27 @@ const operators = {
|
|
|
83
100
|
* @returns {Promise<SingleResult | ListResult | GetByIdResult>}
|
|
84
101
|
*/
|
|
85
102
|
async get(name, query) {
|
|
103
|
+
const codec = this._codec()
|
|
86
104
|
const schema = this.schemaOf(name)
|
|
87
|
-
const codec = this.spec.codec
|
|
88
105
|
if (typeof query === 'string') {
|
|
89
|
-
const res = await this.rpc.getOne({
|
|
106
|
+
const res = await this.rpc.getOne({
|
|
107
|
+
handle: this.id,
|
|
108
|
+
ref: name,
|
|
109
|
+
id: query,
|
|
110
|
+
local: this._local
|
|
111
|
+
})
|
|
90
112
|
return { data: res.data ? codec.decodeRow(schema, res.data) : null }
|
|
91
113
|
}
|
|
92
114
|
const res = await this.rpc.get({
|
|
93
115
|
handle: this.id,
|
|
94
116
|
ref: name,
|
|
95
|
-
query: codec.encodeQuery(query)
|
|
117
|
+
query: codec.encodeQuery(query),
|
|
118
|
+
local: this._local
|
|
96
119
|
})
|
|
97
|
-
const kind = this.spec.meta.refs[name]?.kind
|
|
98
120
|
const data =
|
|
99
|
-
kind === 'single'
|
|
121
|
+
this._refInfo(name)?.kind === 'single'
|
|
122
|
+
? codec.decodeRow(schema, res.data)
|
|
123
|
+
: codec.decodeRows(schema, res.data)
|
|
100
124
|
return { data, total: res.total, size: res.size }
|
|
101
125
|
},
|
|
102
126
|
|
|
@@ -108,7 +132,7 @@ const operators = {
|
|
|
108
132
|
* @returns {Promise<void>}
|
|
109
133
|
*/
|
|
110
134
|
async del(name, id) {
|
|
111
|
-
await this.rpc.del({ handle: this.id, ref: name, id })
|
|
135
|
+
await this.rpc.del({ handle: this.id, ref: name, id, local: this._local })
|
|
112
136
|
},
|
|
113
137
|
|
|
114
138
|
/**
|
|
@@ -119,11 +143,12 @@ const operators = {
|
|
|
119
143
|
* @returns {Promise<{ data: number }>}
|
|
120
144
|
*/
|
|
121
145
|
async count(name, query) {
|
|
122
|
-
const codec = this.
|
|
146
|
+
const codec = this._codec()
|
|
123
147
|
const res = await this.rpc.count({
|
|
124
148
|
handle: this.id,
|
|
125
149
|
ref: name,
|
|
126
|
-
query: codec.encodeQuery(query)
|
|
150
|
+
query: codec.encodeQuery(query),
|
|
151
|
+
local: this._local
|
|
127
152
|
})
|
|
128
153
|
return { data: res.count }
|
|
129
154
|
},
|
|
@@ -137,13 +162,14 @@ const operators = {
|
|
|
137
162
|
* @returns {import('streamx').Readable}
|
|
138
163
|
*/
|
|
139
164
|
watch(name, query) {
|
|
140
|
-
const refInfo = this.
|
|
165
|
+
const refInfo = this._refInfo(name)
|
|
166
|
+
const codec = this._codec()
|
|
141
167
|
const schema = refInfo?.schema
|
|
142
|
-
const codec = this.spec.codec
|
|
143
168
|
const wire = this.rpc.watch({
|
|
144
169
|
handle: this.id,
|
|
145
170
|
ref: name,
|
|
146
|
-
query: codec.encodeQuery(query)
|
|
171
|
+
query: codec.encodeQuery(query),
|
|
172
|
+
local: this._local
|
|
147
173
|
})
|
|
148
174
|
const out = new Readable({
|
|
149
175
|
predestroy() {
|
|
@@ -171,7 +197,7 @@ const operators = {
|
|
|
171
197
|
*/
|
|
172
198
|
async call(op, data) {
|
|
173
199
|
const schema = this.schemaOf(op)
|
|
174
|
-
const codec = this.
|
|
200
|
+
const codec = this._codec()
|
|
175
201
|
const encoded = data ? codec.encodeAction({ [op]: { schema } }, op, data) : null
|
|
176
202
|
await this.rpc.call({ handle: this.id, op, data: encoded })
|
|
177
203
|
},
|
|
@@ -215,6 +241,36 @@ export async function restore(me, phrase) {
|
|
|
215
241
|
return me
|
|
216
242
|
}
|
|
217
243
|
|
|
244
|
+
/**
|
|
245
|
+
* Per-device `local`-namespace surface on a Client. Exposes each app-defined
|
|
246
|
+
* local ref (e.g. `client.local.settings`) and routes ops over RPC with
|
|
247
|
+
* `local: true`, so they hit the server's per-device store and never
|
|
248
|
+
* replicate. Built-in local refs (identity master/keypair) are not exposed.
|
|
249
|
+
*/
|
|
250
|
+
class LocalRefs {
|
|
251
|
+
/** @param {Client} client */
|
|
252
|
+
constructor(client) {
|
|
253
|
+
Object.assign(this, operators)
|
|
254
|
+
this.parent = client
|
|
255
|
+
this.spec = client.spec
|
|
256
|
+
this.store = this
|
|
257
|
+
this._local = true
|
|
258
|
+
const refs = client.spec.meta.local?.refs || {}
|
|
259
|
+
const exposed = Object.fromEntries(Object.entries(refs).filter(([, info]) => !info.builtin))
|
|
260
|
+
attachRefs(this, exposed)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** Underlying RPC channel borrowed from the parent. */
|
|
264
|
+
get rpc() {
|
|
265
|
+
return this.parent.rpc
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** Root handle id (local ops are resolved against the root's local store). */
|
|
269
|
+
get id() {
|
|
270
|
+
return this.parent.id
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
218
274
|
/**
|
|
219
275
|
* IPC-side RPC client for cero. Wraps an `hrpc` channel and exposes the
|
|
220
276
|
* same handle/ref/row API as a local cero instance, transparently
|
|
@@ -227,10 +283,12 @@ export class Client extends RPCClient {
|
|
|
227
283
|
*/
|
|
228
284
|
constructor(ipc, spec) {
|
|
229
285
|
super(ipc, spec)
|
|
286
|
+
if (spec.local?.schema && !spec.local.codec) bindCodec(spec.local)
|
|
230
287
|
Object.assign(this, operators)
|
|
231
288
|
this.id = null
|
|
232
289
|
this.deviceId = null
|
|
233
290
|
this.store = this
|
|
291
|
+
this.local = null
|
|
234
292
|
}
|
|
235
293
|
|
|
236
294
|
async _open() {
|
|
@@ -240,6 +298,7 @@ export class Client extends RPCClient {
|
|
|
240
298
|
this.deviceId = deviceId || null
|
|
241
299
|
this.identity = { id, toPhrase: () => phrase || null }
|
|
242
300
|
attachRefs(this, /** @type {Spec} */ (this.spec).meta.refs)
|
|
301
|
+
if (/** @type {Spec} */ (this.spec).meta.local?.refs) this.local = new LocalRefs(this)
|
|
243
302
|
}
|
|
244
303
|
|
|
245
304
|
/**
|
package/src/rpc/server.js
CHANGED
|
@@ -40,6 +40,7 @@ export class Server extends RPCServer {
|
|
|
40
40
|
if (!storage) throw CeroError.REQUIRED('storage')
|
|
41
41
|
if (!spec) throw CeroError.REQUIRED('spec')
|
|
42
42
|
super(ipc, spec)
|
|
43
|
+
if (spec.local?.schema && !spec.local.codec) bindCodec(spec.local)
|
|
43
44
|
this.storage = storage
|
|
44
45
|
this.opts = opts
|
|
45
46
|
this.me = null
|
|
@@ -100,20 +101,20 @@ export class Server extends RPCServer {
|
|
|
100
101
|
|
|
101
102
|
/** Register the row-level RPC handlers (put/set/get/del/count/watch/call). */
|
|
102
103
|
_wireData() {
|
|
103
|
-
this.rpc.onAddRow(async ({ handle, ref, data }) => {
|
|
104
|
-
const { ref: r, codec } = this._refOf(handle, ref)
|
|
104
|
+
this.rpc.onAddRow(async ({ handle, ref, data, local }) => {
|
|
105
|
+
const { ref: r, codec } = this._refOf(handle, ref, local)
|
|
105
106
|
const { data: row } = await put(r, codec.decodeRow(r.schema, data))
|
|
106
107
|
return { data: codec.encodeRow(r.schema, row) }
|
|
107
108
|
})
|
|
108
109
|
|
|
109
|
-
this.rpc.onSet(async ({ handle, ref, data }) => {
|
|
110
|
-
const { ref: r, codec } = this._refOf(handle, ref)
|
|
110
|
+
this.rpc.onSet(async ({ handle, ref, data, local }) => {
|
|
111
|
+
const { ref: r, codec } = this._refOf(handle, ref, local)
|
|
111
112
|
const { data: row } = await set(r, codec.decodeRow(r.schema, data))
|
|
112
113
|
return { data: codec.encodeRow(r.schema, row) }
|
|
113
114
|
})
|
|
114
115
|
|
|
115
|
-
this.rpc.onGet(async ({ handle, ref, query }) => {
|
|
116
|
-
const { ref: r, codec } = this._refOf(handle, ref)
|
|
116
|
+
this.rpc.onGet(async ({ handle, ref, query, local }) => {
|
|
117
|
+
const { ref: r, codec } = this._refOf(handle, ref, local)
|
|
117
118
|
const result = /** @type {GetResult} */ (await get(r, codec.decodeQuery(query)))
|
|
118
119
|
const data =
|
|
119
120
|
r.kind === 'single'
|
|
@@ -122,28 +123,28 @@ export class Server extends RPCServer {
|
|
|
122
123
|
return { data, total: result.total ?? 0, size: result.size ?? 0 }
|
|
123
124
|
})
|
|
124
125
|
|
|
125
|
-
this.rpc.onGetOne(async ({ handle, ref, id }) => {
|
|
126
|
-
const { ref: r, codec } = this._refOf(handle, ref)
|
|
126
|
+
this.rpc.onGetOne(async ({ handle, ref, id, local }) => {
|
|
127
|
+
const { ref: r, codec } = this._refOf(handle, ref, local)
|
|
127
128
|
const { data } = await get(r, id)
|
|
128
129
|
return { data: data ? codec.encodeRow(r.schema, data) : null }
|
|
129
130
|
})
|
|
130
131
|
|
|
131
|
-
this.rpc.onDel(async ({ handle, ref, id }) => {
|
|
132
|
-
await del(this._refOf(handle, ref).ref, id)
|
|
132
|
+
this.rpc.onDel(async ({ handle, ref, id, local }) => {
|
|
133
|
+
await del(this._refOf(handle, ref, local).ref, id)
|
|
133
134
|
return {}
|
|
134
135
|
})
|
|
135
136
|
|
|
136
|
-
this.rpc.onCount(async ({ handle, ref, query }) => {
|
|
137
|
-
const { ref: r, codec } = this._refOf(handle, ref)
|
|
137
|
+
this.rpc.onCount(async ({ handle, ref, query, local }) => {
|
|
138
|
+
const { ref: r, codec } = this._refOf(handle, ref, local)
|
|
138
139
|
const { data } = await count(r, codec.decodeQuery(query))
|
|
139
140
|
return { count: data }
|
|
140
141
|
})
|
|
141
142
|
|
|
142
143
|
this.rpc.onWatch((stream) => {
|
|
143
|
-
const { handle, ref, query } = stream.data
|
|
144
|
+
const { handle, ref, query, local } = stream.data
|
|
144
145
|
let r, codec, live
|
|
145
146
|
try {
|
|
146
|
-
;({ ref: r, codec } = this._refOf(handle, ref))
|
|
147
|
+
;({ ref: r, codec } = this._refOf(handle, ref, local))
|
|
147
148
|
live = watch(r, codec.decodeQuery(query))
|
|
148
149
|
} catch (err) {
|
|
149
150
|
stream.destroy(err)
|
|
@@ -249,13 +250,23 @@ export class Server extends RPCServer {
|
|
|
249
250
|
}
|
|
250
251
|
|
|
251
252
|
/**
|
|
252
|
-
* Resolve a `{ handle, ref }` pair to its `Ref` and
|
|
253
|
+
* Resolve a `{ handle, ref }` pair to its `Ref` and codec. When `local` is
|
|
254
|
+
* set, the ref is resolved against the root's per-device `local` store and
|
|
255
|
+
* paired with the codec bound from the local schema.
|
|
253
256
|
*
|
|
254
257
|
* @param {string} id
|
|
255
258
|
* @param {string} name
|
|
259
|
+
* @param {boolean} [local]
|
|
256
260
|
* @returns {RefAndCodec}
|
|
257
261
|
*/
|
|
258
|
-
_refOf(id, name) {
|
|
262
|
+
_refOf(id, name, local) {
|
|
263
|
+
if (local) {
|
|
264
|
+
const info = this.spec.meta.local?.refs?.[name]
|
|
265
|
+
if (!info || info.builtin) throw CeroError.UNKNOWN('local ref', name)
|
|
266
|
+
const r = this.me.local?.[name]
|
|
267
|
+
if (!r) throw CeroError.UNKNOWN('local ref', name)
|
|
268
|
+
return { ref: r, codec: this.spec.local.codec }
|
|
269
|
+
}
|
|
259
270
|
const h = this._resolve(id)
|
|
260
271
|
const r = h[name]
|
|
261
272
|
if (!r) throw CeroError.UNKNOWN('ref', name)
|
package/types/rpc/client.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export class Client extends RPCClient {
|
|
|
29
29
|
id: any;
|
|
30
30
|
deviceId: any;
|
|
31
31
|
store: this;
|
|
32
|
+
local: LocalRefs;
|
|
32
33
|
identity: {
|
|
33
34
|
id: any;
|
|
34
35
|
toPhrase: () => any;
|
|
@@ -63,6 +64,7 @@ export type RefInfo = {
|
|
|
63
64
|
kind?: "single" | "collection" | "action" | "handle";
|
|
64
65
|
schema?: string;
|
|
65
66
|
type?: string;
|
|
67
|
+
builtin?: boolean;
|
|
66
68
|
};
|
|
67
69
|
/**
|
|
68
70
|
* Built cero spec (schema + rpc + per-handle child specs).
|
|
@@ -71,6 +73,9 @@ export type Spec = import("@cero-base/core/rpc").Spec & {
|
|
|
71
73
|
meta: {
|
|
72
74
|
ns?: string;
|
|
73
75
|
refs: Record<string, RefInfo>;
|
|
76
|
+
local?: {
|
|
77
|
+
refs: Record<string, RefInfo>;
|
|
78
|
+
};
|
|
74
79
|
handles?: Record<string, Spec>;
|
|
75
80
|
};
|
|
76
81
|
handles: Record<string, Spec>;
|
|
@@ -96,6 +101,24 @@ export type HandleStub = {
|
|
|
96
101
|
name: string | null;
|
|
97
102
|
};
|
|
98
103
|
import { RPCClient } from '@cero-base/core/rpc';
|
|
104
|
+
/**
|
|
105
|
+
* Per-device `local`-namespace surface on a Client. Exposes each app-defined
|
|
106
|
+
* local ref (e.g. `client.local.settings`) and routes ops over RPC with
|
|
107
|
+
* `local: true`, so they hit the server's per-device store and never
|
|
108
|
+
* replicate. Built-in local refs (identity master/keypair) are not exposed.
|
|
109
|
+
*/
|
|
110
|
+
declare class LocalRefs {
|
|
111
|
+
/** @param {Client} client */
|
|
112
|
+
constructor(client: Client);
|
|
113
|
+
parent: Client;
|
|
114
|
+
spec: import("@cero-base/core/rpc").Spec;
|
|
115
|
+
store: this;
|
|
116
|
+
_local: boolean;
|
|
117
|
+
/** Underlying RPC channel borrowed from the parent. */
|
|
118
|
+
get rpc(): any;
|
|
119
|
+
/** Root handle id (local ops are resolved against the root's local store). */
|
|
120
|
+
get id(): any;
|
|
121
|
+
}
|
|
99
122
|
/**
|
|
100
123
|
* Client-side proxy for a remote handle. Exposes the same row-ops surface
|
|
101
124
|
* as `Client` but scoped to a single child handle id, and routes every
|
package/types/rpc/server.d.ts
CHANGED
|
@@ -87,13 +87,16 @@ export class Server extends RPCServer {
|
|
|
87
87
|
*/
|
|
88
88
|
_resolve(id: string): any;
|
|
89
89
|
/**
|
|
90
|
-
* Resolve a `{ handle, ref }` pair to its `Ref` and
|
|
90
|
+
* Resolve a `{ handle, ref }` pair to its `Ref` and codec. When `local` is
|
|
91
|
+
* set, the ref is resolved against the root's per-device `local` store and
|
|
92
|
+
* paired with the codec bound from the local schema.
|
|
91
93
|
*
|
|
92
94
|
* @param {string} id
|
|
93
95
|
* @param {string} name
|
|
96
|
+
* @param {boolean} [local]
|
|
94
97
|
* @returns {RefAndCodec}
|
|
95
98
|
*/
|
|
96
|
-
_refOf(id: string, name: string): RefAndCodec;
|
|
99
|
+
_refOf(id: string, name: string, local?: boolean): RefAndCodec;
|
|
97
100
|
/**
|
|
98
101
|
* Snapshot the current identity for return to the client.
|
|
99
102
|
*
|