memorio 5.1.3 → 5.1.4

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/index.cjs CHANGED
@@ -3324,19 +3324,39 @@ if (globalThis[STATE_INSTANCE_KEY]) {
3324
3324
  const initial = exports.store.get(key);
3325
3325
  if (initial !== void 0 && initial !== null) {
3326
3326
  let acc = exports.state;
3327
+ let seedOk = true;
3327
3328
  for (let i = 0; i < segments.length - 1; i++) {
3328
3329
  const seg = segments[i];
3329
- if (acc[seg] === void 0 || acc[seg] === null) acc[seg] = {};
3330
- acc = acc[seg];
3330
+ const existing = acc[seg];
3331
+ if (existing === void 0 || existing === null) {
3332
+ acc[seg] = {};
3333
+ acc = acc[seg];
3334
+ } else if (typeof existing === "object") {
3335
+ acc = existing;
3336
+ } else {
3337
+ if (exports.DEV) {
3338
+ console.warn(
3339
+ `[memorio state] state.persist('${normalized}') aborted seeding: '${seg}' already holds a primitive value (${typeof existing}), cannot nest '${segments.slice(i + 1).join(".")}' under it.`
3340
+ );
3341
+ }
3342
+ seedOk = false;
3343
+ break;
3344
+ }
3345
+ }
3346
+ if (seedOk && acc) {
3347
+ acc[segments[segments.length - 1]] = deepRaw(initial);
3331
3348
  }
3332
- if (acc) acc[segments[segments.length - 1]] = deepRaw(initial);
3333
3349
  }
3334
3350
  const handler = /* @__PURE__ */ __name(() => {
3335
3351
  let current = exports.state;
3336
3352
  for (const seg of segments) {
3337
3353
  current = current === void 0 || current === null ? void 0 : current[seg];
3338
3354
  }
3339
- exports.store.set(key, deepRaw(current));
3355
+ if (current === void 0) {
3356
+ exports.store.remove(key);
3357
+ } else {
3358
+ exports.store.set(key, deepRaw(current));
3359
+ }
3340
3360
  }, "handler");
3341
3361
  const off = dispatch.listen(normalized, handler);
3342
3362
  return typeof off === "function" ? off : () => {
@@ -3756,8 +3776,7 @@ var observerFunction = /* @__PURE__ */ __name((s, cb = null, option = true) => {
3756
3776
  }
3757
3777
  if (s && cb) {
3758
3778
  const resolvedPath = resolvePath(s);
3759
- if (!resolvedPath) return;
3760
- if (typeof s !== "string" && !(s && typeof s === "object")) {
3779
+ if (!resolvedPath) {
3761
3780
  console.error(`Observer Error: name of state need to be a 'string' like 'state.test' or a direct state value`);
3762
3781
  return;
3763
3782
  }
@@ -3807,7 +3826,7 @@ Object.defineProperties(
3807
3826
  * @returns void
3808
3827
  */
3809
3828
  removeAll: {
3810
- get: /* @__PURE__ */ __name(() => {
3829
+ value: /* @__PURE__ */ __name(() => {
3811
3830
  const obs = globalThis.observer;
3812
3831
  const list = obs?.list;
3813
3832
  if (list) {
@@ -3816,7 +3835,7 @@ Object.defineProperties(
3816
3835
  });
3817
3836
  }
3818
3837
  return true;
3819
- }, "get")
3838
+ }, "value")
3820
3839
  },
3821
3840
  ///
3822
3841
  /**
@@ -3846,40 +3865,58 @@ var useObserver = /* @__PURE__ */ __name(((func, deps = []) => {
3846
3865
  const unsubs = [];
3847
3866
  const depList = Array.isArray(deps) && !deps.__path ? deps : [deps];
3848
3867
  try {
3849
- depList.forEach((dep) => {
3850
- let t = "";
3851
- if (typeof dep === "function") {
3852
- const result = exports.propertyName(dep);
3853
- if (result) t = result;
3854
- } else if (typeof dep === "object" && dep !== null) {
3855
- t = dep.__path || (typeof dep.toString === "function" && dep.toString() !== "[object Object]" ? dep.toString() : "");
3868
+ if (depList.length === 0) {
3869
+ exports.internal.clearTrackedPaths();
3870
+ exports.internal.tracking = true;
3871
+ try {
3872
+ func();
3873
+ } catch (_) {
3856
3874
  }
3857
- if (t) {
3858
- t = t.replace(/^(\(\)\s*=>\s*)/, "").replace(/^globalThis\./, "").replace(/^state\./, "");
3859
- const path = t.startsWith("store.") || t.startsWith("state.") ? t : "state." + t;
3875
+ exports.internal.tracking = false;
3876
+ exports.internal.trackedPaths.forEach((path) => {
3860
3877
  if (!handlers.includes(path)) {
3878
+ message_default(`useObserver: [Auto-Discovery] -> "${path}"`);
3861
3879
  handlers.push(path);
3862
3880
  const off = dispatch.listen(path, () => func());
3863
3881
  if (typeof off === "function") unsubs.push({ path, off });
3864
3882
  }
3865
- } else {
3866
- exports.internal.clearTrackedPaths();
3867
- exports.internal.tracking = true;
3868
- try {
3869
- func();
3870
- } catch (_) {
3883
+ });
3884
+ } else {
3885
+ depList.forEach((dep) => {
3886
+ let t = "";
3887
+ if (typeof dep === "function") {
3888
+ const result = exports.propertyName(dep);
3889
+ if (result) t = result;
3890
+ } else if (typeof dep === "object" && dep !== null) {
3891
+ t = dep.__path || (typeof dep.toString === "function" && dep.toString() !== "[object Object]" ? dep.toString() : "");
3871
3892
  }
3872
- exports.internal.tracking = false;
3873
- exports.internal.trackedPaths.forEach((path) => {
3893
+ if (t) {
3894
+ t = t.replace(/^(\(\)\s*=>\s*)/, "").replace(/^globalThis\./, "").replace(/^state\./, "");
3895
+ const path = t.startsWith("store.") || t.startsWith("state.") ? t : "state." + t;
3874
3896
  if (!handlers.includes(path)) {
3875
- message_default(`useObserver: [Auto-Discovery] -> "${path}"`);
3876
3897
  handlers.push(path);
3877
3898
  const off = dispatch.listen(path, () => func());
3878
3899
  if (typeof off === "function") unsubs.push({ path, off });
3879
3900
  }
3880
- });
3881
- }
3882
- });
3901
+ } else {
3902
+ exports.internal.clearTrackedPaths();
3903
+ exports.internal.tracking = true;
3904
+ try {
3905
+ func();
3906
+ } catch (_) {
3907
+ }
3908
+ exports.internal.tracking = false;
3909
+ exports.internal.trackedPaths.forEach((path) => {
3910
+ if (!handlers.includes(path)) {
3911
+ message_default(`useObserver: [Auto-Discovery] -> "${path}"`);
3912
+ handlers.push(path);
3913
+ const off = dispatch.listen(path, () => func());
3914
+ if (typeof off === "function") unsubs.push({ path, off });
3915
+ }
3916
+ });
3917
+ }
3918
+ });
3919
+ }
3883
3920
  if (handlers.length > 0) {
3884
3921
  message_default(`useObserver: Monitoring ${handlers.length} paths.`);
3885
3922
  } else {
@@ -4805,7 +4842,7 @@ init_internal();
4805
4842
 
4806
4843
  // package.json
4807
4844
  var package_default = {
4808
- version: "5.1.3"};
4845
+ version: "5.1.4"};
4809
4846
 
4810
4847
  // core/global.ts
4811
4848
  init_env();
@@ -5481,19 +5518,22 @@ var memory = {
5481
5518
  async patch(key, patches) {
5482
5519
  const entry = await this._getEntry(key);
5483
5520
  if (!entry) return;
5521
+ const patchedValue = JSON.parse(JSON.stringify(entry.value ?? {}));
5484
5522
  let patched = false;
5485
5523
  for (const p of patches) {
5524
+ const relativePath = p.path.replace(/^[^.]+\./, "");
5486
5525
  if (p.op === "set") {
5487
- setNestedPath({ [entry.key]: entry.value }, p.path.replace(/^[^.]+\./, ""), p.value);
5526
+ setNestedPath(patchedValue, relativePath, p.value);
5488
5527
  patched = true;
5489
5528
  } else if (p.op === "delete") {
5490
- deleteNestedPath({ [entry.key]: entry.value }, p.path.replace(/^[^.]+\./, ""));
5529
+ deleteNestedPath(patchedValue, relativePath);
5491
5530
  patched = true;
5492
5531
  }
5493
5532
  }
5494
5533
  if (!patched) return;
5495
5534
  const updated = {
5496
5535
  ...entry,
5536
+ value: patchedValue,
5497
5537
  updatedAt: now(),
5498
5538
  lastConfirmedAt: now(),
5499
5539
  version: (entry.version ? entry.version : 0) + 1,
package/index.js CHANGED
@@ -3321,19 +3321,39 @@ if (globalThis[STATE_INSTANCE_KEY]) {
3321
3321
  const initial = store.get(key);
3322
3322
  if (initial !== void 0 && initial !== null) {
3323
3323
  let acc = state2;
3324
+ let seedOk = true;
3324
3325
  for (let i = 0; i < segments.length - 1; i++) {
3325
3326
  const seg = segments[i];
3326
- if (acc[seg] === void 0 || acc[seg] === null) acc[seg] = {};
3327
- acc = acc[seg];
3327
+ const existing = acc[seg];
3328
+ if (existing === void 0 || existing === null) {
3329
+ acc[seg] = {};
3330
+ acc = acc[seg];
3331
+ } else if (typeof existing === "object") {
3332
+ acc = existing;
3333
+ } else {
3334
+ if (DEV) {
3335
+ console.warn(
3336
+ `[memorio state] state.persist('${normalized}') aborted seeding: '${seg}' already holds a primitive value (${typeof existing}), cannot nest '${segments.slice(i + 1).join(".")}' under it.`
3337
+ );
3338
+ }
3339
+ seedOk = false;
3340
+ break;
3341
+ }
3342
+ }
3343
+ if (seedOk && acc) {
3344
+ acc[segments[segments.length - 1]] = deepRaw(initial);
3328
3345
  }
3329
- if (acc) acc[segments[segments.length - 1]] = deepRaw(initial);
3330
3346
  }
3331
3347
  const handler = /* @__PURE__ */ __name(() => {
3332
3348
  let current = state2;
3333
3349
  for (const seg of segments) {
3334
3350
  current = current === void 0 || current === null ? void 0 : current[seg];
3335
3351
  }
3336
- store.set(key, deepRaw(current));
3352
+ if (current === void 0) {
3353
+ store.remove(key);
3354
+ } else {
3355
+ store.set(key, deepRaw(current));
3356
+ }
3337
3357
  }, "handler");
3338
3358
  const off = dispatch.listen(normalized, handler);
3339
3359
  return typeof off === "function" ? off : () => {
@@ -3753,8 +3773,7 @@ var observerFunction = /* @__PURE__ */ __name((s, cb = null, option = true) => {
3753
3773
  }
3754
3774
  if (s && cb) {
3755
3775
  const resolvedPath = resolvePath(s);
3756
- if (!resolvedPath) return;
3757
- if (typeof s !== "string" && !(s && typeof s === "object")) {
3776
+ if (!resolvedPath) {
3758
3777
  console.error(`Observer Error: name of state need to be a 'string' like 'state.test' or a direct state value`);
3759
3778
  return;
3760
3779
  }
@@ -3804,7 +3823,7 @@ Object.defineProperties(
3804
3823
  * @returns void
3805
3824
  */
3806
3825
  removeAll: {
3807
- get: /* @__PURE__ */ __name(() => {
3826
+ value: /* @__PURE__ */ __name(() => {
3808
3827
  const obs = globalThis.observer;
3809
3828
  const list = obs?.list;
3810
3829
  if (list) {
@@ -3813,7 +3832,7 @@ Object.defineProperties(
3813
3832
  });
3814
3833
  }
3815
3834
  return true;
3816
- }, "get")
3835
+ }, "value")
3817
3836
  },
3818
3837
  ///
3819
3838
  /**
@@ -3843,40 +3862,58 @@ var useObserver = /* @__PURE__ */ __name(((func, deps = []) => {
3843
3862
  const unsubs = [];
3844
3863
  const depList = Array.isArray(deps) && !deps.__path ? deps : [deps];
3845
3864
  try {
3846
- depList.forEach((dep) => {
3847
- let t = "";
3848
- if (typeof dep === "function") {
3849
- const result = propertyName(dep);
3850
- if (result) t = result;
3851
- } else if (typeof dep === "object" && dep !== null) {
3852
- t = dep.__path || (typeof dep.toString === "function" && dep.toString() !== "[object Object]" ? dep.toString() : "");
3865
+ if (depList.length === 0) {
3866
+ internal_default.clearTrackedPaths();
3867
+ internal_default.tracking = true;
3868
+ try {
3869
+ func();
3870
+ } catch (_) {
3853
3871
  }
3854
- if (t) {
3855
- t = t.replace(/^(\(\)\s*=>\s*)/, "").replace(/^globalThis\./, "").replace(/^state\./, "");
3856
- const path2 = t.startsWith("store.") || t.startsWith("state.") ? t : "state." + t;
3872
+ internal_default.tracking = false;
3873
+ internal_default.trackedPaths.forEach((path2) => {
3857
3874
  if (!handlers.includes(path2)) {
3875
+ message_default(`useObserver: [Auto-Discovery] -> "${path2}"`);
3858
3876
  handlers.push(path2);
3859
3877
  const off = dispatch.listen(path2, () => func());
3860
3878
  if (typeof off === "function") unsubs.push({ path: path2, off });
3861
3879
  }
3862
- } else {
3863
- internal_default.clearTrackedPaths();
3864
- internal_default.tracking = true;
3865
- try {
3866
- func();
3867
- } catch (_) {
3880
+ });
3881
+ } else {
3882
+ depList.forEach((dep) => {
3883
+ let t = "";
3884
+ if (typeof dep === "function") {
3885
+ const result = propertyName(dep);
3886
+ if (result) t = result;
3887
+ } else if (typeof dep === "object" && dep !== null) {
3888
+ t = dep.__path || (typeof dep.toString === "function" && dep.toString() !== "[object Object]" ? dep.toString() : "");
3868
3889
  }
3869
- internal_default.tracking = false;
3870
- internal_default.trackedPaths.forEach((path2) => {
3890
+ if (t) {
3891
+ t = t.replace(/^(\(\)\s*=>\s*)/, "").replace(/^globalThis\./, "").replace(/^state\./, "");
3892
+ const path2 = t.startsWith("store.") || t.startsWith("state.") ? t : "state." + t;
3871
3893
  if (!handlers.includes(path2)) {
3872
- message_default(`useObserver: [Auto-Discovery] -> "${path2}"`);
3873
3894
  handlers.push(path2);
3874
3895
  const off = dispatch.listen(path2, () => func());
3875
3896
  if (typeof off === "function") unsubs.push({ path: path2, off });
3876
3897
  }
3877
- });
3878
- }
3879
- });
3898
+ } else {
3899
+ internal_default.clearTrackedPaths();
3900
+ internal_default.tracking = true;
3901
+ try {
3902
+ func();
3903
+ } catch (_) {
3904
+ }
3905
+ internal_default.tracking = false;
3906
+ internal_default.trackedPaths.forEach((path2) => {
3907
+ if (!handlers.includes(path2)) {
3908
+ message_default(`useObserver: [Auto-Discovery] -> "${path2}"`);
3909
+ handlers.push(path2);
3910
+ const off = dispatch.listen(path2, () => func());
3911
+ if (typeof off === "function") unsubs.push({ path: path2, off });
3912
+ }
3913
+ });
3914
+ }
3915
+ });
3916
+ }
3880
3917
  if (handlers.length > 0) {
3881
3918
  message_default(`useObserver: Monitoring ${handlers.length} paths.`);
3882
3919
  } else {
@@ -4802,7 +4839,7 @@ init_internal();
4802
4839
 
4803
4840
  // package.json
4804
4841
  var package_default = {
4805
- version: "5.1.3"};
4842
+ version: "5.1.4"};
4806
4843
 
4807
4844
  // core/global.ts
4808
4845
  init_env();
@@ -5478,19 +5515,22 @@ var memory = {
5478
5515
  async patch(key, patches) {
5479
5516
  const entry = await this._getEntry(key);
5480
5517
  if (!entry) return;
5518
+ const patchedValue = JSON.parse(JSON.stringify(entry.value ?? {}));
5481
5519
  let patched = false;
5482
5520
  for (const p of patches) {
5521
+ const relativePath = p.path.replace(/^[^.]+\./, "");
5483
5522
  if (p.op === "set") {
5484
- setNestedPath({ [entry.key]: entry.value }, p.path.replace(/^[^.]+\./, ""), p.value);
5523
+ setNestedPath(patchedValue, relativePath, p.value);
5485
5524
  patched = true;
5486
5525
  } else if (p.op === "delete") {
5487
- deleteNestedPath({ [entry.key]: entry.value }, p.path.replace(/^[^.]+\./, ""));
5526
+ deleteNestedPath(patchedValue, relativePath);
5488
5527
  patched = true;
5489
5528
  }
5490
5529
  }
5491
5530
  if (!patched) return;
5492
5531
  const updated = {
5493
5532
  ...entry,
5533
+ value: patchedValue,
5494
5534
  updatedAt: now(),
5495
5535
  lastConfirmedAt: now(),
5496
5536
  version: (entry.version ? entry.version : 0) + 1,
package/llms.txt CHANGED
@@ -91,6 +91,19 @@ These are materially different behaviors - confirm against the actual source whi
91
91
  - Automatic path tracking via `__path` property
92
92
  - Nested proxy support
93
93
  - Auto-dispatches events on changes
94
+ - `state.persist(path)` mirrors state path to `store` and syncs writes (see "Getting Started" guide)
95
+
96
+ #### `state.persist(path)`
97
+
98
+ Creates a bidirectional mirror between `state` (live in-memory) and `store` (durable copy). Seeds the initial value from `store` if present, then every write to that path flows to `store` automatically.
99
+
100
+ ```javascript
101
+ const stopPersisting = state.persist('state.user')
102
+ state.user = { name: 'Sara' }
103
+ // ... writes to state.user are mirrored to store
104
+
105
+ stopPersisting() // stops mirroring; store value is preserved
106
+ ```
94
107
 
95
108
  ### `store` - localStorage Persistence
96
109
 
@@ -69,6 +69,33 @@ Permanently removes a memory.
69
69
  await memorio.memory.forget('user.temp')
70
70
  ```
71
71
 
72
+ ### `memorio.memory.patch(key, patches)`
73
+
74
+ Apply a field-level JSON Patch to an existing memory entry's value. Supports `set` and `delete` operations.
75
+
76
+ ```ts
77
+ await memorio.memory.remember('user', {
78
+ name: 'Mario',
79
+ profile: { theme: 'light', lang: 'en' }
80
+ })
81
+
82
+ // Set a nested value
83
+ await memorio.memory.patch('user', [
84
+ { op: 'set', path: 'user.profile.theme', value: 'dark' }
85
+ ])
86
+
87
+ // Delete a field
88
+ await memorio.memory.patch('user', [
89
+ { op: 'delete', path: 'user.profile.lang' }
90
+ ])
91
+ ```
92
+
93
+ | Field | Type | Description |
94
+ |-------|------|-------------|
95
+ | `op` | `'set' \| 'delete'` | The patch operation type |
96
+ | `path` | `string` | Dot-notation path relative to the entry value (e.g. `'user.profile.theme'`) |
97
+ | `value` | `any` | The value to set (only for `op: 'set'`) |
98
+
72
99
  ### `memorio.memory.context(opts?)`
73
100
 
74
101
  Returns ranked, relevant memories. Uses recency × confidence × type/scope boost algorithm.
@@ -153,8 +153,8 @@ await sqlite.db.journal.checkpoint('app'); // manual checkpoint
153
153
 
154
154
  | Method | Parameters | Returns | Description |
155
155
  |--------|------------|---------|-------------|
156
- | `sqlite.config(opts)` | `opts: { loader?, locateFile?, wasmUrl?, persistence?, namespace? }` | `sqlite` | Configure the engine. `loader` fully replaces the initializer (default = CDN `<script>`); `locateFile` customizes wasm resolution; `wasmUrl` sets the wasm base directory; `persistence` toggles automatic db snapshots; `namespace` partitions persisted snapshots. Chainable. |
157
- | `sqlite.db.create(name, opts)` | `name: string, opts?: { data?, persistence? }` | `Database` | Opens/creates a named in-memory db. With `persistence: true` (or global config), a snapshot is restored if present and writes are auto-saved. |
156
+ | `sqlite.config(opts)` | `opts: { loader?, locateFile?, wasmUrl?, persistence?, namespace? }` | `sqlite` | Configure the engine. `loader` fully replaces the initializer (default = CDN `<script>`); `locateFile` customizes wasm resolution; `wasmUrl` sets the wasm base directory; `persistence` toggles journal + checkpoint persistence; `namespace` partitions persisted data. Chainable. |
157
+ | `sqlite.db.create(name, opts)` | `name: string, opts?: { data?, persistence? }` | `Database` | Opens/creates a named in-memory db. With `persistence: true` (or global config), the latest checkpoint is restored and pending journal entries are replayed for full crash recovery. |
158
158
  | `sqlite.db.persist(name)` | `name: string` | `Promise<boolean>` | Force an immediate checkpoint (full snapshot + journal clear) of a persisted database to `store`. Alias of `flush`. |
159
159
  | `sqlite.db.flush(name)` | `name: string` | `Promise<boolean>` | Force an immediate checkpoint (alias of `persist`). |
160
160
  | `sqlite.db.download(name, filename?)` | `name: string, filename?: string` | `Promise<boolean>` | Dev-only: trigger a browser download of the db as a `.sqlite` file. |
package/markdown/SYNC.md CHANGED
@@ -71,7 +71,7 @@ the durable journal/value store when you opt in:
71
71
  snapshot the database to `store` (localStorage) and restore it on reopen.
72
72
  - Writes are journaled incrementally (append-only, HLC-timestamped) and
73
73
  checkpointed periodically (every 50 ops or 250 ms of idle). On reopen, the
74
- last checkpoint is loaded and the journal is replayed — no writes are lost.
74
+ last checkpoint is loaded and the journal is replayed - no writes are lost.
75
75
  - `sqlite.db.persist(name)` / `sqlite.db.flush(name)` forces an immediate
76
76
  checkpoint; `sqlite.db.close(name)` checkpoints + closes;
77
77
  `sqlite.db.download(name, file?)` triggers a browser `.sqlite` download
package/modules/redux.cjs CHANGED
@@ -2029,19 +2029,39 @@ if (globalThis[STATE_INSTANCE_KEY]) {
2029
2029
  const initial = store.get(key);
2030
2030
  if (initial !== void 0 && initial !== null) {
2031
2031
  let acc = state2;
2032
+ let seedOk = true;
2032
2033
  for (let i = 0; i < segments.length - 1; i++) {
2033
2034
  const seg = segments[i];
2034
- if (acc[seg] === void 0 || acc[seg] === null) acc[seg] = {};
2035
- acc = acc[seg];
2035
+ const existing = acc[seg];
2036
+ if (existing === void 0 || existing === null) {
2037
+ acc[seg] = {};
2038
+ acc = acc[seg];
2039
+ } else if (typeof existing === "object") {
2040
+ acc = existing;
2041
+ } else {
2042
+ if (DEV) {
2043
+ console.warn(
2044
+ `[memorio state] state.persist('${normalized}') aborted seeding: '${seg}' already holds a primitive value (${typeof existing}), cannot nest '${segments.slice(i + 1).join(".")}' under it.`
2045
+ );
2046
+ }
2047
+ seedOk = false;
2048
+ break;
2049
+ }
2050
+ }
2051
+ if (seedOk && acc) {
2052
+ acc[segments[segments.length - 1]] = deepRaw(initial);
2036
2053
  }
2037
- if (acc) acc[segments[segments.length - 1]] = deepRaw(initial);
2038
2054
  }
2039
2055
  const handler = /* @__PURE__ */ __name(() => {
2040
2056
  let current = state2;
2041
2057
  for (const seg of segments) {
2042
2058
  current = current === void 0 || current === null ? void 0 : current[seg];
2043
2059
  }
2044
- store.set(key, deepRaw(current));
2060
+ if (current === void 0) {
2061
+ store.remove(key);
2062
+ } else {
2063
+ store.set(key, deepRaw(current));
2064
+ }
2045
2065
  }, "handler");
2046
2066
  const off = dispatch.listen(normalized, handler);
2047
2067
  return typeof off === "function" ? off : () => {
@@ -3031,19 +3051,22 @@ var memory = {
3031
3051
  async patch(key, patches) {
3032
3052
  const entry = await this._getEntry(key);
3033
3053
  if (!entry) return;
3054
+ const patchedValue = JSON.parse(JSON.stringify(entry.value ?? {}));
3034
3055
  let patched = false;
3035
3056
  for (const p of patches) {
3057
+ const relativePath = p.path.replace(/^[^.]+\./, "");
3036
3058
  if (p.op === "set") {
3037
- setNestedPath({ [entry.key]: entry.value }, p.path.replace(/^[^.]+\./, ""), p.value);
3059
+ setNestedPath(patchedValue, relativePath, p.value);
3038
3060
  patched = true;
3039
3061
  } else if (p.op === "delete") {
3040
- deleteNestedPath({ [entry.key]: entry.value }, p.path.replace(/^[^.]+\./, ""));
3062
+ deleteNestedPath(patchedValue, relativePath);
3041
3063
  patched = true;
3042
3064
  }
3043
3065
  }
3044
3066
  if (!patched) return;
3045
3067
  const updated = {
3046
3068
  ...entry,
3069
+ value: patchedValue,
3047
3070
  updatedAt: now(),
3048
3071
  lastConfirmedAt: now(),
3049
3072
  version: (entry.version ? entry.version : 0) + 1,