@cero-base/core 0.6.0 → 0.7.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cero-base/core",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "cero p2p primitives — identity, storage, network, database, blobs, rpc, pairing.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -37,6 +37,11 @@ export function makeDispatcher(spec, ns, routes) {
37
37
  if (kind === COLLECTION) await insert(ctx.view, name, col, op)
38
38
  else await ctx.view.insert(col, op)
39
39
  }
40
+ const update = (name, col) => async (op, ctx) => {
41
+ const existing = await ctx.view.get(col, { id: op.id })
42
+ if (!existing) return
43
+ await insert(ctx.view, name, col, { ...existing, ...op })
44
+ }
40
45
  const remove = (col) => async (op, ctx) => ctx.view.delete(col, op)
41
46
  const add = (verb, fn) => dispatcher.add(`@${ns}/${verb}`, fn)
42
47
 
@@ -127,7 +132,7 @@ export function makeDispatcher(spec, ns, routes) {
127
132
  continue
128
133
  }
129
134
  add(`add-${b.verb}`, upsert(b.name, col, COLLECTION))
130
- add(`set-${b.verb}`, upsert(b.name, col, COLLECTION))
135
+ add(`set-${b.verb}`, update(b.name, col))
131
136
  add(`del-${b.verb}`, remove(col))
132
137
  }
133
138
 
@@ -140,7 +145,7 @@ export function makeDispatcher(spec, ns, routes) {
140
145
  }
141
146
  const col = `@${ns}/${name}`
142
147
  const kind = info.kind === SINGLE ? SINGLE : COLLECTION
143
- add(`set-${name}`, upsert(name, col, kind))
148
+ add(`set-${name}`, kind === SINGLE ? upsert(name, col, kind) : update(name, col))
144
149
  if (info.kind === SINGLE) continue
145
150
  add(`add-${name}`, upsert(name, col, COLLECTION))
146
151
  add(`del-${name}`, remove(col))
@@ -243,13 +243,16 @@ export class Database extends ReadyResource {
243
243
  }
244
244
 
245
245
  /**
246
- * Upsert by merging with the existing row, preserving `createdAt`.
246
+ * Upsert by merging with the existing row, preserving `createdAt`. Pass
247
+ * `{ upsert: false }` to update-only — a missing row is left untouched
248
+ * (checked atomically in the dispatch, so it never resurrects a deleted row).
247
249
  *
248
250
  * @param {string} name
249
251
  * @param {Record<string, any>} row
252
+ * @param {{ upsert?: boolean }} [opts]
250
253
  * @returns {Promise<SingleResult | null>}
251
254
  */
252
- async set(name, row) {
255
+ async set(name, row, { upsert = true } = {}) {
253
256
  this.guard()
254
257
  const ref = this.ref(name)
255
258
  const col = this.col(ref)
@@ -260,6 +263,7 @@ export class Database extends ReadyResource {
260
263
  : row?.id
261
264
  ? ((await this.view.get(col, { id: row.id })) ?? null)
262
265
  : null
266
+ if (!upsert && !existing) return null
263
267
  const stored = {
264
268
  ...existing,
265
269
  ...row,
@@ -271,7 +275,11 @@ export class Database extends ReadyResource {
271
275
  const ctx = { op: 'set', name, row: stored }
272
276
  if ((await this.runBefore('set', ctx)) === false) return null
273
277
 
274
- await this.write([[`set-${ref.verb}`, ctx.row]])
278
+ // member/device have bespoke set handlers — only generic collections upsert via add-
279
+ const special = ref.verb === 'member' || ref.verb === 'device'
280
+ const verb =
281
+ ref.kind === COLLECTION && upsert && !special ? `add-${ref.verb}` : `set-${ref.verb}`
282
+ await this.write([[verb, ctx.row]])
275
283
 
276
284
  const result = { data: ctx.row }
277
285
  await this.runAfter('set', { ...ctx, result })
@@ -126,13 +126,18 @@ export class Database extends ReadyResource {
126
126
  */
127
127
  put(name: string, row: Record<string, any>): Promise<SingleResult | null>;
128
128
  /**
129
- * Upsert by merging with the existing row, preserving `createdAt`.
129
+ * Upsert by merging with the existing row, preserving `createdAt`. Pass
130
+ * `{ upsert: false }` to update-only — a missing row is left untouched
131
+ * (checked atomically in the dispatch, so it never resurrects a deleted row).
130
132
  *
131
133
  * @param {string} name
132
134
  * @param {Record<string, any>} row
135
+ * @param {{ upsert?: boolean }} [opts]
133
136
  * @returns {Promise<SingleResult | null>}
134
137
  */
135
- set(name: string, row: Record<string, any>): Promise<SingleResult | null>;
138
+ set(name: string, row: Record<string, any>, { upsert }?: {
139
+ upsert?: boolean;
140
+ }): Promise<SingleResult | null>;
136
141
  /**
137
142
  * Delete by id (collection) or wipe the whole single-row table.
138
143
  *