@converse/skeletor 3.1.2 → 3.1.3

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/CHANGES.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.1.3 (2026-06-23)
4
+
5
+ - Fix a regression (since 3.1.0) where a missing record on a `read` was treated as an error.
6
+ `model.fetch({ promise: true })` rejected with the bare string `'Record Not Found'` on a
7
+ first-run read of a non-existent record (and the `error` callback / `'error'` event fired),
8
+ where previously 3.0.x had resolved. A read miss is a normal empty state, so it now
9
+ resolves with `null` on both the callback (`success`) and promise forms.
10
+
11
+ **Behaviour change:** a read miss no longer fires the `error` callback or the `'error'` event,
12
+ it fires `success(null)` instead.
13
+
14
+ - Storage-layer `sync` failures now surface a real `Error` (with a stack) through the `error`
15
+ callback / rejected promise instead of a bare string. The internal `Model#hydrate`
16
+ `'Record Not Found'` string-match workaround is removed accordingly.
17
+
3
18
  ## 3.1.2 (2026-06-22)
4
19
 
5
20
  - Fix the published package missing its `dist/` directory. `dist/` is gitignored and nothing built
@@ -8705,7 +8705,7 @@ class PersistentStorage {
8705
8705
  // eslint-disable-next-line @typescript-eslint/no-this-alias
8706
8706
  const that = this;
8707
8707
  async function localSync(method, model, options) {
8708
- let resp, errorMessage, promise, new_attributes;
8708
+ let resp, caughtError, promise, new_attributes;
8709
8709
  // We get the collection (and if necessary the model attribute.
8710
8710
  // Waiting for storeInitialized will cause another iteration of
8711
8711
  // the event loop, after which the collection reference will
@@ -8762,10 +8762,12 @@ class PersistentStorage {
8762
8762
  catch (error) {
8763
8763
  const storageSize = await that.getStorageSize();
8764
8764
  if (error.code === 22 && storageSize === 0) {
8765
- errorMessage = 'Private browsing is unsupported';
8765
+ caughtError = new Error('Private browsing is unsupported');
8766
8766
  }
8767
8767
  else {
8768
- errorMessage = error.message;
8768
+ // Preserve a real Error (stack/name); wrap anything else so the
8769
+ // error path always surfaces an Error, never a bare string.
8770
+ caughtError = error instanceof Error ? error : new Error(error?.message ?? String(error));
8769
8771
  }
8770
8772
  }
8771
8773
  if (resp) {
@@ -8779,10 +8781,21 @@ class PersistentStorage {
8779
8781
  options.success(data, options);
8780
8782
  }
8781
8783
  }
8784
+ else if (method === 'read' && !caughtError) {
8785
+ // A read that finds no record is a normal empty result (first run /
8786
+ // empty storage), not an error. Resolve with `null` so the callback
8787
+ // and promise forms of fetch() agree and a first-run read never
8788
+ // rejects.
8789
+ if (options && options.success) {
8790
+ options.success(null, options);
8791
+ }
8792
+ }
8782
8793
  else {
8783
- errorMessage = errorMessage ? errorMessage : 'Record Not Found';
8794
+ // A genuine failure (storage threw, or a write produced no result):
8795
+ // surface a real Error so consumers get a stack and `instanceof Error`
8796
+ // holds.
8784
8797
  if (options && options.error) {
8785
- options.error(errorMessage);
8798
+ options.error(caughtError ?? new Error('Record Not Found'));
8786
8799
  }
8787
8800
  }
8788
8801
  }
@@ -11454,12 +11467,6 @@ _Model_computedCache = new WeakMap(), _Model_computedDefs = new WeakMap(), _Mode
11454
11467
  try {
11455
11468
  await this.fetch({ fromStorage: true, promise: true });
11456
11469
  }
11457
- catch (e) {
11458
- // 'Record Not Found' is a normal first-run state (nothing stored yet);
11459
- // keep the initial attributes and resolve. Re-throw anything else.
11460
- if (e !== 'Record Not Found')
11461
- throw e;
11462
- }
11463
11470
  finally {
11464
11471
  __classPrivateFieldSet(this, _Model_state, 'ready', "f");
11465
11472
  }
@@ -12234,8 +12241,9 @@ class Collection extends EventEmitterObject {
12234
12241
  }
12235
12242
  _Collection_instances = new WeakSet(), _Collection_hydrate = async function _Collection_hydrate() {
12236
12243
  ensureUnloadListener(PersistentStorage);
12237
- // findAll() returns [] for an empty store, so a first-run collection
12238
- // resolves rather than erroring the way a model fetch-by-id would.
12244
+ // An empty store is a normal first-run state: findAll() returns [] and a
12245
+ // missing model record resolves to null, so hydration resolves rather
12246
+ // than rejecting.
12239
12247
  await this.fetch({ fromStorage: true, promise: true });
12240
12248
  }, _a = Symbol.iterator;
12241
12249
  // This "enum" defines the three possible kinds of values which can be emitted