@peers-app/peers-sdk 0.23.9 → 0.23.10
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.
|
@@ -135,12 +135,27 @@ function getAllTables() {
|
|
|
135
135
|
return tableMap;
|
|
136
136
|
}
|
|
137
137
|
if (!rpc_types_1.isClient) {
|
|
138
|
+
/**
|
|
139
|
+
* Resolve a table for a renderer RPC call.
|
|
140
|
+
*
|
|
141
|
+
* Prefers a full (code/package-registered) instance. When no package on this
|
|
142
|
+
* device has registered `tableName`, falls back to a synced
|
|
143
|
+
* `TableDefinitions` record so a renderer whose UI bundle is ahead of the
|
|
144
|
+
* package the host loaded can still reach the table's data.
|
|
145
|
+
*/
|
|
138
146
|
async function getTable(dataContextId, tableName) {
|
|
139
147
|
const userContext = await getUserContext();
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
148
|
+
const tableContainer = userContext.getDataContext(dataContextId || userContext.userId).tableContainer;
|
|
149
|
+
try {
|
|
150
|
+
return tableContainer.getTable(tableName);
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
const fallback = await tableContainer.getFallbackTable(tableName);
|
|
154
|
+
if (fallback) {
|
|
155
|
+
return fallback;
|
|
156
|
+
}
|
|
157
|
+
throw err;
|
|
158
|
+
}
|
|
144
159
|
}
|
|
145
160
|
// TODO: add check that client has permission to make this call
|
|
146
161
|
rpc_types_1.rpcServerCalls.tableMethodCall = async (dataContextId, tableName, methodName, ...args) => {
|
|
@@ -123,12 +123,20 @@ export declare function groupVar<T = string>(name: string, opts?: Omit<IPersiste
|
|
|
123
123
|
/**
|
|
124
124
|
* A persistent variable that is stored only on this device, in the user's personal db.
|
|
125
125
|
* It can have a different value for each group on the device but is not synced to other devices.
|
|
126
|
+
*
|
|
127
|
+
* The record always lives in the personal db. `opts.dataContext` (or, when omitted, the
|
|
128
|
+
* current default group) only selects which group's value is addressed by suffixing the
|
|
129
|
+
* stored name with that data context id, so server-side callers that pin a group and
|
|
130
|
+
* renderer callers that follow the default group share one row.
|
|
126
131
|
*/
|
|
127
132
|
export declare function groupDeviceVar<T = string>(name: string, opts: Omit<IPersistentVarOptionsWithDefault<T>, "scope">): PersistentVar<T>;
|
|
128
133
|
export declare function groupDeviceVar<T = string>(name: string, opts?: Omit<IPersistentVarOptionsWithoutDefault<T>, "scope">): PersistentVar<T | undefined>;
|
|
129
134
|
/**
|
|
130
135
|
* A persistent variable that is stored in the user's personal db and synced across all their devices in the group.
|
|
131
136
|
* It can have a different value for each user in the group and a different value for each group the user is in.
|
|
137
|
+
*
|
|
138
|
+
* As with {@link groupDeviceVar}, the record always lives in the personal db; `opts.dataContext`
|
|
139
|
+
* only selects the group whose value is addressed.
|
|
132
140
|
*/
|
|
133
141
|
export declare function groupUserVar<T = string>(name: string, opts: Omit<IPersistentVarOptionsWithDefault<T>, "scope">): PersistentVar<T>;
|
|
134
142
|
export declare function groupUserVar<T = string>(name: string, opts?: Omit<IPersistentVarOptionsWithoutDefault<T>, "scope">): PersistentVar<T | undefined>;
|
|
@@ -277,26 +277,71 @@ function persistentVarFactory(name, opts) {
|
|
|
277
277
|
void (async () => {
|
|
278
278
|
try {
|
|
279
279
|
const userContext = opts?.userContext || (await (0, user_context_singleton_1.getUserContext)());
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
280
|
+
/**
|
|
281
|
+
* The data context whose `PersistentVars` table stores this variable.
|
|
282
|
+
*
|
|
283
|
+
* Only `group` scope lives in a group DB. Every other scope lives in the
|
|
284
|
+
* user's personal DB; for `groupDevice` / `groupUser` the route context
|
|
285
|
+
* (`opts.dataContext` or the current default group) only disambiguates
|
|
286
|
+
* the stored name (see {@link getVarNameInDb}). Storing the record in
|
|
287
|
+
* the personal DB regardless of whether a caller pinned a `dataContext`
|
|
288
|
+
* keeps server-side callers (which pin) and renderer callers (which
|
|
289
|
+
* don't) reading and writing the same row.
|
|
290
|
+
*/
|
|
291
|
+
function getStorageDataContext() {
|
|
284
292
|
if (scope === "group") {
|
|
285
|
-
return userContext.defaultDataContext();
|
|
293
|
+
return opts?.dataContext ?? userContext.defaultDataContext();
|
|
294
|
+
}
|
|
295
|
+
return userContext.userDataContext;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Before storage was unified in the personal DB, a `groupDevice` /
|
|
299
|
+
* `groupUser` var created with an explicit group `dataContext` was
|
|
300
|
+
* written to that group's DB. Return that legacy location so an
|
|
301
|
+
* existing value can be migrated forward, or `undefined` when there is
|
|
302
|
+
* no distinct legacy location for this variable.
|
|
303
|
+
*/
|
|
304
|
+
function getLegacyStorageDataContext() {
|
|
305
|
+
if (scope !== "groupDevice" && scope !== "groupUser") {
|
|
306
|
+
return undefined;
|
|
286
307
|
}
|
|
287
|
-
|
|
288
|
-
|
|
308
|
+
const pinned = opts?.dataContext;
|
|
309
|
+
if (!pinned || pinned.dataContextId === userContext.userDataContext.dataContextId) {
|
|
310
|
+
return undefined;
|
|
289
311
|
}
|
|
312
|
+
return pinned;
|
|
290
313
|
}
|
|
291
314
|
function getVarNameInDb() {
|
|
292
315
|
const dc = opts?.dataContext || userContext.defaultDataContext();
|
|
293
316
|
return (0, persistent_var_identity_1.persistentVarStorageName)(name, scope, dc?.dataContextId);
|
|
294
317
|
}
|
|
318
|
+
/**
|
|
319
|
+
* Copy a record left in a group DB by the pre-unification storage rule
|
|
320
|
+
* into the personal DB. Secrets are skipped because their ciphertext is
|
|
321
|
+
* bound to the group key and cannot be moved verbatim. The legacy row is
|
|
322
|
+
* left in place: older builds on other devices may still read it, and
|
|
323
|
+
* the personal copy is authoritative from here on.
|
|
324
|
+
*/
|
|
325
|
+
async function migrateLegacyRec(table, name) {
|
|
326
|
+
const legacyContext = getLegacyStorageDataContext();
|
|
327
|
+
if (!legacyContext) {
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
330
|
+
const legacyRec = await PersistentVars(legacyContext).findOne({ name });
|
|
331
|
+
if (!legacyRec || legacyRec.scope !== scope || legacyRec.isSecret) {
|
|
332
|
+
return undefined;
|
|
333
|
+
}
|
|
334
|
+
const { persistentVarId: _legacyId, ...rest } = legacyRec;
|
|
335
|
+
return table.save({ ...rest, persistentVarId: "" }, { weakInsert: true });
|
|
336
|
+
}
|
|
295
337
|
async function loadRecFromDb() {
|
|
296
|
-
const dc =
|
|
338
|
+
const dc = getStorageDataContext();
|
|
297
339
|
const table = PersistentVars(dc);
|
|
298
340
|
const name = getVarNameInDb();
|
|
299
341
|
let dbRec = await table.findOne({ name });
|
|
342
|
+
if (!dbRec) {
|
|
343
|
+
dbRec = await migrateLegacyRec(table, name);
|
|
344
|
+
}
|
|
300
345
|
if (dbRec) {
|
|
301
346
|
if (dbRec.scope !== scope) {
|
|
302
347
|
console.warn(`${name}: deleting old persistent var record because scopes don't match. If this is unexpected there could be two different persistent variables using the same name`);
|
|
@@ -340,7 +385,7 @@ function persistentVarFactory(name, opts) {
|
|
|
340
385
|
return;
|
|
341
386
|
}
|
|
342
387
|
rec.value.value = value;
|
|
343
|
-
const dc =
|
|
388
|
+
const dc = getStorageDataContext();
|
|
344
389
|
const table = PersistentVars(dc);
|
|
345
390
|
try {
|
|
346
391
|
rec = await table.save(rec, { weakInsert: true });
|
|
@@ -362,7 +407,7 @@ function persistentVarFactory(name, opts) {
|
|
|
362
407
|
}
|
|
363
408
|
}
|
|
364
409
|
deleteVarImpl = async () => {
|
|
365
|
-
const dc =
|
|
410
|
+
const dc = getStorageDataContext();
|
|
366
411
|
const table = PersistentVars(dc);
|
|
367
412
|
if (rec?.persistentVarId) {
|
|
368
413
|
await table.delete(rec);
|
|
@@ -374,7 +419,7 @@ function persistentVarFactory(name, opts) {
|
|
|
374
419
|
};
|
|
375
420
|
// subscribe to db changes
|
|
376
421
|
userContext.subscribeToDataChangedAcrossAllGroups(exports.persistentVarsMetaData.name, async (evt) => {
|
|
377
|
-
const dc =
|
|
422
|
+
const dc = getStorageDataContext();
|
|
378
423
|
if (dc && evt.dataContext && evt.dataContext.dataContextId !== dc.dataContextId) {
|
|
379
424
|
return;
|
|
380
425
|
}
|
|
@@ -50,8 +50,8 @@ export declare const toolAccessApprovalSchema: z.ZodObject<{
|
|
|
50
50
|
userId: string;
|
|
51
51
|
expiresAt: Date;
|
|
52
52
|
toolId: string;
|
|
53
|
-
createdAt: Date;
|
|
54
53
|
dataContextId: string;
|
|
54
|
+
createdAt: Date;
|
|
55
55
|
toolAccessApprovalId: string;
|
|
56
56
|
toolName: string;
|
|
57
57
|
argsHash: string;
|
|
@@ -106,8 +106,8 @@ export declare function ToolAccessApprovals(dataContext?: DataContext): import("
|
|
|
106
106
|
userId: string;
|
|
107
107
|
expiresAt: Date;
|
|
108
108
|
toolId: string;
|
|
109
|
-
createdAt: Date;
|
|
110
109
|
dataContextId: string;
|
|
110
|
+
createdAt: Date;
|
|
111
111
|
toolAccessApprovalId: string;
|
|
112
112
|
toolName: string;
|
|
113
113
|
argsHash: string;
|