@converse/skeletor 4.0.0 → 4.0.2
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 +19 -0
- package/dist/skeletor.d.ts +925 -953
- package/dist/skeletor.esm.js +79 -91
- package/dist/skeletor.esm.js.map +1 -1
- package/dist/skeletor.js +79 -91
- package/dist/skeletor.js.map +1 -1
- package/dist/skeletor.min.js +5 -5
- package/dist/skeletor.node.d.ts +950 -978
- package/dist/skeletor.node.js +79 -91
- package/dist/skeletor.node.mjs +79 -91
- package/package.json +9 -19
- package/src/collection.ts +35 -34
- package/src/model.ts +85 -52
- package/src/types.ts +5 -6
package/dist/skeletor.js
CHANGED
|
@@ -1674,19 +1674,6 @@
|
|
|
1674
1674
|
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
1675
1675
|
}
|
|
1676
1676
|
|
|
1677
|
-
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
1678
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
1679
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
1680
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
1681
|
-
}
|
|
1682
|
-
|
|
1683
|
-
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
1684
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
1685
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
1686
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
1687
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
1688
|
-
}
|
|
1689
|
-
|
|
1690
1677
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
1691
1678
|
var e = new Error(message);
|
|
1692
1679
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
@@ -11014,7 +11001,47 @@
|
|
|
11014
11001
|
return object == null ? {} : basePick(object, paths);
|
|
11015
11002
|
});
|
|
11016
11003
|
|
|
11017
|
-
|
|
11004
|
+
const INTERNALS = new WeakMap();
|
|
11005
|
+
function internals(model) {
|
|
11006
|
+
let priv = INTERNALS.get(model);
|
|
11007
|
+
if (!priv) {
|
|
11008
|
+
priv = { state: 'constructing' };
|
|
11009
|
+
INTERNALS.set(model, priv);
|
|
11010
|
+
}
|
|
11011
|
+
return priv;
|
|
11012
|
+
}
|
|
11013
|
+
/** Load the model from storage, marking it ready whether or not the read succeeds. */
|
|
11014
|
+
async function hydrate$1(model, priv) {
|
|
11015
|
+
ensureUnloadListener(PersistentStorage);
|
|
11016
|
+
try {
|
|
11017
|
+
await model.fetch({ fromStorage: true, promise: true });
|
|
11018
|
+
}
|
|
11019
|
+
finally {
|
|
11020
|
+
priv.state = 'ready';
|
|
11021
|
+
}
|
|
11022
|
+
}
|
|
11023
|
+
/** Evaluate the model's declared computed properties once, seeding the cache. */
|
|
11024
|
+
function initComputed(model, priv) {
|
|
11025
|
+
const defs = result(model, 'computed');
|
|
11026
|
+
if (!defs || isEmpty(defs))
|
|
11027
|
+
return;
|
|
11028
|
+
priv.computedDefs = defs;
|
|
11029
|
+
priv.computedCache = {};
|
|
11030
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
11031
|
+
priv.computedCache[key] = def.fn(model);
|
|
11032
|
+
}
|
|
11033
|
+
}
|
|
11034
|
+
/** Recompute one computed property, firing `change:key` when its value changed. */
|
|
11035
|
+
function updateComputed(model, priv, key, def, silent, options) {
|
|
11036
|
+
const newVal = def.fn(model);
|
|
11037
|
+
if (!isEqual(priv.computedCache[key], newVal)) {
|
|
11038
|
+
priv.computedCache[key] = newVal;
|
|
11039
|
+
if (!silent) {
|
|
11040
|
+
model.changed[key] = newVal;
|
|
11041
|
+
model.trigger('change:' + key, model, newVal, options);
|
|
11042
|
+
}
|
|
11043
|
+
}
|
|
11044
|
+
}
|
|
11018
11045
|
/**
|
|
11019
11046
|
* @public
|
|
11020
11047
|
* **Models** are the basic data object in the framework --
|
|
@@ -11029,15 +11056,12 @@
|
|
|
11029
11056
|
*/
|
|
11030
11057
|
constructor(attributes, options) {
|
|
11031
11058
|
super();
|
|
11032
|
-
_Model_instances.add(this);
|
|
11033
|
-
_Model_computedCache.set(this, void 0);
|
|
11034
|
-
_Model_computedDefs.set(this, void 0);
|
|
11035
|
-
_Model_state.set(this, 'constructing');
|
|
11036
11059
|
this._changing = false;
|
|
11037
11060
|
this._pending = false;
|
|
11038
11061
|
this._url = '';
|
|
11039
11062
|
this.changed = {};
|
|
11040
11063
|
this.validationError = null;
|
|
11064
|
+
const priv = internals(this);
|
|
11041
11065
|
let attrs = attributes || {};
|
|
11042
11066
|
options = options || {};
|
|
11043
11067
|
this.preinitialize.apply(this, arguments);
|
|
@@ -11050,11 +11074,12 @@
|
|
|
11050
11074
|
const default_attrs = result(this, 'defaults');
|
|
11051
11075
|
attrs = defaults(Object.assign({}, default_attrs, attrs), default_attrs);
|
|
11052
11076
|
this.set(attrs, options);
|
|
11053
|
-
|
|
11077
|
+
initComputed(this, priv);
|
|
11054
11078
|
this.attrs = new Proxy(this.attributes, {
|
|
11055
11079
|
get: (_target, key) => {
|
|
11056
|
-
|
|
11057
|
-
|
|
11080
|
+
const cache = priv.computedCache;
|
|
11081
|
+
if (typeof key !== 'symbol' && cache && key in cache) {
|
|
11082
|
+
return cache[key];
|
|
11058
11083
|
}
|
|
11059
11084
|
return this.attributes[key];
|
|
11060
11085
|
},
|
|
@@ -11072,16 +11097,16 @@
|
|
|
11072
11097
|
// otherwise it's already ready and resolves immediately.
|
|
11073
11098
|
if (this.autoSync) {
|
|
11074
11099
|
if (getStorage(this) && !this.isNew()) {
|
|
11075
|
-
|
|
11076
|
-
this.hydrated =
|
|
11100
|
+
priv.state = 'hydrating';
|
|
11101
|
+
this.hydrated = hydrate$1(this, priv);
|
|
11077
11102
|
}
|
|
11078
11103
|
else {
|
|
11079
|
-
|
|
11104
|
+
priv.state = 'ready';
|
|
11080
11105
|
this.hydrated = Promise.resolve();
|
|
11081
11106
|
}
|
|
11082
11107
|
}
|
|
11083
11108
|
else {
|
|
11084
|
-
|
|
11109
|
+
priv.state = 'ready';
|
|
11085
11110
|
}
|
|
11086
11111
|
}
|
|
11087
11112
|
/**
|
|
@@ -11180,8 +11205,9 @@
|
|
|
11180
11205
|
* Get the value of an attribute, or a computed property.
|
|
11181
11206
|
*/
|
|
11182
11207
|
get(attr) {
|
|
11183
|
-
|
|
11184
|
-
|
|
11208
|
+
const cache = internals(this).computedCache;
|
|
11209
|
+
if (cache && attr in cache) {
|
|
11210
|
+
return cache[attr];
|
|
11185
11211
|
}
|
|
11186
11212
|
return this.attributes[attr];
|
|
11187
11213
|
}
|
|
@@ -11257,9 +11283,10 @@
|
|
|
11257
11283
|
attrs[key] = val;
|
|
11258
11284
|
}
|
|
11259
11285
|
options = options || {};
|
|
11286
|
+
const priv = internals(this);
|
|
11260
11287
|
// Guard must come after arg normalization: when called as set(obj, opts),
|
|
11261
11288
|
// fromStorage lives in `val` (second arg), not `options` (third arg).
|
|
11262
|
-
if (this.autoSync &&
|
|
11289
|
+
if (this.autoSync && priv.state === 'hydrating' && !options.fromStorage) {
|
|
11263
11290
|
throw new Error(`Skeletor: set() called on an autoSync model before hydration resolved. Await model.hydrated first.`);
|
|
11264
11291
|
}
|
|
11265
11292
|
// Run validation.
|
|
@@ -11303,10 +11330,10 @@
|
|
|
11303
11330
|
}
|
|
11304
11331
|
}
|
|
11305
11332
|
// Recalculate computed properties whose deps changed.
|
|
11306
|
-
if (changes.length &&
|
|
11307
|
-
for (const [key, def] of Object.entries(
|
|
11333
|
+
if (changes.length && priv.computedDefs) {
|
|
11334
|
+
for (const [key, def] of Object.entries(priv.computedDefs)) {
|
|
11308
11335
|
if (def.deps.some((dep) => changes.includes(dep))) {
|
|
11309
|
-
|
|
11336
|
+
updateComputed(this, priv, key, def, silent, options);
|
|
11310
11337
|
}
|
|
11311
11338
|
}
|
|
11312
11339
|
}
|
|
@@ -11326,13 +11353,13 @@
|
|
|
11326
11353
|
// Auto-save: schedule a debounced write when autoSync is on and there
|
|
11327
11354
|
// were actual changes that originated from application code (not a
|
|
11328
11355
|
// storage read or an explicit noAutoSave call).
|
|
11329
|
-
if (
|
|
11356
|
+
if (priv.state === 'ready' &&
|
|
11330
11357
|
this.autoSync &&
|
|
11331
11358
|
getStorage(this) &&
|
|
11332
11359
|
changes.length &&
|
|
11333
11360
|
!options.fromStorage &&
|
|
11334
11361
|
!options.noAutoSave) {
|
|
11335
|
-
scheduleAutoSave(this, () =>
|
|
11362
|
+
scheduleAutoSave(this, () => this.save(null, { noAutoSave: true }), this.autoSyncDelay);
|
|
11336
11363
|
}
|
|
11337
11364
|
return this;
|
|
11338
11365
|
}
|
|
@@ -11613,37 +11640,8 @@
|
|
|
11613
11640
|
return false;
|
|
11614
11641
|
}
|
|
11615
11642
|
}
|
|
11616
|
-
_Model_computedCache = new WeakMap(), _Model_computedDefs = new WeakMap(), _Model_state = new WeakMap(), _Model_instances = new WeakSet(), _Model_hydrate = async function _Model_hydrate() {
|
|
11617
|
-
ensureUnloadListener(PersistentStorage);
|
|
11618
|
-
try {
|
|
11619
|
-
await this.fetch({ fromStorage: true, promise: true });
|
|
11620
|
-
}
|
|
11621
|
-
finally {
|
|
11622
|
-
__classPrivateFieldSet(this, _Model_state, 'ready', "f");
|
|
11623
|
-
}
|
|
11624
|
-
}, _Model_doAutoSave = function _Model_doAutoSave() {
|
|
11625
|
-
return this.save(null, { noAutoSave: true });
|
|
11626
|
-
}, _Model_updateComputed = function _Model_updateComputed(key, def, silent, options) {
|
|
11627
|
-
const newVal = def.fn(this);
|
|
11628
|
-
if (!isEqual(__classPrivateFieldGet(this, _Model_computedCache, "f")[key], newVal)) {
|
|
11629
|
-
__classPrivateFieldGet(this, _Model_computedCache, "f")[key] = newVal;
|
|
11630
|
-
if (!silent) {
|
|
11631
|
-
this.changed[key] = newVal;
|
|
11632
|
-
this.trigger('change:' + key, this, newVal, options);
|
|
11633
|
-
}
|
|
11634
|
-
}
|
|
11635
|
-
}, _Model_initComputed = function _Model_initComputed() {
|
|
11636
|
-
const defs = result(this, 'computed');
|
|
11637
|
-
if (!defs || isEmpty(defs))
|
|
11638
|
-
return;
|
|
11639
|
-
__classPrivateFieldSet(this, _Model_computedDefs, defs, "f");
|
|
11640
|
-
__classPrivateFieldSet(this, _Model_computedCache, {}, "f");
|
|
11641
|
-
for (const [key, def] of Object.entries(defs)) {
|
|
11642
|
-
__classPrivateFieldGet(this, _Model_computedCache, "f")[key] = def.fn(this);
|
|
11643
|
-
}
|
|
11644
|
-
};
|
|
11645
11643
|
|
|
11646
|
-
var
|
|
11644
|
+
var _a;
|
|
11647
11645
|
// Default options for `Collection#set`.
|
|
11648
11646
|
const setOptions = { add: true, remove: true, merge: true };
|
|
11649
11647
|
const addOptions = { add: true, remove: false };
|
|
@@ -11664,6 +11662,18 @@
|
|
|
11664
11662
|
const matcher = matches(pred);
|
|
11665
11663
|
return (m) => matcher(m.attributes);
|
|
11666
11664
|
}
|
|
11665
|
+
/**
|
|
11666
|
+
* Load the collection's members from storage. A module-level function rather
|
|
11667
|
+
* than a `#private` method so the published declarations carry no private
|
|
11668
|
+
* members, which TypeScript 6 rejects in anonymously extended classes (TS4094).
|
|
11669
|
+
*/
|
|
11670
|
+
async function hydrate(collection) {
|
|
11671
|
+
ensureUnloadListener(PersistentStorage);
|
|
11672
|
+
// An empty store is a normal first-run state: findAll() returns [] and a
|
|
11673
|
+
// missing model record resolves to null, so hydration resolves rather
|
|
11674
|
+
// than rejecting.
|
|
11675
|
+
await collection.fetch({ fromStorage: true, promise: true });
|
|
11676
|
+
}
|
|
11667
11677
|
/**
|
|
11668
11678
|
* @public
|
|
11669
11679
|
* If models tend to represent a single row of data, a Collection is
|
|
@@ -11673,6 +11683,7 @@
|
|
|
11673
11683
|
* belonging to this particular author, and so on. Collections maintain
|
|
11674
11684
|
* indexes of their models, both in order, and for lookup by `id`.
|
|
11675
11685
|
*/
|
|
11686
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging -- see the interface above
|
|
11676
11687
|
class Collection extends EventEmitterObject {
|
|
11677
11688
|
/**
|
|
11678
11689
|
* Create a new **Collection**, perhaps to contain a specific type of `model`.
|
|
@@ -11681,7 +11692,6 @@
|
|
|
11681
11692
|
*/
|
|
11682
11693
|
constructor(models, options) {
|
|
11683
11694
|
super();
|
|
11684
|
-
_Collection_instances.add(this);
|
|
11685
11695
|
this._url = '';
|
|
11686
11696
|
/**
|
|
11687
11697
|
* @public
|
|
@@ -11691,7 +11701,7 @@
|
|
|
11691
11701
|
options = options || {};
|
|
11692
11702
|
this.preinitialize.apply(this, arguments);
|
|
11693
11703
|
if (options.model)
|
|
11694
|
-
this.
|
|
11704
|
+
this.model = options.model;
|
|
11695
11705
|
if (options.comparator !== undefined)
|
|
11696
11706
|
this.comparator = options.comparator;
|
|
11697
11707
|
this._reset();
|
|
@@ -11703,15 +11713,9 @@
|
|
|
11703
11713
|
// uniformly `await collection.hydrated`; it resolves immediately when
|
|
11704
11714
|
// there's no storage to hydrate from.
|
|
11705
11715
|
if (this.autoSync) {
|
|
11706
|
-
this.hydrated = getStorage(this) ?
|
|
11716
|
+
this.hydrated = getStorage(this) ? hydrate(this) : Promise.resolve();
|
|
11707
11717
|
}
|
|
11708
11718
|
}
|
|
11709
|
-
get comparator() {
|
|
11710
|
-
return this._comparator;
|
|
11711
|
-
}
|
|
11712
|
-
set comparator(c) {
|
|
11713
|
-
this._comparator = c;
|
|
11714
|
-
}
|
|
11715
11719
|
/**
|
|
11716
11720
|
* The canonical storage accessor. Set to a `PersistentStorage` instance
|
|
11717
11721
|
* to enable local persistence for this collection.
|
|
@@ -11747,16 +11751,6 @@
|
|
|
11747
11751
|
get autoSync() {
|
|
11748
11752
|
return false;
|
|
11749
11753
|
}
|
|
11750
|
-
/**
|
|
11751
|
-
* The default model for a collection is just a **Model**.
|
|
11752
|
-
* This should be overridden in most cases.
|
|
11753
|
-
*/
|
|
11754
|
-
get model() {
|
|
11755
|
-
return this._model ?? Model;
|
|
11756
|
-
}
|
|
11757
|
-
set model(model) {
|
|
11758
|
-
this._model = model;
|
|
11759
|
-
}
|
|
11760
11754
|
get length() {
|
|
11761
11755
|
return this.models.length;
|
|
11762
11756
|
}
|
|
@@ -12260,7 +12254,7 @@
|
|
|
12260
12254
|
* Define how to uniquely identify models in the collection.
|
|
12261
12255
|
*/
|
|
12262
12256
|
modelId(attrs) {
|
|
12263
|
-
return attrs[this.model.prototype?.idAttribute || 'id'];
|
|
12257
|
+
return attrs[(this.model ?? Model).prototype?.idAttribute || 'id'];
|
|
12264
12258
|
}
|
|
12265
12259
|
/** Get an iterator of all models in this collection. */
|
|
12266
12260
|
values() {
|
|
@@ -12283,7 +12277,7 @@
|
|
|
12283
12277
|
this._byId = {};
|
|
12284
12278
|
}
|
|
12285
12279
|
createModel(attrs, options) {
|
|
12286
|
-
const Klass = this.model;
|
|
12280
|
+
const Klass = this.model ?? Model;
|
|
12287
12281
|
return new Klass(attrs, options);
|
|
12288
12282
|
}
|
|
12289
12283
|
/**
|
|
@@ -12386,13 +12380,7 @@
|
|
|
12386
12380
|
this.trigger.apply(this, arguments);
|
|
12387
12381
|
}
|
|
12388
12382
|
}
|
|
12389
|
-
|
|
12390
|
-
ensureUnloadListener(PersistentStorage);
|
|
12391
|
-
// An empty store is a normal first-run state: findAll() returns [] and a
|
|
12392
|
-
// missing model record resolves to null, so hydration resolves rather
|
|
12393
|
-
// than rejecting.
|
|
12394
|
-
await this.fetch({ fromStorage: true, promise: true });
|
|
12395
|
-
}, _a = Symbol.iterator;
|
|
12383
|
+
_a = Symbol.iterator;
|
|
12396
12384
|
// This "enum" defines the three possible kinds of values which can be emitted
|
|
12397
12385
|
// by a CollectionIterator that correspond to the values(), keys() and entries()
|
|
12398
12386
|
// methods on Collection, respectively.
|