@expressive/mvc 1.0.0-beta.43 → 1.0.0-beta.44
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/lib/index.d.ts +5 -3
- package/lib/index.esm.js +131 -126
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +131 -126
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -220,7 +220,8 @@ declare namespace Instruction {
|
|
|
220
220
|
value?: T;
|
|
221
221
|
writable?: boolean;
|
|
222
222
|
get?: Getter<T>;
|
|
223
|
-
set?: Setter<T> | false
|
|
223
|
+
set?: Setter<T> | false;
|
|
224
|
+
suspense?: boolean;
|
|
224
225
|
}
|
|
225
226
|
|
|
226
227
|
interface ExplicitDescriptor extends PropertyDescriptor {
|
|
@@ -231,7 +232,8 @@ declare namespace Instruction {
|
|
|
231
232
|
recursive: true;
|
|
232
233
|
enumerable?: boolean;
|
|
233
234
|
value?: T;
|
|
234
|
-
set?: Setter<T> | false
|
|
235
|
+
set?: Setter<T> | false;
|
|
236
|
+
suspense?: boolean;
|
|
235
237
|
}
|
|
236
238
|
}
|
|
237
239
|
|
|
@@ -533,7 +535,7 @@ declare class Global extends MVC {
|
|
|
533
535
|
* Returns a thenable; resolves after successful update.
|
|
534
536
|
* If instance does not already exist, one will be created.
|
|
535
537
|
*/
|
|
536
|
-
static set<T extends typeof Global>(this: T, updates: Partial<InstanceOf<T>>):
|
|
538
|
+
static set<T extends typeof Global>(this: T, updates: Partial<InstanceOf<T>>): Promise<false>;
|
|
537
539
|
/**
|
|
538
540
|
* **React Hook** - Fetch most instance of this controller from context, if it exists.
|
|
539
541
|
*
|
package/lib/index.esm.js
CHANGED
|
@@ -34,9 +34,6 @@ function defineLazy(object, property, init) {
|
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
-
function setAlias(func, displayName) {
|
|
38
|
-
assign(func, { displayName });
|
|
39
|
-
}
|
|
40
37
|
function createEffect(callback) {
|
|
41
38
|
let unSet;
|
|
42
39
|
return function (value) {
|
|
@@ -144,66 +141,7 @@ class Subscriber {
|
|
|
144
141
|
|
|
145
142
|
const Oops$b = issues({
|
|
146
143
|
ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
147
|
-
FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`
|
|
148
144
|
});
|
|
149
|
-
/**
|
|
150
|
-
* Get value, suspend instead if undefined.
|
|
151
|
-
*
|
|
152
|
-
* Throws suspense promise also interpretable as an error.
|
|
153
|
-
* React could handle it but other contexts probably not.
|
|
154
|
-
*/
|
|
155
|
-
function pendingValue(via, key) {
|
|
156
|
-
const value = via.state[key];
|
|
157
|
-
if (value === undefined)
|
|
158
|
-
throw suspend(via, key);
|
|
159
|
-
return value;
|
|
160
|
-
}
|
|
161
|
-
function pendingFactory(parent, key, fn, immediate) {
|
|
162
|
-
const { subject, state } = parent;
|
|
163
|
-
let pending;
|
|
164
|
-
let error;
|
|
165
|
-
const init = () => {
|
|
166
|
-
const output = suspenseBoundary(() => {
|
|
167
|
-
return fn.call(subject, key, subject);
|
|
168
|
-
});
|
|
169
|
-
if (output instanceof Promise) {
|
|
170
|
-
pending = output
|
|
171
|
-
.catch(err => error = err)
|
|
172
|
-
.then(val => state[key] = val)
|
|
173
|
-
.finally(() => {
|
|
174
|
-
pending = undefined;
|
|
175
|
-
parent.update(key);
|
|
176
|
-
});
|
|
177
|
-
const issue = Oops$b.ValueNotReady(subject, key);
|
|
178
|
-
Object.assign(pending, {
|
|
179
|
-
message: issue.message,
|
|
180
|
-
stack: issue.stack
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
return state[key] = output;
|
|
184
|
-
};
|
|
185
|
-
if (immediate)
|
|
186
|
-
try {
|
|
187
|
-
init();
|
|
188
|
-
}
|
|
189
|
-
catch (err) {
|
|
190
|
-
Oops$b.FactoryFailed(subject, key).warn();
|
|
191
|
-
throw err;
|
|
192
|
-
}
|
|
193
|
-
return () => {
|
|
194
|
-
if (pending)
|
|
195
|
-
throw pending;
|
|
196
|
-
if (error)
|
|
197
|
-
throw error;
|
|
198
|
-
if (key in state)
|
|
199
|
-
return state[key];
|
|
200
|
-
let output = init();
|
|
201
|
-
if (pending)
|
|
202
|
-
throw pending;
|
|
203
|
-
else
|
|
204
|
-
return output;
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
145
|
function suspend(source, key) {
|
|
208
146
|
const error = Oops$b.ValueNotReady(source.subject, key);
|
|
209
147
|
const promise = new Promise(resolve => {
|
|
@@ -240,9 +178,7 @@ function from(source, arg1, arg2) {
|
|
|
240
178
|
const parent = this;
|
|
241
179
|
const { subject, state } = this;
|
|
242
180
|
let getSource;
|
|
243
|
-
let
|
|
244
|
-
if (arg2 === true || arg1 === true)
|
|
245
|
-
getter = pendingValue;
|
|
181
|
+
let required = arg2 === true || arg1 === true;
|
|
246
182
|
if (typeof arg1 == "boolean")
|
|
247
183
|
arg1 = undefined;
|
|
248
184
|
// Easy mistake, using a peer, will always be unresolved.
|
|
@@ -326,9 +262,6 @@ function from(source, arg1, arg2) {
|
|
|
326
262
|
}
|
|
327
263
|
}
|
|
328
264
|
}
|
|
329
|
-
setAlias(update, `try ${key}`);
|
|
330
|
-
setAlias(create, `new ${key}`);
|
|
331
|
-
setAlias(setter, `run ${key}`);
|
|
332
265
|
INIT.add(create);
|
|
333
266
|
INFO.set(update, info);
|
|
334
267
|
defineProperty(state, key, {
|
|
@@ -336,8 +269,12 @@ function from(source, arg1, arg2) {
|
|
|
336
269
|
configurable: true,
|
|
337
270
|
enumerable: true
|
|
338
271
|
});
|
|
339
|
-
|
|
340
|
-
|
|
272
|
+
return () => {
|
|
273
|
+
const value = parent.state[key];
|
|
274
|
+
if (value === undefined && required)
|
|
275
|
+
throw suspend(this, key);
|
|
276
|
+
return value;
|
|
277
|
+
};
|
|
341
278
|
});
|
|
342
279
|
}
|
|
343
280
|
function ensure(on, keys) {
|
|
@@ -364,7 +301,7 @@ function flush(on) {
|
|
|
364
301
|
}
|
|
365
302
|
|
|
366
303
|
const Oops$9 = issues({
|
|
367
|
-
StrictUpdate: (
|
|
304
|
+
StrictUpdate: () => `Strict update() did not find pending updates.`,
|
|
368
305
|
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
369
306
|
});
|
|
370
307
|
const READY = new WeakSet();
|
|
@@ -394,7 +331,9 @@ class Controller {
|
|
|
394
331
|
return;
|
|
395
332
|
let onGet;
|
|
396
333
|
let onSet;
|
|
334
|
+
let set;
|
|
397
335
|
let enumerable;
|
|
336
|
+
let suspense;
|
|
398
337
|
const instruction = Pending.get(entry);
|
|
399
338
|
if (instruction) {
|
|
400
339
|
Pending.delete(entry);
|
|
@@ -407,31 +346,35 @@ class Controller {
|
|
|
407
346
|
state[key] = desc.value;
|
|
408
347
|
onSet = desc.set;
|
|
409
348
|
onGet = desc.get;
|
|
349
|
+
suspense = desc.suspense;
|
|
410
350
|
enumerable = desc.enumerable;
|
|
411
351
|
}
|
|
412
352
|
}
|
|
413
353
|
else
|
|
414
354
|
state[key] = entry;
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
355
|
+
if (onSet !== false)
|
|
356
|
+
set = this.ref(key, onSet);
|
|
357
|
+
const get = (local) => {
|
|
358
|
+
if (!(key in state) && suspense)
|
|
359
|
+
throw suspend(this, key);
|
|
420
360
|
const value = state[key];
|
|
421
|
-
if (
|
|
422
|
-
local
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
361
|
+
if (onGet)
|
|
362
|
+
return local
|
|
363
|
+
? onGet(value, local)
|
|
364
|
+
: onGet(value);
|
|
365
|
+
return value;
|
|
366
|
+
};
|
|
426
367
|
defineProperty(subject, key, {
|
|
427
|
-
enumerable,
|
|
428
|
-
set,
|
|
429
|
-
get: onGet
|
|
430
|
-
? () => onGet(state[key])
|
|
431
|
-
: () => state[key]
|
|
368
|
+
enumerable, set, get
|
|
432
369
|
});
|
|
433
370
|
defineProperty(proxy, key, {
|
|
434
|
-
enumerable,
|
|
371
|
+
enumerable, set,
|
|
372
|
+
get() {
|
|
373
|
+
const local = this[LOCAL];
|
|
374
|
+
if (local && !local.watch[key])
|
|
375
|
+
local.watch[key] = true;
|
|
376
|
+
return get(local);
|
|
377
|
+
}
|
|
435
378
|
});
|
|
436
379
|
}
|
|
437
380
|
ref(key, handler) {
|
|
@@ -491,12 +434,12 @@ class Controller {
|
|
|
491
434
|
this.waiting.add(arg);
|
|
492
435
|
return;
|
|
493
436
|
}
|
|
494
|
-
if (
|
|
495
|
-
return Promise.reject(Oops$9.StrictUpdate(
|
|
437
|
+
if (arg === true && this.frame.size < 1)
|
|
438
|
+
return Promise.reject(Oops$9.StrictUpdate());
|
|
496
439
|
return {
|
|
497
440
|
then: (callback) => {
|
|
498
441
|
if (callback)
|
|
499
|
-
if (this.frame.size)
|
|
442
|
+
if (this.frame.size || arg !== false)
|
|
500
443
|
this.waiting.add(callback);
|
|
501
444
|
else
|
|
502
445
|
callback(false);
|
|
@@ -679,17 +622,21 @@ function apply(fn, label) {
|
|
|
679
622
|
const placeholder = Symbol(`${name} instruction`);
|
|
680
623
|
function setup(key) {
|
|
681
624
|
let output = fn.call(this, key, this);
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
625
|
+
switch (typeof output) {
|
|
626
|
+
case "function":
|
|
627
|
+
return { get: output };
|
|
628
|
+
case "object": {
|
|
629
|
+
if ("explicit" in output && output.explicit) {
|
|
630
|
+
defineProperty(this.subject, key, output);
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
if ("recursive" in output && output.recursive)
|
|
634
|
+
return Object.assign(Object.assign({}, output), { get: recursive(this, key) });
|
|
635
|
+
}
|
|
636
|
+
case "boolean":
|
|
637
|
+
return output;
|
|
689
638
|
}
|
|
690
|
-
|
|
691
|
-
output = Object.assign(Object.assign({}, output), { get: recursive(this, key) });
|
|
692
|
-
return output;
|
|
639
|
+
return;
|
|
693
640
|
}
|
|
694
641
|
Pending.set(placeholder, setup);
|
|
695
642
|
return placeholder;
|
|
@@ -745,7 +692,6 @@ function act(task) {
|
|
|
745
692
|
});
|
|
746
693
|
};
|
|
747
694
|
this.state[key] = undefined;
|
|
748
|
-
setAlias(invoke, `run ${key}`);
|
|
749
695
|
defineProperty(invoke, "active", {
|
|
750
696
|
get: () => pending
|
|
751
697
|
});
|
|
@@ -780,20 +726,22 @@ function createRef(key, cb) {
|
|
|
780
726
|
|
|
781
727
|
const Oops$7 = issues({
|
|
782
728
|
NonOptional: (Parent, key) => `Property ${Parent}.${key} is marked as required.`,
|
|
783
|
-
BadFactory: () => `Set instruction can only accept a factory or undefined
|
|
729
|
+
BadFactory: () => `Set instruction can only accept a factory or undefined.`,
|
|
730
|
+
ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
731
|
+
FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`
|
|
784
732
|
});
|
|
785
733
|
function set(factory, argument) {
|
|
786
734
|
return apply(function set(key) {
|
|
787
735
|
let set;
|
|
788
736
|
let get;
|
|
737
|
+
let suspense;
|
|
789
738
|
const required = argument === true || argument === undefined;
|
|
790
739
|
if (factory === undefined)
|
|
791
|
-
|
|
792
|
-
else if (typeof factory
|
|
793
|
-
throw Oops$7.BadFactory();
|
|
794
|
-
else {
|
|
740
|
+
suspense = true;
|
|
741
|
+
else if (typeof factory === "function")
|
|
795
742
|
get = pendingFactory(this, key, factory, required);
|
|
796
|
-
|
|
743
|
+
else
|
|
744
|
+
throw Oops$7.BadFactory();
|
|
797
745
|
if (typeof argument == "function")
|
|
798
746
|
set = createValueEffect(argument);
|
|
799
747
|
else
|
|
@@ -801,8 +749,63 @@ function set(factory, argument) {
|
|
|
801
749
|
if (value === undefined && required)
|
|
802
750
|
throw Oops$7.NonOptional(this.subject, key);
|
|
803
751
|
};
|
|
804
|
-
return {
|
|
752
|
+
return {
|
|
753
|
+
set,
|
|
754
|
+
get,
|
|
755
|
+
suspense
|
|
756
|
+
};
|
|
805
757
|
});
|
|
758
|
+
}
|
|
759
|
+
function pendingFactory(parent, key, fn, required) {
|
|
760
|
+
const { subject, state } = parent;
|
|
761
|
+
let pending;
|
|
762
|
+
let error;
|
|
763
|
+
const init = () => {
|
|
764
|
+
const output = suspenseBoundary(() => {
|
|
765
|
+
return fn.call(subject, key, subject);
|
|
766
|
+
});
|
|
767
|
+
if (output instanceof Promise) {
|
|
768
|
+
pending = output
|
|
769
|
+
.catch(err => error = err)
|
|
770
|
+
.then(val => state[key] = val)
|
|
771
|
+
.finally(() => {
|
|
772
|
+
pending = undefined;
|
|
773
|
+
parent.update(key);
|
|
774
|
+
});
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
return state[key] = output;
|
|
778
|
+
};
|
|
779
|
+
const suspend = () => {
|
|
780
|
+
if (required === false)
|
|
781
|
+
return undefined;
|
|
782
|
+
const issue = Oops$7.ValueNotReady(subject, key);
|
|
783
|
+
Object.assign(pending, {
|
|
784
|
+
message: issue.message,
|
|
785
|
+
stack: issue.stack
|
|
786
|
+
});
|
|
787
|
+
throw pending;
|
|
788
|
+
};
|
|
789
|
+
if (required)
|
|
790
|
+
try {
|
|
791
|
+
init();
|
|
792
|
+
}
|
|
793
|
+
catch (err) {
|
|
794
|
+
Oops$7.FactoryFailed(subject, key).warn();
|
|
795
|
+
throw err;
|
|
796
|
+
}
|
|
797
|
+
return () => {
|
|
798
|
+
if (pending)
|
|
799
|
+
return suspend();
|
|
800
|
+
if (error)
|
|
801
|
+
throw error;
|
|
802
|
+
if (key in state)
|
|
803
|
+
return state[key];
|
|
804
|
+
let output = init();
|
|
805
|
+
return pending
|
|
806
|
+
? suspend()
|
|
807
|
+
: output;
|
|
808
|
+
};
|
|
806
809
|
}
|
|
807
810
|
|
|
808
811
|
const Parent = new WeakMap();
|
|
@@ -945,24 +948,26 @@ const ContextWasUsed = new WeakMap();
|
|
|
945
948
|
function tap(type, argument) {
|
|
946
949
|
return apply(function tap(key) {
|
|
947
950
|
if ("set" in type)
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
951
|
+
return {
|
|
952
|
+
recursive: true,
|
|
953
|
+
value: type.get()
|
|
954
|
+
};
|
|
955
|
+
const { subject } = this;
|
|
956
|
+
if ("set" in subject.constructor)
|
|
957
|
+
throw Oops$3.CantAttachGlobal(subject, type.name);
|
|
958
|
+
getPending(subject).push(context => {
|
|
959
|
+
let instance = context.get(type);
|
|
960
|
+
if (typeof argument == "function") {
|
|
961
|
+
if (argument(instance) === false)
|
|
962
|
+
instance = undefined;
|
|
963
|
+
}
|
|
964
|
+
else if (!instance && argument)
|
|
965
|
+
throw Oops$3.AmbientRequired(type.name, subject, key);
|
|
966
|
+
this.update(key, instance);
|
|
967
|
+
});
|
|
964
968
|
return {
|
|
965
|
-
recursive: true
|
|
969
|
+
recursive: true,
|
|
970
|
+
suspense: true
|
|
966
971
|
};
|
|
967
972
|
});
|
|
968
973
|
}
|
|
@@ -1260,7 +1265,7 @@ class Global extends MVC {
|
|
|
1260
1265
|
static set(updates) {
|
|
1261
1266
|
const instance = Active.get(this) || this.create();
|
|
1262
1267
|
instance.import(updates);
|
|
1263
|
-
return instance.update();
|
|
1268
|
+
return instance.update(false);
|
|
1264
1269
|
}
|
|
1265
1270
|
static get(arg) {
|
|
1266
1271
|
const instance = Active.get(this);
|