@expressive/mvc 0.42.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 +15 -6
- package/dist/index.js +47 -29
- package/dist/index.mjs +47 -29
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,18 +2,22 @@ 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 (arg?:
|
|
5
|
+
type New<T extends Model = Model> = (new (arg?: Argument) => T) & typeof Model;
|
|
6
6
|
/**
|
|
7
7
|
* Model constructor callback - is called when Model finishes intializing.
|
|
8
8
|
* Returned function will call when model is destroyed.
|
|
9
9
|
*/
|
|
10
|
-
type Callback = (
|
|
10
|
+
type Callback<T extends Model = Model> = (this: T, thisArg: T) => (() => void) | Assign<T> | void;
|
|
11
11
|
/** Model constructor argument */
|
|
12
|
-
type Argument = string | Callback | undefined;
|
|
12
|
+
type Argument<T extends Model = Model> = string | Callback<T> | Assign<T> | undefined;
|
|
13
13
|
/** Subset of `keyof T` which are not methods or defined by base Model U. **/
|
|
14
14
|
type Field<T> = Exclude<keyof T, keyof Model>;
|
|
15
15
|
/** Any valid key for controller, including but not limited to Field<T>. */
|
|
16
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>;
|
|
17
21
|
/** Export/Import compatible value for a given property in a Model. */
|
|
18
22
|
type Export<R> = R extends {
|
|
19
23
|
get(): infer T;
|
|
@@ -49,7 +53,7 @@ declare namespace Model {
|
|
|
49
53
|
*
|
|
50
54
|
* @returns A callback function which will be called when this effect is stale.
|
|
51
55
|
*/
|
|
52
|
-
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;
|
|
53
57
|
/**
|
|
54
58
|
* A callback function returned by effect. Will be called when effect is stale.
|
|
55
59
|
*
|
|
@@ -70,7 +74,7 @@ declare namespace Model {
|
|
|
70
74
|
* Property initializer, will run upon instance creation.
|
|
71
75
|
* Optional returned callback will run when once upon first access.
|
|
72
76
|
*/
|
|
73
|
-
type Instruction<T = any, M extends Model = any> = (this: M, key:
|
|
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
|
/**
|
|
@@ -159,6 +163,11 @@ declare class Model {
|
|
|
159
163
|
* @returns Promise which resolves an array of keys which were updated.
|
|
160
164
|
*/
|
|
161
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
|
*
|
|
@@ -176,7 +185,7 @@ declare class Model {
|
|
|
176
185
|
*
|
|
177
186
|
* @param args - arguments sent to constructor
|
|
178
187
|
*/
|
|
179
|
-
static new<T extends Model>(this: Model.New<T>, arg?: Model.Argument): T;
|
|
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,38 +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
|
-
const bind = (value2) => {
|
|
175
|
-
const method = value2.bind(this);
|
|
176
|
-
METHOD.set(method, value2);
|
|
177
|
-
define(this, key, {
|
|
178
|
-
value: method,
|
|
179
|
-
configurable: false
|
|
180
|
-
});
|
|
181
|
-
return method;
|
|
182
|
-
};
|
|
183
|
-
Object.defineProperty(Type.prototype, key, {
|
|
184
|
-
get: () => this.hasOwnProperty(key) ? value : bind(value),
|
|
185
|
-
set: bind
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
171
|
Type = Object.getPrototypeOf(Type);
|
|
190
172
|
}
|
|
191
173
|
addListener(this, () => {
|
|
192
|
-
|
|
193
|
-
if (typeof
|
|
194
|
-
|
|
174
|
+
const apply = typeof arg == "function" ? arg.call(this, this) : arg;
|
|
175
|
+
if (typeof apply == "object")
|
|
176
|
+
assign(this, apply);
|
|
195
177
|
for (const key in this) {
|
|
196
178
|
const desc = Object.getOwnPropertyDescriptor(this, key);
|
|
197
179
|
if ("value" in desc) {
|
|
@@ -209,8 +191,8 @@ var Model = class _Model {
|
|
|
209
191
|
for (const [_, value] of this)
|
|
210
192
|
if (value instanceof _Model && PARENT.get(value) === this)
|
|
211
193
|
value.set(null);
|
|
212
|
-
if (typeof
|
|
213
|
-
|
|
194
|
+
if (typeof apply == "function")
|
|
195
|
+
apply();
|
|
214
196
|
Object.freeze(state);
|
|
215
197
|
}, null);
|
|
216
198
|
return null;
|
|
@@ -264,7 +246,9 @@ var Model = class _Model {
|
|
|
264
246
|
});
|
|
265
247
|
if (arg1 === null)
|
|
266
248
|
return event(this, null);
|
|
267
|
-
if (arg1
|
|
249
|
+
if (typeof arg1 == "object")
|
|
250
|
+
assign(self, arg1);
|
|
251
|
+
else if (arg1 !== void 0)
|
|
268
252
|
if (1 in arguments)
|
|
269
253
|
update(self, arg1, arg2, arg3);
|
|
270
254
|
else
|
|
@@ -322,7 +306,7 @@ var Model = class _Model {
|
|
|
322
306
|
};
|
|
323
307
|
define(Model.prototype, "toString", {
|
|
324
308
|
value() {
|
|
325
|
-
return
|
|
309
|
+
return NAMES.get(this.is);
|
|
326
310
|
}
|
|
327
311
|
});
|
|
328
312
|
define(Model, "toString", {
|
|
@@ -380,6 +364,40 @@ function push(subject, key, silent) {
|
|
|
380
364
|
if (!silent)
|
|
381
365
|
event(subject, key);
|
|
382
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
|
+
}
|
|
383
401
|
function uid() {
|
|
384
402
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
385
403
|
}
|
|
@@ -805,12 +823,12 @@ function has(type, argument) {
|
|
|
805
823
|
return add((key, subject, state) => {
|
|
806
824
|
if (typeof argument == "boolean") {
|
|
807
825
|
Context.request(type, subject, (model) => {
|
|
826
|
+
subject.set(key, model);
|
|
808
827
|
const remove = () => {
|
|
809
828
|
drop();
|
|
810
829
|
if (state[key] === model)
|
|
811
830
|
delete state[key];
|
|
812
831
|
};
|
|
813
|
-
subject.set(key, model);
|
|
814
832
|
const drop = model.get(null, remove);
|
|
815
833
|
return remove;
|
|
816
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,38 +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
|
-
const bind = (value2) => {
|
|
141
|
-
const method = value2.bind(this);
|
|
142
|
-
METHOD.set(method, value2);
|
|
143
|
-
define(this, key, {
|
|
144
|
-
value: method,
|
|
145
|
-
configurable: false
|
|
146
|
-
});
|
|
147
|
-
return method;
|
|
148
|
-
};
|
|
149
|
-
Object.defineProperty(Type.prototype, key, {
|
|
150
|
-
get: () => this.hasOwnProperty(key) ? value : bind(value),
|
|
151
|
-
set: bind
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
137
|
Type = Object.getPrototypeOf(Type);
|
|
156
138
|
}
|
|
157
139
|
addListener(this, () => {
|
|
158
|
-
|
|
159
|
-
if (typeof
|
|
160
|
-
|
|
140
|
+
const apply = typeof arg == "function" ? arg.call(this, this) : arg;
|
|
141
|
+
if (typeof apply == "object")
|
|
142
|
+
assign(this, apply);
|
|
161
143
|
for (const key in this) {
|
|
162
144
|
const desc = Object.getOwnPropertyDescriptor(this, key);
|
|
163
145
|
if ("value" in desc) {
|
|
@@ -175,8 +157,8 @@ var Model = class _Model {
|
|
|
175
157
|
for (const [_, value] of this)
|
|
176
158
|
if (value instanceof _Model && PARENT.get(value) === this)
|
|
177
159
|
value.set(null);
|
|
178
|
-
if (typeof
|
|
179
|
-
|
|
160
|
+
if (typeof apply == "function")
|
|
161
|
+
apply();
|
|
180
162
|
Object.freeze(state);
|
|
181
163
|
}, null);
|
|
182
164
|
return null;
|
|
@@ -230,7 +212,9 @@ var Model = class _Model {
|
|
|
230
212
|
});
|
|
231
213
|
if (arg1 === null)
|
|
232
214
|
return event(this, null);
|
|
233
|
-
if (arg1
|
|
215
|
+
if (typeof arg1 == "object")
|
|
216
|
+
assign(self, arg1);
|
|
217
|
+
else if (arg1 !== void 0)
|
|
234
218
|
if (1 in arguments)
|
|
235
219
|
update(self, arg1, arg2, arg3);
|
|
236
220
|
else
|
|
@@ -288,7 +272,7 @@ var Model = class _Model {
|
|
|
288
272
|
};
|
|
289
273
|
define(Model.prototype, "toString", {
|
|
290
274
|
value() {
|
|
291
|
-
return
|
|
275
|
+
return NAMES.get(this.is);
|
|
292
276
|
}
|
|
293
277
|
});
|
|
294
278
|
define(Model, "toString", {
|
|
@@ -346,6 +330,40 @@ function push(subject, key, silent) {
|
|
|
346
330
|
if (!silent)
|
|
347
331
|
event(subject, key);
|
|
348
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
|
+
}
|
|
349
367
|
function uid() {
|
|
350
368
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
351
369
|
}
|
|
@@ -771,12 +789,12 @@ function has(type, argument) {
|
|
|
771
789
|
return add((key, subject, state) => {
|
|
772
790
|
if (typeof argument == "boolean") {
|
|
773
791
|
Context.request(type, subject, (model) => {
|
|
792
|
+
subject.set(key, model);
|
|
774
793
|
const remove = () => {
|
|
775
794
|
drop();
|
|
776
795
|
if (state[key] === model)
|
|
777
796
|
delete state[key];
|
|
778
797
|
};
|
|
779
|
-
subject.set(key, model);
|
|
780
798
|
const drop = model.get(null, remove);
|
|
781
799
|
return remove;
|
|
782
800
|
});
|
package/package.json
CHANGED