@expressive/mvc 0.41.0 → 0.43.0
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/dist/index.d.ts +28 -19
- package/dist/index.js +49 -28
- package/dist/index.mjs +49 -28
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,19 +2,30 @@ declare namespace Model {
|
|
|
2
2
|
/** Any type of Model, using own class constructor as its identifier. */
|
|
3
3
|
type Type<T extends Model = Model> = abstract new (...args: any[]) => T;
|
|
4
4
|
/** A type of Model which may be created without constructor arguments. */
|
|
5
|
-
type New<T extends Model = Model> = (new () => T) & typeof Model;
|
|
5
|
+
type New<T extends Model = Model> = (new (arg?: Argument) => T) & typeof Model;
|
|
6
|
+
/**
|
|
7
|
+
* Model constructor callback - is called when Model finishes intializing.
|
|
8
|
+
* Returned function will call when model is destroyed.
|
|
9
|
+
*/
|
|
10
|
+
type Callback<T extends Model = Model> = (this: T, thisArg: T) => (() => void) | Assign<T> | void;
|
|
11
|
+
/** Model constructor argument */
|
|
12
|
+
type Argument<T extends Model = Model> = string | Callback<T> | Assign<T> | undefined;
|
|
6
13
|
/** Subset of `keyof T` which are not methods or defined by base Model U. **/
|
|
7
14
|
type Field<T> = Exclude<keyof T, keyof Model>;
|
|
8
15
|
/** Any valid key for controller, including but not limited to Field<T>. */
|
|
9
|
-
type
|
|
16
|
+
type Event<T> = Field<T> | (string & {}) | number | symbol;
|
|
17
|
+
/** Object overlay which may be used to override values and methods while creating model. */
|
|
18
|
+
type Assign<T> = {
|
|
19
|
+
[K in Exclude<keyof T, keyof Model>]?: T[K] extends (...args: any[]) => infer R ? (this: T, ...args: Parameters<T[K]>) => ReturnType<T[K]> : T[K];
|
|
20
|
+
} & Record<string, unknown>;
|
|
10
21
|
/** Export/Import compatible value for a given property in a Model. */
|
|
11
22
|
type Export<R> = R extends {
|
|
12
23
|
get(): infer T;
|
|
13
24
|
} ? T : R;
|
|
14
25
|
/** Value for a property managed by a controller. */
|
|
15
|
-
type Value<T extends Model, K extends
|
|
26
|
+
type Value<T extends Model, K extends Event<T>> = K extends keyof T ? Export<T[K]> : unknown;
|
|
16
27
|
type OnEvent<T extends Model> = (this: T, key: unknown, source: T) => (() => void) | void | null;
|
|
17
|
-
type OnUpdate<T extends Model, K extends
|
|
28
|
+
type OnUpdate<T extends Model, K extends Event<T>> = (this: T, value: Value<T, K>, key: K, thisArg: K) => void;
|
|
18
29
|
/**
|
|
19
30
|
* Values from current state of given controller.
|
|
20
31
|
* Differs from `Values` as values here will drill
|
|
@@ -42,7 +53,7 @@ declare namespace Model {
|
|
|
42
53
|
*
|
|
43
54
|
* @returns A callback function which will be called when this effect is stale.
|
|
44
55
|
*/
|
|
45
|
-
type Effect<T> = (this: T, current: T, update: Set<
|
|
56
|
+
type Effect<T> = (this: T, current: T, update: Set<Event<T>>) => EffectCallback | Promise<void> | null | void;
|
|
46
57
|
/**
|
|
47
58
|
* A callback function returned by effect. Will be called when effect is stale.
|
|
48
59
|
*
|
|
@@ -63,14 +74,7 @@ declare namespace Model {
|
|
|
63
74
|
* Property initializer, will run upon instance creation.
|
|
64
75
|
* Optional returned callback will run when once upon first access.
|
|
65
76
|
*/
|
|
66
|
-
type Instruction<T = any, M extends Model = any> = (this: M, key:
|
|
67
|
-
/**
|
|
68
|
-
* Model constructor callback - is called when Model finishes intializing.
|
|
69
|
-
* Returned function will call when model is destroyed.
|
|
70
|
-
*/
|
|
71
|
-
type Callback = (() => void | (() => void));
|
|
72
|
-
/** Model constructor argument */
|
|
73
|
-
type Argument = string | Callback;
|
|
77
|
+
type Instruction<T = any, M extends Model = any> = (this: M, key: Field<M> & string, thisArg: M, state: State<M>) => Instruction.Descriptor<T> | Instruction.Getter<T> | void;
|
|
74
78
|
}
|
|
75
79
|
interface Model {
|
|
76
80
|
/**
|
|
@@ -99,14 +103,14 @@ declare class Model {
|
|
|
99
103
|
* @param key - Property to get value of.
|
|
100
104
|
* @param required - If true, will throw an error if property is not available.
|
|
101
105
|
*/
|
|
102
|
-
get<T extends Model.
|
|
106
|
+
get<T extends Model.Event<this>>(key: T, required?: boolean): Model.Value<this, T>;
|
|
103
107
|
/**
|
|
104
108
|
* Run a function when a property is updated.
|
|
105
109
|
*
|
|
106
110
|
* @param key - Property to watch for updates.
|
|
107
111
|
* @param callback - Function to call when property is updated.
|
|
108
112
|
*/
|
|
109
|
-
get<T extends Model.
|
|
113
|
+
get<T extends Model.Event<this>>(key: T, callback: Model.OnUpdate<this, T>): () => void;
|
|
110
114
|
/**
|
|
111
115
|
* Check if model is expired.
|
|
112
116
|
*
|
|
@@ -125,7 +129,7 @@ declare class Model {
|
|
|
125
129
|
*
|
|
126
130
|
* @returns Promise which resolves object with updated values. Is `undefined` if there is no update.
|
|
127
131
|
**/
|
|
128
|
-
set(): PromiseLike<Model.
|
|
132
|
+
set(): PromiseLike<Model.Event<this>[]> | undefined;
|
|
129
133
|
/**
|
|
130
134
|
* Call a function when update occurs.
|
|
131
135
|
*
|
|
@@ -158,7 +162,12 @@ declare class Model {
|
|
|
158
162
|
* @param key - Property or event to dispatch.
|
|
159
163
|
* @returns Promise which resolves an array of keys which were updated.
|
|
160
164
|
*/
|
|
161
|
-
set(key: Model.
|
|
165
|
+
set(key: Model.Event<this>): PromiseLike<Model.Event<this>[]>;
|
|
166
|
+
/**
|
|
167
|
+
* Update mulitple properties at once. Merges argument with current state.
|
|
168
|
+
* Properties which are not managed by this controller will be ignored.
|
|
169
|
+
*/
|
|
170
|
+
set(assign: Model.Assign<this>): PromiseLike<Model.Event<this>[]> | undefined;
|
|
162
171
|
/**
|
|
163
172
|
* Update a property with value.
|
|
164
173
|
*
|
|
@@ -166,7 +175,7 @@ declare class Model {
|
|
|
166
175
|
* @param value - value to update property with (if the same as current, no update will occur)
|
|
167
176
|
* @param silent - if true, will not notify listeners of an update
|
|
168
177
|
*/
|
|
169
|
-
set<K extends string>(key: K, value?: Model.Value<this, K>, silent?: boolean): PromiseLike<Model.
|
|
178
|
+
set<K extends string>(key: K, value?: Model.Value<this, K>, silent?: boolean): PromiseLike<Model.Event<this>[]> | undefined;
|
|
170
179
|
/** Iterate over managed properties in this instance of Model. */
|
|
171
180
|
[Symbol.iterator](): Iterator<[string, unknown]>;
|
|
172
181
|
/**
|
|
@@ -176,7 +185,7 @@ declare class Model {
|
|
|
176
185
|
*
|
|
177
186
|
* @param args - arguments sent to constructor
|
|
178
187
|
*/
|
|
179
|
-
static new<T extends
|
|
188
|
+
static new<T extends Model>(this: Model.New<T>, arg?: Model.Argument<T>): T;
|
|
180
189
|
/**
|
|
181
190
|
* Static equivalent of `x instanceof this`.
|
|
182
191
|
* Determines if provided class is a subtype of this one.
|
package/dist/index.js
CHANGED
|
@@ -149,7 +149,7 @@ function effect(target, callback) {
|
|
|
149
149
|
|
|
150
150
|
// src/model.ts
|
|
151
151
|
var FLATTEN;
|
|
152
|
-
var
|
|
152
|
+
var NAMES = /* @__PURE__ */ new WeakMap();
|
|
153
153
|
var STATE = /* @__PURE__ */ new WeakMap();
|
|
154
154
|
var NOTIFY = /* @__PURE__ */ new WeakMap();
|
|
155
155
|
var PENDING2 = /* @__PURE__ */ new WeakMap();
|
|
@@ -160,33 +160,20 @@ var Model = class _Model {
|
|
|
160
160
|
constructor(arg) {
|
|
161
161
|
const state = {};
|
|
162
162
|
let Type = this.constructor;
|
|
163
|
+
bind(Type);
|
|
163
164
|
define(this, "is", { value: this });
|
|
164
165
|
STATE.set(this, state);
|
|
165
|
-
|
|
166
|
+
NAMES.set(this, typeof arg == "string" ? arg : `${Type}-${uid()}`);
|
|
166
167
|
while (true) {
|
|
167
168
|
new Set(NOTIFY.get(Type)).forEach((x) => addListener(this, x));
|
|
168
169
|
if (Type === _Model)
|
|
169
170
|
break;
|
|
170
|
-
const desc = Object.getOwnPropertyDescriptors(Type.prototype);
|
|
171
|
-
for (const key in desc) {
|
|
172
|
-
let { value } = desc[key];
|
|
173
|
-
if (typeof value == "function" && key !== "constructor")
|
|
174
|
-
Object.defineProperty(Type.prototype, key, {
|
|
175
|
-
get() {
|
|
176
|
-
const method = value.bind(this.is);
|
|
177
|
-
METHOD.set(method, value);
|
|
178
|
-
define(this.is, key, {
|
|
179
|
-
value: method,
|
|
180
|
-
configurable: false
|
|
181
|
-
});
|
|
182
|
-
return method;
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
171
|
Type = Object.getPrototypeOf(Type);
|
|
187
172
|
}
|
|
188
173
|
addListener(this, () => {
|
|
189
|
-
|
|
174
|
+
const apply = typeof arg == "function" ? arg.call(this, this) : arg;
|
|
175
|
+
if (typeof apply == "object")
|
|
176
|
+
assign(this, apply);
|
|
190
177
|
for (const key in this) {
|
|
191
178
|
const desc = Object.getOwnPropertyDescriptor(this, key);
|
|
192
179
|
if ("value" in desc) {
|
|
@@ -200,14 +187,12 @@ var Model = class _Model {
|
|
|
200
187
|
});
|
|
201
188
|
}
|
|
202
189
|
}
|
|
203
|
-
if (typeof arg == "function")
|
|
204
|
-
onDone = arg();
|
|
205
190
|
addListener(this, () => {
|
|
206
191
|
for (const [_, value] of this)
|
|
207
192
|
if (value instanceof _Model && PARENT.get(value) === this)
|
|
208
193
|
value.set(null);
|
|
209
|
-
if (typeof
|
|
210
|
-
|
|
194
|
+
if (typeof apply == "function")
|
|
195
|
+
apply();
|
|
211
196
|
Object.freeze(state);
|
|
212
197
|
}, null);
|
|
213
198
|
return null;
|
|
@@ -261,7 +246,9 @@ var Model = class _Model {
|
|
|
261
246
|
});
|
|
262
247
|
if (arg1 === null)
|
|
263
248
|
return event(this, null);
|
|
264
|
-
if (arg1
|
|
249
|
+
if (typeof arg1 == "object")
|
|
250
|
+
assign(self, arg1);
|
|
251
|
+
else if (arg1 !== void 0)
|
|
265
252
|
if (1 in arguments)
|
|
266
253
|
update(self, arg1, arg2, arg3);
|
|
267
254
|
else
|
|
@@ -289,8 +276,8 @@ var Model = class _Model {
|
|
|
289
276
|
*
|
|
290
277
|
* @param args - arguments sent to constructor
|
|
291
278
|
*/
|
|
292
|
-
static new(
|
|
293
|
-
const instance = new this(
|
|
279
|
+
static new(arg) {
|
|
280
|
+
const instance = new this(arg);
|
|
294
281
|
event(instance, true);
|
|
295
282
|
return instance;
|
|
296
283
|
}
|
|
@@ -319,7 +306,7 @@ var Model = class _Model {
|
|
|
319
306
|
};
|
|
320
307
|
define(Model.prototype, "toString", {
|
|
321
308
|
value() {
|
|
322
|
-
return
|
|
309
|
+
return NAMES.get(this.is);
|
|
323
310
|
}
|
|
324
311
|
});
|
|
325
312
|
define(Model, "toString", {
|
|
@@ -377,6 +364,40 @@ function push(subject, key, silent) {
|
|
|
377
364
|
if (!silent)
|
|
378
365
|
event(subject, key);
|
|
379
366
|
}
|
|
367
|
+
var METHODS = new WeakMap([[Model, []]]);
|
|
368
|
+
function assign(to, values) {
|
|
369
|
+
const methods = METHODS.get(to.constructor);
|
|
370
|
+
const applicable = new Set(Object.keys(to).concat(methods));
|
|
371
|
+
for (const key in values)
|
|
372
|
+
if (applicable.has(key))
|
|
373
|
+
to[key] = values[key];
|
|
374
|
+
}
|
|
375
|
+
function bind(type) {
|
|
376
|
+
let keys = METHODS.get(type);
|
|
377
|
+
if (!keys) {
|
|
378
|
+
METHODS.set(type, keys = bind2(Object.getPrototypeOf(type)).slice());
|
|
379
|
+
const desc = Object.getOwnPropertyDescriptors(type.prototype);
|
|
380
|
+
for (const key in desc)
|
|
381
|
+
if (key != "constructor" && "value" in desc[key]) {
|
|
382
|
+
let bind3 = function(method) {
|
|
383
|
+
const value2 = method.bind(this.is);
|
|
384
|
+
METHOD.set(value2, method);
|
|
385
|
+
define(this.is, key, { value: value2, writable: true });
|
|
386
|
+
return value2;
|
|
387
|
+
};
|
|
388
|
+
var bind2 = bind3;
|
|
389
|
+
let { value } = desc[key];
|
|
390
|
+
keys.push(key);
|
|
391
|
+
Object.defineProperty(type.prototype, key, {
|
|
392
|
+
set: bind3,
|
|
393
|
+
get() {
|
|
394
|
+
return this.hasOwnProperty(key) ? value : bind3.call(this, value);
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return keys;
|
|
400
|
+
}
|
|
380
401
|
function uid() {
|
|
381
402
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
382
403
|
}
|
|
@@ -802,12 +823,12 @@ function has(type, argument) {
|
|
|
802
823
|
return add((key, subject, state) => {
|
|
803
824
|
if (typeof argument == "boolean") {
|
|
804
825
|
Context.request(type, subject, (model) => {
|
|
826
|
+
subject.set(key, model);
|
|
805
827
|
const remove = () => {
|
|
806
828
|
drop();
|
|
807
829
|
if (state[key] === model)
|
|
808
830
|
delete state[key];
|
|
809
831
|
};
|
|
810
|
-
subject.set(key, model);
|
|
811
832
|
const drop = model.get(null, remove);
|
|
812
833
|
return remove;
|
|
813
834
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -115,7 +115,7 @@ function effect(target, callback) {
|
|
|
115
115
|
|
|
116
116
|
// src/model.ts
|
|
117
117
|
var FLATTEN;
|
|
118
|
-
var
|
|
118
|
+
var NAMES = /* @__PURE__ */ new WeakMap();
|
|
119
119
|
var STATE = /* @__PURE__ */ new WeakMap();
|
|
120
120
|
var NOTIFY = /* @__PURE__ */ new WeakMap();
|
|
121
121
|
var PENDING2 = /* @__PURE__ */ new WeakMap();
|
|
@@ -126,33 +126,20 @@ var Model = class _Model {
|
|
|
126
126
|
constructor(arg) {
|
|
127
127
|
const state = {};
|
|
128
128
|
let Type = this.constructor;
|
|
129
|
+
bind(Type);
|
|
129
130
|
define(this, "is", { value: this });
|
|
130
131
|
STATE.set(this, state);
|
|
131
|
-
|
|
132
|
+
NAMES.set(this, typeof arg == "string" ? arg : `${Type}-${uid()}`);
|
|
132
133
|
while (true) {
|
|
133
134
|
new Set(NOTIFY.get(Type)).forEach((x) => addListener(this, x));
|
|
134
135
|
if (Type === _Model)
|
|
135
136
|
break;
|
|
136
|
-
const desc = Object.getOwnPropertyDescriptors(Type.prototype);
|
|
137
|
-
for (const key in desc) {
|
|
138
|
-
let { value } = desc[key];
|
|
139
|
-
if (typeof value == "function" && key !== "constructor")
|
|
140
|
-
Object.defineProperty(Type.prototype, key, {
|
|
141
|
-
get() {
|
|
142
|
-
const method = value.bind(this.is);
|
|
143
|
-
METHOD.set(method, value);
|
|
144
|
-
define(this.is, key, {
|
|
145
|
-
value: method,
|
|
146
|
-
configurable: false
|
|
147
|
-
});
|
|
148
|
-
return method;
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
137
|
Type = Object.getPrototypeOf(Type);
|
|
153
138
|
}
|
|
154
139
|
addListener(this, () => {
|
|
155
|
-
|
|
140
|
+
const apply = typeof arg == "function" ? arg.call(this, this) : arg;
|
|
141
|
+
if (typeof apply == "object")
|
|
142
|
+
assign(this, apply);
|
|
156
143
|
for (const key in this) {
|
|
157
144
|
const desc = Object.getOwnPropertyDescriptor(this, key);
|
|
158
145
|
if ("value" in desc) {
|
|
@@ -166,14 +153,12 @@ var Model = class _Model {
|
|
|
166
153
|
});
|
|
167
154
|
}
|
|
168
155
|
}
|
|
169
|
-
if (typeof arg == "function")
|
|
170
|
-
onDone = arg();
|
|
171
156
|
addListener(this, () => {
|
|
172
157
|
for (const [_, value] of this)
|
|
173
158
|
if (value instanceof _Model && PARENT.get(value) === this)
|
|
174
159
|
value.set(null);
|
|
175
|
-
if (typeof
|
|
176
|
-
|
|
160
|
+
if (typeof apply == "function")
|
|
161
|
+
apply();
|
|
177
162
|
Object.freeze(state);
|
|
178
163
|
}, null);
|
|
179
164
|
return null;
|
|
@@ -227,7 +212,9 @@ var Model = class _Model {
|
|
|
227
212
|
});
|
|
228
213
|
if (arg1 === null)
|
|
229
214
|
return event(this, null);
|
|
230
|
-
if (arg1
|
|
215
|
+
if (typeof arg1 == "object")
|
|
216
|
+
assign(self, arg1);
|
|
217
|
+
else if (arg1 !== void 0)
|
|
231
218
|
if (1 in arguments)
|
|
232
219
|
update(self, arg1, arg2, arg3);
|
|
233
220
|
else
|
|
@@ -255,8 +242,8 @@ var Model = class _Model {
|
|
|
255
242
|
*
|
|
256
243
|
* @param args - arguments sent to constructor
|
|
257
244
|
*/
|
|
258
|
-
static new(
|
|
259
|
-
const instance = new this(
|
|
245
|
+
static new(arg) {
|
|
246
|
+
const instance = new this(arg);
|
|
260
247
|
event(instance, true);
|
|
261
248
|
return instance;
|
|
262
249
|
}
|
|
@@ -285,7 +272,7 @@ var Model = class _Model {
|
|
|
285
272
|
};
|
|
286
273
|
define(Model.prototype, "toString", {
|
|
287
274
|
value() {
|
|
288
|
-
return
|
|
275
|
+
return NAMES.get(this.is);
|
|
289
276
|
}
|
|
290
277
|
});
|
|
291
278
|
define(Model, "toString", {
|
|
@@ -343,6 +330,40 @@ function push(subject, key, silent) {
|
|
|
343
330
|
if (!silent)
|
|
344
331
|
event(subject, key);
|
|
345
332
|
}
|
|
333
|
+
var METHODS = new WeakMap([[Model, []]]);
|
|
334
|
+
function assign(to, values) {
|
|
335
|
+
const methods = METHODS.get(to.constructor);
|
|
336
|
+
const applicable = new Set(Object.keys(to).concat(methods));
|
|
337
|
+
for (const key in values)
|
|
338
|
+
if (applicable.has(key))
|
|
339
|
+
to[key] = values[key];
|
|
340
|
+
}
|
|
341
|
+
function bind(type) {
|
|
342
|
+
let keys = METHODS.get(type);
|
|
343
|
+
if (!keys) {
|
|
344
|
+
METHODS.set(type, keys = bind2(Object.getPrototypeOf(type)).slice());
|
|
345
|
+
const desc = Object.getOwnPropertyDescriptors(type.prototype);
|
|
346
|
+
for (const key in desc)
|
|
347
|
+
if (key != "constructor" && "value" in desc[key]) {
|
|
348
|
+
let bind3 = function(method) {
|
|
349
|
+
const value2 = method.bind(this.is);
|
|
350
|
+
METHOD.set(value2, method);
|
|
351
|
+
define(this.is, key, { value: value2, writable: true });
|
|
352
|
+
return value2;
|
|
353
|
+
};
|
|
354
|
+
var bind2 = bind3;
|
|
355
|
+
let { value } = desc[key];
|
|
356
|
+
keys.push(key);
|
|
357
|
+
Object.defineProperty(type.prototype, key, {
|
|
358
|
+
set: bind3,
|
|
359
|
+
get() {
|
|
360
|
+
return this.hasOwnProperty(key) ? value : bind3.call(this, value);
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return keys;
|
|
366
|
+
}
|
|
346
367
|
function uid() {
|
|
347
368
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
348
369
|
}
|
|
@@ -768,12 +789,12 @@ function has(type, argument) {
|
|
|
768
789
|
return add((key, subject, state) => {
|
|
769
790
|
if (typeof argument == "boolean") {
|
|
770
791
|
Context.request(type, subject, (model) => {
|
|
792
|
+
subject.set(key, model);
|
|
771
793
|
const remove = () => {
|
|
772
794
|
drop();
|
|
773
795
|
if (state[key] === model)
|
|
774
796
|
delete state[key];
|
|
775
797
|
};
|
|
776
|
-
subject.set(key, model);
|
|
777
798
|
const drop = model.get(null, remove);
|
|
778
799
|
return remove;
|
|
779
800
|
});
|
package/package.json
CHANGED