@converse/skeletor 4.0.1 → 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/package.json CHANGED
@@ -39,19 +39,20 @@
39
39
  "contributors": [
40
40
  "JC Brand"
41
41
  ],
42
- "version": "4.0.1",
42
+ "version": "4.0.2",
43
43
  "engines": {
44
44
  "node": ">=22.0.0"
45
45
  },
46
46
  "license": "MIT",
47
47
  "repository": {
48
48
  "type": "git",
49
- "url": "https://github.com/conversejs/skeletor.git"
49
+ "url": "git+https://github.com/conversejs/skeletor.git"
50
50
  },
51
51
  "scripts": {
52
52
  "build": "npm run clean && rollup -c",
53
53
  "check": "npm run check:types && npm run test && npm run test:node && npm run lint",
54
54
  "check:types": "tsc --noEmit",
55
+ "check:dts": "tsc -p tsconfig.dts.json",
55
56
  "clean": "rm -rf dist",
56
57
  "dev": "karma start --single-run=false",
57
58
  "lint": "eslint src/*.ts test/*.ts",
@@ -86,12 +87,6 @@
86
87
  "tslib": "^2.8.1"
87
88
  },
88
89
  "devDependencies": {
89
- "@babel/core": "^7.10.2",
90
- "@babel/plugin-external-helpers": "^7.10.1",
91
- "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
92
- "@babel/plugin-proposal-optional-chaining": "^7.13.12",
93
- "@babel/preset-env": "^7.9.5",
94
- "@rollup/plugin-babel": "^6.0.4",
95
90
  "@rollup/plugin-commonjs": "^28.0.3",
96
91
  "@rollup/plugin-node-resolve": "^16.0.1",
97
92
  "@rollup/plugin-terser": "^1.0.0",
@@ -103,8 +98,6 @@
103
98
  "@types/sinon": "^17.0.4",
104
99
  "@typescript-eslint/eslint-plugin": "^8.29.0",
105
100
  "@typescript-eslint/parser": "^8.29.0",
106
- "babel-eslint": "^10.1.0",
107
- "babel-loader": "^9.2.1",
108
101
  "chai": "^4.2.0",
109
102
  "eslint": "^8.57.0",
110
103
  "karma": "^6.3.16",
package/src/collection.ts CHANGED
@@ -65,6 +65,23 @@ async function hydrate(collection: Collection<any>): Promise<void> {
65
65
  await collection.fetch({ fromStorage: true, promise: true });
66
66
  }
67
67
 
68
+ /**
69
+ * `model` and `comparator` are declared on an interface merged with the class
70
+ * rather than on the class itself, so that subclasses may override them either
71
+ * as instance properties (`model = Contact`) or as accessors (`get model()`).
72
+ * TypeScript rejects the one form overriding the other (TS2610, TS2611) only
73
+ * when the base member is declared on a class.
74
+ */
75
+ export interface Collection<T extends Model = Model> {
76
+ /**
77
+ * The model class to instantiate when raw attributes are added. Defaults to
78
+ * `Model` when unset. Typed loosely so that model classes whose constructors
79
+ * take required or narrower attributes and options fit.
80
+ */
81
+ model: new (attributes?: any, options?: any) => T;
82
+ comparator: Comparator<T>;
83
+ }
84
+
68
85
  /**
69
86
  * @public
70
87
  * If models tend to represent a single row of data, a Collection is
@@ -74,15 +91,14 @@ async function hydrate(collection: Collection<any>): Promise<void> {
74
91
  * belonging to this particular author, and so on. Collections maintain
75
92
  * indexes of their models, both in order, and for lookup by `id`.
76
93
  */
94
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging -- see the interface above
77
95
  export class Collection<T extends Model = Model> extends EventEmitterObject {
78
96
  [key: symbol]: () => CollectionIterator<T>;
79
97
  _storage?: PersistentStorage;
80
- _comparator?: Comparator<T>;
81
98
  _url: string = '';
82
99
  hydrated?: Promise<void>;
83
100
  models: T[];
84
101
  protected _byId: Record<string, T>;
85
- protected _model?: new (attributes?: Partial<ModelAttributes>, options?: ModelOptions) => T;
86
102
 
87
103
  /**
88
104
  * Create a new **Collection**, perhaps to contain a specific type of `model`.
@@ -93,7 +109,7 @@ export class Collection<T extends Model = Model> extends EventEmitterObject {
93
109
  super();
94
110
  options = options || {};
95
111
  this.preinitialize.apply(this, arguments as any);
96
- if (options.model) this._model = options.model;
112
+ if (options.model) this.model = options.model;
97
113
  if (options.comparator !== undefined) this.comparator = options.comparator;
98
114
  this._reset();
99
115
  this.initialize.apply(this, arguments as any);
@@ -108,14 +124,6 @@ export class Collection<T extends Model = Model> extends EventEmitterObject {
108
124
  }
109
125
  }
110
126
 
111
- get comparator(): Comparator<T> {
112
- return this._comparator;
113
- }
114
-
115
- set comparator(c: Comparator<T>) {
116
- this._comparator = c;
117
- }
118
-
119
127
  /**
120
128
  * The canonical storage accessor. Set to a `PersistentStorage` instance
121
129
  * to enable local persistence for this collection.
@@ -156,18 +164,6 @@ export class Collection<T extends Model = Model> extends EventEmitterObject {
156
164
  return false;
157
165
  }
158
166
 
159
- /**
160
- * The default model for a collection is just a **Model**.
161
- * This should be overridden in most cases.
162
- */
163
- get model(): new (attributes?: Partial<ModelAttributes>, options?: ModelOptions) => T | Model {
164
- return this._model ?? Model;
165
- }
166
-
167
- set model(model: new (attributes?: Partial<ModelAttributes>, options?: ModelOptions) => T) {
168
- this._model = model;
169
- }
170
-
171
167
  get length(): number {
172
168
  return this.models.length;
173
169
  }
@@ -745,7 +741,7 @@ export class Collection<T extends Model = Model> extends EventEmitterObject {
745
741
  * Define how to uniquely identify models in the collection.
746
742
  */
747
743
  modelId(attrs: ModelAttributes): string | number | undefined {
748
- return attrs[this.model.prototype?.idAttribute || 'id'];
744
+ return attrs[(this.model ?? Model).prototype?.idAttribute || 'id'];
749
745
  }
750
746
 
751
747
  /** Get an iterator of all models in this collection. */
@@ -779,7 +775,7 @@ export class Collection<T extends Model = Model> extends EventEmitterObject {
779
775
  }
780
776
 
781
777
  createModel(attrs: ModelAttributes, options?: Options): T {
782
- const Klass = this.model;
778
+ const Klass = this.model ?? Model;
783
779
  return new Klass(attrs, options) as T;
784
780
  }
785
781
 
package/src/types.ts CHANGED
@@ -62,10 +62,7 @@ export type EventListenerMap = Record<string, ListeningType>;
62
62
  /**
63
63
  * @public
64
64
  */
65
- export interface EventHandlersMap {
66
- all?: EventHandler[];
67
- [name: string]: EventHandler[];
68
- }
65
+ export type EventHandlersMap = Record<string, EventHandler[]>;
69
66
 
70
67
  /**
71
68
  * @public
@@ -168,7 +165,9 @@ export type IterateeFunction = (
168
165
  */
169
166
  export type ComputedProperty<M> = {
170
167
  deps: string[];
171
- fn: (model: M) => any;
168
+ // Method syntax, so that TypeScript checks `fn` bivariantly and
169
+ // `ComputedProperties<Subclass>` stays assignable to `ComputedProperties<Model>`.
170
+ fn(model: M): any;
172
171
  };
173
172
 
174
173
  /**
@@ -198,7 +197,7 @@ export type FetchOrCreateOptions = Options & {
198
197
  * @public
199
198
  */
200
199
  export type CollectionOptions<T extends Model = Model> = Options & {
201
- model?: new (attributes?: Partial<ModelAttributes>, options?: ModelOptions) => T;
200
+ model?: new (attributes?: any, options?: any) => T;
202
201
  comparator?: Comparator<T>;
203
202
  previousModels?: Model[];
204
203
  };