@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.node.js
CHANGED
|
@@ -35,19 +35,6 @@ function __values(o) {
|
|
|
35
35
|
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
39
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
40
|
-
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");
|
|
41
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
45
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
46
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
47
|
-
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");
|
|
48
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
38
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
52
39
|
var e = new Error(message);
|
|
53
40
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
@@ -11161,7 +11148,47 @@ var pick = flatRest(function(object, paths) {
|
|
|
11161
11148
|
return object == null ? {} : basePick(object, paths);
|
|
11162
11149
|
});
|
|
11163
11150
|
|
|
11164
|
-
|
|
11151
|
+
const INTERNALS = new WeakMap();
|
|
11152
|
+
function internals(model) {
|
|
11153
|
+
let priv = INTERNALS.get(model);
|
|
11154
|
+
if (!priv) {
|
|
11155
|
+
priv = { state: 'constructing' };
|
|
11156
|
+
INTERNALS.set(model, priv);
|
|
11157
|
+
}
|
|
11158
|
+
return priv;
|
|
11159
|
+
}
|
|
11160
|
+
/** Load the model from storage, marking it ready whether or not the read succeeds. */
|
|
11161
|
+
async function hydrate$1(model, priv) {
|
|
11162
|
+
ensureUnloadListener(PersistentStorage);
|
|
11163
|
+
try {
|
|
11164
|
+
await model.fetch({ fromStorage: true, promise: true });
|
|
11165
|
+
}
|
|
11166
|
+
finally {
|
|
11167
|
+
priv.state = 'ready';
|
|
11168
|
+
}
|
|
11169
|
+
}
|
|
11170
|
+
/** Evaluate the model's declared computed properties once, seeding the cache. */
|
|
11171
|
+
function initComputed(model, priv) {
|
|
11172
|
+
const defs = result(model, 'computed');
|
|
11173
|
+
if (!defs || isEmpty(defs))
|
|
11174
|
+
return;
|
|
11175
|
+
priv.computedDefs = defs;
|
|
11176
|
+
priv.computedCache = {};
|
|
11177
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
11178
|
+
priv.computedCache[key] = def.fn(model);
|
|
11179
|
+
}
|
|
11180
|
+
}
|
|
11181
|
+
/** Recompute one computed property, firing `change:key` when its value changed. */
|
|
11182
|
+
function updateComputed(model, priv, key, def, silent, options) {
|
|
11183
|
+
const newVal = def.fn(model);
|
|
11184
|
+
if (!isEqual(priv.computedCache[key], newVal)) {
|
|
11185
|
+
priv.computedCache[key] = newVal;
|
|
11186
|
+
if (!silent) {
|
|
11187
|
+
model.changed[key] = newVal;
|
|
11188
|
+
model.trigger('change:' + key, model, newVal, options);
|
|
11189
|
+
}
|
|
11190
|
+
}
|
|
11191
|
+
}
|
|
11165
11192
|
/**
|
|
11166
11193
|
* @public
|
|
11167
11194
|
* **Models** are the basic data object in the framework --
|
|
@@ -11176,15 +11203,12 @@ class Model extends EventEmitterObject {
|
|
|
11176
11203
|
*/
|
|
11177
11204
|
constructor(attributes, options) {
|
|
11178
11205
|
super();
|
|
11179
|
-
_Model_instances.add(this);
|
|
11180
|
-
_Model_computedCache.set(this, void 0);
|
|
11181
|
-
_Model_computedDefs.set(this, void 0);
|
|
11182
|
-
_Model_state.set(this, 'constructing');
|
|
11183
11206
|
this._changing = false;
|
|
11184
11207
|
this._pending = false;
|
|
11185
11208
|
this._url = '';
|
|
11186
11209
|
this.changed = {};
|
|
11187
11210
|
this.validationError = null;
|
|
11211
|
+
const priv = internals(this);
|
|
11188
11212
|
let attrs = attributes || {};
|
|
11189
11213
|
options = options || {};
|
|
11190
11214
|
this.preinitialize.apply(this, arguments);
|
|
@@ -11197,11 +11221,12 @@ class Model extends EventEmitterObject {
|
|
|
11197
11221
|
const default_attrs = result(this, 'defaults');
|
|
11198
11222
|
attrs = defaults(Object.assign({}, default_attrs, attrs), default_attrs);
|
|
11199
11223
|
this.set(attrs, options);
|
|
11200
|
-
|
|
11224
|
+
initComputed(this, priv);
|
|
11201
11225
|
this.attrs = new Proxy(this.attributes, {
|
|
11202
11226
|
get: (_target, key) => {
|
|
11203
|
-
|
|
11204
|
-
|
|
11227
|
+
const cache = priv.computedCache;
|
|
11228
|
+
if (typeof key !== 'symbol' && cache && key in cache) {
|
|
11229
|
+
return cache[key];
|
|
11205
11230
|
}
|
|
11206
11231
|
return this.attributes[key];
|
|
11207
11232
|
},
|
|
@@ -11219,16 +11244,16 @@ class Model extends EventEmitterObject {
|
|
|
11219
11244
|
// otherwise it's already ready and resolves immediately.
|
|
11220
11245
|
if (this.autoSync) {
|
|
11221
11246
|
if (getStorage(this) && !this.isNew()) {
|
|
11222
|
-
|
|
11223
|
-
this.hydrated =
|
|
11247
|
+
priv.state = 'hydrating';
|
|
11248
|
+
this.hydrated = hydrate$1(this, priv);
|
|
11224
11249
|
}
|
|
11225
11250
|
else {
|
|
11226
|
-
|
|
11251
|
+
priv.state = 'ready';
|
|
11227
11252
|
this.hydrated = Promise.resolve();
|
|
11228
11253
|
}
|
|
11229
11254
|
}
|
|
11230
11255
|
else {
|
|
11231
|
-
|
|
11256
|
+
priv.state = 'ready';
|
|
11232
11257
|
}
|
|
11233
11258
|
}
|
|
11234
11259
|
/**
|
|
@@ -11327,8 +11352,9 @@ class Model extends EventEmitterObject {
|
|
|
11327
11352
|
* Get the value of an attribute, or a computed property.
|
|
11328
11353
|
*/
|
|
11329
11354
|
get(attr) {
|
|
11330
|
-
|
|
11331
|
-
|
|
11355
|
+
const cache = internals(this).computedCache;
|
|
11356
|
+
if (cache && attr in cache) {
|
|
11357
|
+
return cache[attr];
|
|
11332
11358
|
}
|
|
11333
11359
|
return this.attributes[attr];
|
|
11334
11360
|
}
|
|
@@ -11404,9 +11430,10 @@ class Model extends EventEmitterObject {
|
|
|
11404
11430
|
attrs[key] = val;
|
|
11405
11431
|
}
|
|
11406
11432
|
options = options || {};
|
|
11433
|
+
const priv = internals(this);
|
|
11407
11434
|
// Guard must come after arg normalization: when called as set(obj, opts),
|
|
11408
11435
|
// fromStorage lives in `val` (second arg), not `options` (third arg).
|
|
11409
|
-
if (this.autoSync &&
|
|
11436
|
+
if (this.autoSync && priv.state === 'hydrating' && !options.fromStorage) {
|
|
11410
11437
|
throw new Error(`Skeletor: set() called on an autoSync model before hydration resolved. Await model.hydrated first.`);
|
|
11411
11438
|
}
|
|
11412
11439
|
// Run validation.
|
|
@@ -11450,10 +11477,10 @@ class Model extends EventEmitterObject {
|
|
|
11450
11477
|
}
|
|
11451
11478
|
}
|
|
11452
11479
|
// Recalculate computed properties whose deps changed.
|
|
11453
|
-
if (changes.length &&
|
|
11454
|
-
for (const [key, def] of Object.entries(
|
|
11480
|
+
if (changes.length && priv.computedDefs) {
|
|
11481
|
+
for (const [key, def] of Object.entries(priv.computedDefs)) {
|
|
11455
11482
|
if (def.deps.some((dep) => changes.includes(dep))) {
|
|
11456
|
-
|
|
11483
|
+
updateComputed(this, priv, key, def, silent, options);
|
|
11457
11484
|
}
|
|
11458
11485
|
}
|
|
11459
11486
|
}
|
|
@@ -11473,13 +11500,13 @@ class Model extends EventEmitterObject {
|
|
|
11473
11500
|
// Auto-save: schedule a debounced write when autoSync is on and there
|
|
11474
11501
|
// were actual changes that originated from application code (not a
|
|
11475
11502
|
// storage read or an explicit noAutoSave call).
|
|
11476
|
-
if (
|
|
11503
|
+
if (priv.state === 'ready' &&
|
|
11477
11504
|
this.autoSync &&
|
|
11478
11505
|
getStorage(this) &&
|
|
11479
11506
|
changes.length &&
|
|
11480
11507
|
!options.fromStorage &&
|
|
11481
11508
|
!options.noAutoSave) {
|
|
11482
|
-
scheduleAutoSave(this, () =>
|
|
11509
|
+
scheduleAutoSave(this, () => this.save(null, { noAutoSave: true }), this.autoSyncDelay);
|
|
11483
11510
|
}
|
|
11484
11511
|
return this;
|
|
11485
11512
|
}
|
|
@@ -11760,37 +11787,8 @@ class Model extends EventEmitterObject {
|
|
|
11760
11787
|
return false;
|
|
11761
11788
|
}
|
|
11762
11789
|
}
|
|
11763
|
-
_Model_computedCache = new WeakMap(), _Model_computedDefs = new WeakMap(), _Model_state = new WeakMap(), _Model_instances = new WeakSet(), _Model_hydrate = async function _Model_hydrate() {
|
|
11764
|
-
ensureUnloadListener(PersistentStorage);
|
|
11765
|
-
try {
|
|
11766
|
-
await this.fetch({ fromStorage: true, promise: true });
|
|
11767
|
-
}
|
|
11768
|
-
finally {
|
|
11769
|
-
__classPrivateFieldSet(this, _Model_state, 'ready', "f");
|
|
11770
|
-
}
|
|
11771
|
-
}, _Model_doAutoSave = function _Model_doAutoSave() {
|
|
11772
|
-
return this.save(null, { noAutoSave: true });
|
|
11773
|
-
}, _Model_updateComputed = function _Model_updateComputed(key, def, silent, options) {
|
|
11774
|
-
const newVal = def.fn(this);
|
|
11775
|
-
if (!isEqual(__classPrivateFieldGet(this, _Model_computedCache, "f")[key], newVal)) {
|
|
11776
|
-
__classPrivateFieldGet(this, _Model_computedCache, "f")[key] = newVal;
|
|
11777
|
-
if (!silent) {
|
|
11778
|
-
this.changed[key] = newVal;
|
|
11779
|
-
this.trigger('change:' + key, this, newVal, options);
|
|
11780
|
-
}
|
|
11781
|
-
}
|
|
11782
|
-
}, _Model_initComputed = function _Model_initComputed() {
|
|
11783
|
-
const defs = result(this, 'computed');
|
|
11784
|
-
if (!defs || isEmpty(defs))
|
|
11785
|
-
return;
|
|
11786
|
-
__classPrivateFieldSet(this, _Model_computedDefs, defs, "f");
|
|
11787
|
-
__classPrivateFieldSet(this, _Model_computedCache, {}, "f");
|
|
11788
|
-
for (const [key, def] of Object.entries(defs)) {
|
|
11789
|
-
__classPrivateFieldGet(this, _Model_computedCache, "f")[key] = def.fn(this);
|
|
11790
|
-
}
|
|
11791
|
-
};
|
|
11792
11790
|
|
|
11793
|
-
var
|
|
11791
|
+
var _a;
|
|
11794
11792
|
// Default options for `Collection#set`.
|
|
11795
11793
|
const setOptions = { add: true, remove: true, merge: true };
|
|
11796
11794
|
const addOptions = { add: true, remove: false };
|
|
@@ -11811,6 +11809,18 @@ function toModelPredicate(pred) {
|
|
|
11811
11809
|
const matcher = matches(pred);
|
|
11812
11810
|
return (m) => matcher(m.attributes);
|
|
11813
11811
|
}
|
|
11812
|
+
/**
|
|
11813
|
+
* Load the collection's members from storage. A module-level function rather
|
|
11814
|
+
* than a `#private` method so the published declarations carry no private
|
|
11815
|
+
* members, which TypeScript 6 rejects in anonymously extended classes (TS4094).
|
|
11816
|
+
*/
|
|
11817
|
+
async function hydrate(collection) {
|
|
11818
|
+
ensureUnloadListener(PersistentStorage);
|
|
11819
|
+
// An empty store is a normal first-run state: findAll() returns [] and a
|
|
11820
|
+
// missing model record resolves to null, so hydration resolves rather
|
|
11821
|
+
// than rejecting.
|
|
11822
|
+
await collection.fetch({ fromStorage: true, promise: true });
|
|
11823
|
+
}
|
|
11814
11824
|
/**
|
|
11815
11825
|
* @public
|
|
11816
11826
|
* If models tend to represent a single row of data, a Collection is
|
|
@@ -11820,6 +11830,7 @@ function toModelPredicate(pred) {
|
|
|
11820
11830
|
* belonging to this particular author, and so on. Collections maintain
|
|
11821
11831
|
* indexes of their models, both in order, and for lookup by `id`.
|
|
11822
11832
|
*/
|
|
11833
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging -- see the interface above
|
|
11823
11834
|
class Collection extends EventEmitterObject {
|
|
11824
11835
|
/**
|
|
11825
11836
|
* Create a new **Collection**, perhaps to contain a specific type of `model`.
|
|
@@ -11828,7 +11839,6 @@ class Collection extends EventEmitterObject {
|
|
|
11828
11839
|
*/
|
|
11829
11840
|
constructor(models, options) {
|
|
11830
11841
|
super();
|
|
11831
|
-
_Collection_instances.add(this);
|
|
11832
11842
|
this._url = '';
|
|
11833
11843
|
/**
|
|
11834
11844
|
* @public
|
|
@@ -11838,7 +11848,7 @@ class Collection extends EventEmitterObject {
|
|
|
11838
11848
|
options = options || {};
|
|
11839
11849
|
this.preinitialize.apply(this, arguments);
|
|
11840
11850
|
if (options.model)
|
|
11841
|
-
this.
|
|
11851
|
+
this.model = options.model;
|
|
11842
11852
|
if (options.comparator !== undefined)
|
|
11843
11853
|
this.comparator = options.comparator;
|
|
11844
11854
|
this._reset();
|
|
@@ -11850,15 +11860,9 @@ class Collection extends EventEmitterObject {
|
|
|
11850
11860
|
// uniformly `await collection.hydrated`; it resolves immediately when
|
|
11851
11861
|
// there's no storage to hydrate from.
|
|
11852
11862
|
if (this.autoSync) {
|
|
11853
|
-
this.hydrated = getStorage(this) ?
|
|
11863
|
+
this.hydrated = getStorage(this) ? hydrate(this) : Promise.resolve();
|
|
11854
11864
|
}
|
|
11855
11865
|
}
|
|
11856
|
-
get comparator() {
|
|
11857
|
-
return this._comparator;
|
|
11858
|
-
}
|
|
11859
|
-
set comparator(c) {
|
|
11860
|
-
this._comparator = c;
|
|
11861
|
-
}
|
|
11862
11866
|
/**
|
|
11863
11867
|
* The canonical storage accessor. Set to a `PersistentStorage` instance
|
|
11864
11868
|
* to enable local persistence for this collection.
|
|
@@ -11894,16 +11898,6 @@ class Collection extends EventEmitterObject {
|
|
|
11894
11898
|
get autoSync() {
|
|
11895
11899
|
return false;
|
|
11896
11900
|
}
|
|
11897
|
-
/**
|
|
11898
|
-
* The default model for a collection is just a **Model**.
|
|
11899
|
-
* This should be overridden in most cases.
|
|
11900
|
-
*/
|
|
11901
|
-
get model() {
|
|
11902
|
-
return this._model ?? Model;
|
|
11903
|
-
}
|
|
11904
|
-
set model(model) {
|
|
11905
|
-
this._model = model;
|
|
11906
|
-
}
|
|
11907
11901
|
get length() {
|
|
11908
11902
|
return this.models.length;
|
|
11909
11903
|
}
|
|
@@ -12407,7 +12401,7 @@ class Collection extends EventEmitterObject {
|
|
|
12407
12401
|
* Define how to uniquely identify models in the collection.
|
|
12408
12402
|
*/
|
|
12409
12403
|
modelId(attrs) {
|
|
12410
|
-
return attrs[this.model.prototype?.idAttribute || 'id'];
|
|
12404
|
+
return attrs[(this.model ?? Model).prototype?.idAttribute || 'id'];
|
|
12411
12405
|
}
|
|
12412
12406
|
/** Get an iterator of all models in this collection. */
|
|
12413
12407
|
values() {
|
|
@@ -12430,7 +12424,7 @@ class Collection extends EventEmitterObject {
|
|
|
12430
12424
|
this._byId = {};
|
|
12431
12425
|
}
|
|
12432
12426
|
createModel(attrs, options) {
|
|
12433
|
-
const Klass = this.model;
|
|
12427
|
+
const Klass = this.model ?? Model;
|
|
12434
12428
|
return new Klass(attrs, options);
|
|
12435
12429
|
}
|
|
12436
12430
|
/**
|
|
@@ -12533,13 +12527,7 @@ class Collection extends EventEmitterObject {
|
|
|
12533
12527
|
this.trigger.apply(this, arguments);
|
|
12534
12528
|
}
|
|
12535
12529
|
}
|
|
12536
|
-
|
|
12537
|
-
ensureUnloadListener(PersistentStorage);
|
|
12538
|
-
// An empty store is a normal first-run state: findAll() returns [] and a
|
|
12539
|
-
// missing model record resolves to null, so hydration resolves rather
|
|
12540
|
-
// than rejecting.
|
|
12541
|
-
await this.fetch({ fromStorage: true, promise: true });
|
|
12542
|
-
}, _a = Symbol.iterator;
|
|
12530
|
+
_a = Symbol.iterator;
|
|
12543
12531
|
// This "enum" defines the three possible kinds of values which can be emitted
|
|
12544
12532
|
// by a CollectionIterator that correspond to the values(), keys() and entries()
|
|
12545
12533
|
// methods on Collection, respectively.
|
package/dist/skeletor.node.mjs
CHANGED
|
@@ -31,19 +31,6 @@ function __values(o) {
|
|
|
31
31
|
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
35
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
36
|
-
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");
|
|
37
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
41
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
42
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
43
|
-
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");
|
|
44
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
34
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
48
35
|
var e = new Error(message);
|
|
49
36
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
@@ -11157,7 +11144,47 @@ var pick = flatRest(function(object, paths) {
|
|
|
11157
11144
|
return object == null ? {} : basePick(object, paths);
|
|
11158
11145
|
});
|
|
11159
11146
|
|
|
11160
|
-
|
|
11147
|
+
const INTERNALS = new WeakMap();
|
|
11148
|
+
function internals(model) {
|
|
11149
|
+
let priv = INTERNALS.get(model);
|
|
11150
|
+
if (!priv) {
|
|
11151
|
+
priv = { state: 'constructing' };
|
|
11152
|
+
INTERNALS.set(model, priv);
|
|
11153
|
+
}
|
|
11154
|
+
return priv;
|
|
11155
|
+
}
|
|
11156
|
+
/** Load the model from storage, marking it ready whether or not the read succeeds. */
|
|
11157
|
+
async function hydrate$1(model, priv) {
|
|
11158
|
+
ensureUnloadListener(PersistentStorage);
|
|
11159
|
+
try {
|
|
11160
|
+
await model.fetch({ fromStorage: true, promise: true });
|
|
11161
|
+
}
|
|
11162
|
+
finally {
|
|
11163
|
+
priv.state = 'ready';
|
|
11164
|
+
}
|
|
11165
|
+
}
|
|
11166
|
+
/** Evaluate the model's declared computed properties once, seeding the cache. */
|
|
11167
|
+
function initComputed(model, priv) {
|
|
11168
|
+
const defs = result(model, 'computed');
|
|
11169
|
+
if (!defs || isEmpty(defs))
|
|
11170
|
+
return;
|
|
11171
|
+
priv.computedDefs = defs;
|
|
11172
|
+
priv.computedCache = {};
|
|
11173
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
11174
|
+
priv.computedCache[key] = def.fn(model);
|
|
11175
|
+
}
|
|
11176
|
+
}
|
|
11177
|
+
/** Recompute one computed property, firing `change:key` when its value changed. */
|
|
11178
|
+
function updateComputed(model, priv, key, def, silent, options) {
|
|
11179
|
+
const newVal = def.fn(model);
|
|
11180
|
+
if (!isEqual(priv.computedCache[key], newVal)) {
|
|
11181
|
+
priv.computedCache[key] = newVal;
|
|
11182
|
+
if (!silent) {
|
|
11183
|
+
model.changed[key] = newVal;
|
|
11184
|
+
model.trigger('change:' + key, model, newVal, options);
|
|
11185
|
+
}
|
|
11186
|
+
}
|
|
11187
|
+
}
|
|
11161
11188
|
/**
|
|
11162
11189
|
* @public
|
|
11163
11190
|
* **Models** are the basic data object in the framework --
|
|
@@ -11172,15 +11199,12 @@ class Model extends EventEmitterObject {
|
|
|
11172
11199
|
*/
|
|
11173
11200
|
constructor(attributes, options) {
|
|
11174
11201
|
super();
|
|
11175
|
-
_Model_instances.add(this);
|
|
11176
|
-
_Model_computedCache.set(this, void 0);
|
|
11177
|
-
_Model_computedDefs.set(this, void 0);
|
|
11178
|
-
_Model_state.set(this, 'constructing');
|
|
11179
11202
|
this._changing = false;
|
|
11180
11203
|
this._pending = false;
|
|
11181
11204
|
this._url = '';
|
|
11182
11205
|
this.changed = {};
|
|
11183
11206
|
this.validationError = null;
|
|
11207
|
+
const priv = internals(this);
|
|
11184
11208
|
let attrs = attributes || {};
|
|
11185
11209
|
options = options || {};
|
|
11186
11210
|
this.preinitialize.apply(this, arguments);
|
|
@@ -11193,11 +11217,12 @@ class Model extends EventEmitterObject {
|
|
|
11193
11217
|
const default_attrs = result(this, 'defaults');
|
|
11194
11218
|
attrs = defaults(Object.assign({}, default_attrs, attrs), default_attrs);
|
|
11195
11219
|
this.set(attrs, options);
|
|
11196
|
-
|
|
11220
|
+
initComputed(this, priv);
|
|
11197
11221
|
this.attrs = new Proxy(this.attributes, {
|
|
11198
11222
|
get: (_target, key) => {
|
|
11199
|
-
|
|
11200
|
-
|
|
11223
|
+
const cache = priv.computedCache;
|
|
11224
|
+
if (typeof key !== 'symbol' && cache && key in cache) {
|
|
11225
|
+
return cache[key];
|
|
11201
11226
|
}
|
|
11202
11227
|
return this.attributes[key];
|
|
11203
11228
|
},
|
|
@@ -11215,16 +11240,16 @@ class Model extends EventEmitterObject {
|
|
|
11215
11240
|
// otherwise it's already ready and resolves immediately.
|
|
11216
11241
|
if (this.autoSync) {
|
|
11217
11242
|
if (getStorage(this) && !this.isNew()) {
|
|
11218
|
-
|
|
11219
|
-
this.hydrated =
|
|
11243
|
+
priv.state = 'hydrating';
|
|
11244
|
+
this.hydrated = hydrate$1(this, priv);
|
|
11220
11245
|
}
|
|
11221
11246
|
else {
|
|
11222
|
-
|
|
11247
|
+
priv.state = 'ready';
|
|
11223
11248
|
this.hydrated = Promise.resolve();
|
|
11224
11249
|
}
|
|
11225
11250
|
}
|
|
11226
11251
|
else {
|
|
11227
|
-
|
|
11252
|
+
priv.state = 'ready';
|
|
11228
11253
|
}
|
|
11229
11254
|
}
|
|
11230
11255
|
/**
|
|
@@ -11323,8 +11348,9 @@ class Model extends EventEmitterObject {
|
|
|
11323
11348
|
* Get the value of an attribute, or a computed property.
|
|
11324
11349
|
*/
|
|
11325
11350
|
get(attr) {
|
|
11326
|
-
|
|
11327
|
-
|
|
11351
|
+
const cache = internals(this).computedCache;
|
|
11352
|
+
if (cache && attr in cache) {
|
|
11353
|
+
return cache[attr];
|
|
11328
11354
|
}
|
|
11329
11355
|
return this.attributes[attr];
|
|
11330
11356
|
}
|
|
@@ -11400,9 +11426,10 @@ class Model extends EventEmitterObject {
|
|
|
11400
11426
|
attrs[key] = val;
|
|
11401
11427
|
}
|
|
11402
11428
|
options = options || {};
|
|
11429
|
+
const priv = internals(this);
|
|
11403
11430
|
// Guard must come after arg normalization: when called as set(obj, opts),
|
|
11404
11431
|
// fromStorage lives in `val` (second arg), not `options` (third arg).
|
|
11405
|
-
if (this.autoSync &&
|
|
11432
|
+
if (this.autoSync && priv.state === 'hydrating' && !options.fromStorage) {
|
|
11406
11433
|
throw new Error(`Skeletor: set() called on an autoSync model before hydration resolved. Await model.hydrated first.`);
|
|
11407
11434
|
}
|
|
11408
11435
|
// Run validation.
|
|
@@ -11446,10 +11473,10 @@ class Model extends EventEmitterObject {
|
|
|
11446
11473
|
}
|
|
11447
11474
|
}
|
|
11448
11475
|
// Recalculate computed properties whose deps changed.
|
|
11449
|
-
if (changes.length &&
|
|
11450
|
-
for (const [key, def] of Object.entries(
|
|
11476
|
+
if (changes.length && priv.computedDefs) {
|
|
11477
|
+
for (const [key, def] of Object.entries(priv.computedDefs)) {
|
|
11451
11478
|
if (def.deps.some((dep) => changes.includes(dep))) {
|
|
11452
|
-
|
|
11479
|
+
updateComputed(this, priv, key, def, silent, options);
|
|
11453
11480
|
}
|
|
11454
11481
|
}
|
|
11455
11482
|
}
|
|
@@ -11469,13 +11496,13 @@ class Model extends EventEmitterObject {
|
|
|
11469
11496
|
// Auto-save: schedule a debounced write when autoSync is on and there
|
|
11470
11497
|
// were actual changes that originated from application code (not a
|
|
11471
11498
|
// storage read or an explicit noAutoSave call).
|
|
11472
|
-
if (
|
|
11499
|
+
if (priv.state === 'ready' &&
|
|
11473
11500
|
this.autoSync &&
|
|
11474
11501
|
getStorage(this) &&
|
|
11475
11502
|
changes.length &&
|
|
11476
11503
|
!options.fromStorage &&
|
|
11477
11504
|
!options.noAutoSave) {
|
|
11478
|
-
scheduleAutoSave(this, () =>
|
|
11505
|
+
scheduleAutoSave(this, () => this.save(null, { noAutoSave: true }), this.autoSyncDelay);
|
|
11479
11506
|
}
|
|
11480
11507
|
return this;
|
|
11481
11508
|
}
|
|
@@ -11756,37 +11783,8 @@ class Model extends EventEmitterObject {
|
|
|
11756
11783
|
return false;
|
|
11757
11784
|
}
|
|
11758
11785
|
}
|
|
11759
|
-
_Model_computedCache = new WeakMap(), _Model_computedDefs = new WeakMap(), _Model_state = new WeakMap(), _Model_instances = new WeakSet(), _Model_hydrate = async function _Model_hydrate() {
|
|
11760
|
-
ensureUnloadListener(PersistentStorage);
|
|
11761
|
-
try {
|
|
11762
|
-
await this.fetch({ fromStorage: true, promise: true });
|
|
11763
|
-
}
|
|
11764
|
-
finally {
|
|
11765
|
-
__classPrivateFieldSet(this, _Model_state, 'ready', "f");
|
|
11766
|
-
}
|
|
11767
|
-
}, _Model_doAutoSave = function _Model_doAutoSave() {
|
|
11768
|
-
return this.save(null, { noAutoSave: true });
|
|
11769
|
-
}, _Model_updateComputed = function _Model_updateComputed(key, def, silent, options) {
|
|
11770
|
-
const newVal = def.fn(this);
|
|
11771
|
-
if (!isEqual(__classPrivateFieldGet(this, _Model_computedCache, "f")[key], newVal)) {
|
|
11772
|
-
__classPrivateFieldGet(this, _Model_computedCache, "f")[key] = newVal;
|
|
11773
|
-
if (!silent) {
|
|
11774
|
-
this.changed[key] = newVal;
|
|
11775
|
-
this.trigger('change:' + key, this, newVal, options);
|
|
11776
|
-
}
|
|
11777
|
-
}
|
|
11778
|
-
}, _Model_initComputed = function _Model_initComputed() {
|
|
11779
|
-
const defs = result(this, 'computed');
|
|
11780
|
-
if (!defs || isEmpty(defs))
|
|
11781
|
-
return;
|
|
11782
|
-
__classPrivateFieldSet(this, _Model_computedDefs, defs, "f");
|
|
11783
|
-
__classPrivateFieldSet(this, _Model_computedCache, {}, "f");
|
|
11784
|
-
for (const [key, def] of Object.entries(defs)) {
|
|
11785
|
-
__classPrivateFieldGet(this, _Model_computedCache, "f")[key] = def.fn(this);
|
|
11786
|
-
}
|
|
11787
|
-
};
|
|
11788
11786
|
|
|
11789
|
-
var
|
|
11787
|
+
var _a;
|
|
11790
11788
|
// Default options for `Collection#set`.
|
|
11791
11789
|
const setOptions = { add: true, remove: true, merge: true };
|
|
11792
11790
|
const addOptions = { add: true, remove: false };
|
|
@@ -11807,6 +11805,18 @@ function toModelPredicate(pred) {
|
|
|
11807
11805
|
const matcher = matches(pred);
|
|
11808
11806
|
return (m) => matcher(m.attributes);
|
|
11809
11807
|
}
|
|
11808
|
+
/**
|
|
11809
|
+
* Load the collection's members from storage. A module-level function rather
|
|
11810
|
+
* than a `#private` method so the published declarations carry no private
|
|
11811
|
+
* members, which TypeScript 6 rejects in anonymously extended classes (TS4094).
|
|
11812
|
+
*/
|
|
11813
|
+
async function hydrate(collection) {
|
|
11814
|
+
ensureUnloadListener(PersistentStorage);
|
|
11815
|
+
// An empty store is a normal first-run state: findAll() returns [] and a
|
|
11816
|
+
// missing model record resolves to null, so hydration resolves rather
|
|
11817
|
+
// than rejecting.
|
|
11818
|
+
await collection.fetch({ fromStorage: true, promise: true });
|
|
11819
|
+
}
|
|
11810
11820
|
/**
|
|
11811
11821
|
* @public
|
|
11812
11822
|
* If models tend to represent a single row of data, a Collection is
|
|
@@ -11816,6 +11826,7 @@ function toModelPredicate(pred) {
|
|
|
11816
11826
|
* belonging to this particular author, and so on. Collections maintain
|
|
11817
11827
|
* indexes of their models, both in order, and for lookup by `id`.
|
|
11818
11828
|
*/
|
|
11829
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging -- see the interface above
|
|
11819
11830
|
class Collection extends EventEmitterObject {
|
|
11820
11831
|
/**
|
|
11821
11832
|
* Create a new **Collection**, perhaps to contain a specific type of `model`.
|
|
@@ -11824,7 +11835,6 @@ class Collection extends EventEmitterObject {
|
|
|
11824
11835
|
*/
|
|
11825
11836
|
constructor(models, options) {
|
|
11826
11837
|
super();
|
|
11827
|
-
_Collection_instances.add(this);
|
|
11828
11838
|
this._url = '';
|
|
11829
11839
|
/**
|
|
11830
11840
|
* @public
|
|
@@ -11834,7 +11844,7 @@ class Collection extends EventEmitterObject {
|
|
|
11834
11844
|
options = options || {};
|
|
11835
11845
|
this.preinitialize.apply(this, arguments);
|
|
11836
11846
|
if (options.model)
|
|
11837
|
-
this.
|
|
11847
|
+
this.model = options.model;
|
|
11838
11848
|
if (options.comparator !== undefined)
|
|
11839
11849
|
this.comparator = options.comparator;
|
|
11840
11850
|
this._reset();
|
|
@@ -11846,15 +11856,9 @@ class Collection extends EventEmitterObject {
|
|
|
11846
11856
|
// uniformly `await collection.hydrated`; it resolves immediately when
|
|
11847
11857
|
// there's no storage to hydrate from.
|
|
11848
11858
|
if (this.autoSync) {
|
|
11849
|
-
this.hydrated = getStorage(this) ?
|
|
11859
|
+
this.hydrated = getStorage(this) ? hydrate(this) : Promise.resolve();
|
|
11850
11860
|
}
|
|
11851
11861
|
}
|
|
11852
|
-
get comparator() {
|
|
11853
|
-
return this._comparator;
|
|
11854
|
-
}
|
|
11855
|
-
set comparator(c) {
|
|
11856
|
-
this._comparator = c;
|
|
11857
|
-
}
|
|
11858
11862
|
/**
|
|
11859
11863
|
* The canonical storage accessor. Set to a `PersistentStorage` instance
|
|
11860
11864
|
* to enable local persistence for this collection.
|
|
@@ -11890,16 +11894,6 @@ class Collection extends EventEmitterObject {
|
|
|
11890
11894
|
get autoSync() {
|
|
11891
11895
|
return false;
|
|
11892
11896
|
}
|
|
11893
|
-
/**
|
|
11894
|
-
* The default model for a collection is just a **Model**.
|
|
11895
|
-
* This should be overridden in most cases.
|
|
11896
|
-
*/
|
|
11897
|
-
get model() {
|
|
11898
|
-
return this._model ?? Model;
|
|
11899
|
-
}
|
|
11900
|
-
set model(model) {
|
|
11901
|
-
this._model = model;
|
|
11902
|
-
}
|
|
11903
11897
|
get length() {
|
|
11904
11898
|
return this.models.length;
|
|
11905
11899
|
}
|
|
@@ -12403,7 +12397,7 @@ class Collection extends EventEmitterObject {
|
|
|
12403
12397
|
* Define how to uniquely identify models in the collection.
|
|
12404
12398
|
*/
|
|
12405
12399
|
modelId(attrs) {
|
|
12406
|
-
return attrs[this.model.prototype?.idAttribute || 'id'];
|
|
12400
|
+
return attrs[(this.model ?? Model).prototype?.idAttribute || 'id'];
|
|
12407
12401
|
}
|
|
12408
12402
|
/** Get an iterator of all models in this collection. */
|
|
12409
12403
|
values() {
|
|
@@ -12426,7 +12420,7 @@ class Collection extends EventEmitterObject {
|
|
|
12426
12420
|
this._byId = {};
|
|
12427
12421
|
}
|
|
12428
12422
|
createModel(attrs, options) {
|
|
12429
|
-
const Klass = this.model;
|
|
12423
|
+
const Klass = this.model ?? Model;
|
|
12430
12424
|
return new Klass(attrs, options);
|
|
12431
12425
|
}
|
|
12432
12426
|
/**
|
|
@@ -12529,13 +12523,7 @@ class Collection extends EventEmitterObject {
|
|
|
12529
12523
|
this.trigger.apply(this, arguments);
|
|
12530
12524
|
}
|
|
12531
12525
|
}
|
|
12532
|
-
|
|
12533
|
-
ensureUnloadListener(PersistentStorage);
|
|
12534
|
-
// An empty store is a normal first-run state: findAll() returns [] and a
|
|
12535
|
-
// missing model record resolves to null, so hydration resolves rather
|
|
12536
|
-
// than rejecting.
|
|
12537
|
-
await this.fetch({ fromStorage: true, promise: true });
|
|
12538
|
-
}, _a = Symbol.iterator;
|
|
12526
|
+
_a = Symbol.iterator;
|
|
12539
12527
|
// This "enum" defines the three possible kinds of values which can be emitted
|
|
12540
12528
|
// by a CollectionIterator that correspond to the values(), keys() and entries()
|
|
12541
12529
|
// methods on Collection, respectively.
|