@expressive/mvc 0.47.0 → 0.48.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 +4 -4
- package/dist/index.js +149 -157
- package/dist/index.mjs +149 -157
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ declare namespace Model {
|
|
|
8
8
|
*/
|
|
9
9
|
type Callback<T extends Model = Model> = (this: T, thisArg: T) => MaybeAsync<(() => void) | Assign<T> | void>;
|
|
10
10
|
/** Model constructor argument */
|
|
11
|
-
type Argument<T extends Model = Model> =
|
|
11
|
+
type Argument<T extends Model = Model> = Assign<T> | Callback<T> | string | void;
|
|
12
12
|
/** Model constructor arguments */
|
|
13
13
|
type Args<T extends Model = any> = Argument<T>[];
|
|
14
14
|
/** Subset of `keyof T` which are not methods or defined by base Model U. **/
|
|
@@ -198,7 +198,6 @@ declare class Model {
|
|
|
198
198
|
* Register a callback to run when any instance of this Model is updated.
|
|
199
199
|
*/
|
|
200
200
|
static on<T extends Model>(this: Model.Type<T>, listener: Model.OnEvent<T>): () => boolean;
|
|
201
|
-
static at<T extends Model>(this: Model.Type<T>, from: Model, cb: (got: T | undefined) => void): void;
|
|
202
201
|
}
|
|
203
202
|
|
|
204
203
|
declare namespace get {
|
|
@@ -356,10 +355,11 @@ declare function has<T extends Model>(type: Model.Type<T>, required: boolean): T
|
|
|
356
355
|
declare function has<T extends Model>(type: Model.Type<T>, arg?: has.Callback<T>): Set<T>;
|
|
357
356
|
|
|
358
357
|
declare namespace Context {
|
|
359
|
-
type Input =
|
|
358
|
+
type Input = Record<string | number, Model | Model.Type<Model>>;
|
|
360
359
|
}
|
|
361
360
|
declare class Context {
|
|
362
|
-
static
|
|
361
|
+
static get<T extends Model>(on: Model, callback: ((got: Context) => void)): void;
|
|
362
|
+
static get<T extends Model>(on: Model): Context | undefined;
|
|
363
363
|
id: string;
|
|
364
364
|
protected downstream: WeakMap<Model.Type<Model>, symbol>;
|
|
365
365
|
protected upstream: WeakMap<Model.Type<Model>, symbol>;
|
package/dist/index.js
CHANGED
|
@@ -150,7 +150,7 @@ function effect(target, callback) {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
// src/model.ts
|
|
153
|
-
var
|
|
153
|
+
var EXPORT;
|
|
154
154
|
var NAMES = /* @__PURE__ */ new WeakMap();
|
|
155
155
|
var STATE = /* @__PURE__ */ new WeakMap();
|
|
156
156
|
var NOTIFY = /* @__PURE__ */ new WeakMap();
|
|
@@ -235,16 +235,16 @@ var Model = class _Model {
|
|
|
235
235
|
}
|
|
236
236
|
if (arg1 === void 0) {
|
|
237
237
|
const values = {};
|
|
238
|
-
const current = !
|
|
238
|
+
const current = !EXPORT && (EXPORT = /* @__PURE__ */ new Map([[self, values]]));
|
|
239
239
|
for (let [key, value] of self) {
|
|
240
|
-
if (
|
|
241
|
-
value =
|
|
240
|
+
if (EXPORT.has(value))
|
|
241
|
+
value = EXPORT.get(value);
|
|
242
242
|
else if (value && typeof value.get === "function")
|
|
243
|
-
|
|
243
|
+
EXPORT.set(value, value = value.get());
|
|
244
244
|
values[key] = value;
|
|
245
245
|
}
|
|
246
246
|
if (current)
|
|
247
|
-
|
|
247
|
+
EXPORT = void 0;
|
|
248
248
|
return Object.freeze(values);
|
|
249
249
|
}
|
|
250
250
|
if (typeof arg2 == "function") {
|
|
@@ -323,9 +323,6 @@ var Model = class _Model {
|
|
|
323
323
|
notify.add(listener);
|
|
324
324
|
return () => notify.delete(listener);
|
|
325
325
|
}
|
|
326
|
-
static at(from, cb) {
|
|
327
|
-
throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
|
|
328
|
-
}
|
|
329
326
|
};
|
|
330
327
|
define(Model.prototype, "toString", {
|
|
331
328
|
value() {
|
|
@@ -345,14 +342,14 @@ function fetch(subject, property, required) {
|
|
|
345
342
|
return value;
|
|
346
343
|
}
|
|
347
344
|
const error = new Error(`${subject}.${property} is not yet available.`);
|
|
348
|
-
const promise = new Promise((resolve,
|
|
345
|
+
const promise = new Promise((resolve, reject) => {
|
|
349
346
|
addListener(subject, (key) => {
|
|
350
347
|
if (key === property) {
|
|
351
348
|
resolve(state[key]);
|
|
352
349
|
return null;
|
|
353
350
|
}
|
|
354
351
|
if (key === null)
|
|
355
|
-
|
|
352
|
+
reject(new Error(`${subject} is destroyed.`));
|
|
356
353
|
});
|
|
357
354
|
});
|
|
358
355
|
throw Object.assign(promise, {
|
|
@@ -429,6 +426,132 @@ function uid() {
|
|
|
429
426
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
430
427
|
}
|
|
431
428
|
|
|
429
|
+
// src/context.ts
|
|
430
|
+
var Register = /* @__PURE__ */ new WeakMap();
|
|
431
|
+
var Context = class _Context {
|
|
432
|
+
constructor(inputs) {
|
|
433
|
+
this.downstream = /* @__PURE__ */ new WeakMap();
|
|
434
|
+
this.upstream = /* @__PURE__ */ new WeakMap();
|
|
435
|
+
this.layer = /* @__PURE__ */ new Map();
|
|
436
|
+
if (inputs)
|
|
437
|
+
this.include(inputs);
|
|
438
|
+
}
|
|
439
|
+
static get(from, callback) {
|
|
440
|
+
const waiting = Register.get(from);
|
|
441
|
+
if (!callback)
|
|
442
|
+
return waiting instanceof _Context ? waiting : void 0;
|
|
443
|
+
if (waiting instanceof _Context)
|
|
444
|
+
callback(waiting);
|
|
445
|
+
else if (waiting)
|
|
446
|
+
waiting.push(callback);
|
|
447
|
+
else
|
|
448
|
+
Register.set(from, [callback]);
|
|
449
|
+
}
|
|
450
|
+
key(T, upstream) {
|
|
451
|
+
const table = upstream ? this.upstream : this.downstream;
|
|
452
|
+
let key = table.get(T);
|
|
453
|
+
if (!key) {
|
|
454
|
+
key = Symbol(T.name + (upstream ? " request" : ""));
|
|
455
|
+
table.set(T, key);
|
|
456
|
+
}
|
|
457
|
+
return key;
|
|
458
|
+
}
|
|
459
|
+
has(model) {
|
|
460
|
+
const key = this.key(model.constructor, true);
|
|
461
|
+
const result = this[key];
|
|
462
|
+
const waiting = Register.get(model);
|
|
463
|
+
if (waiting instanceof Array)
|
|
464
|
+
waiting.forEach((cb) => cb(this));
|
|
465
|
+
Register.set(model, this);
|
|
466
|
+
if (typeof result == "function")
|
|
467
|
+
return result(model);
|
|
468
|
+
}
|
|
469
|
+
get(Type) {
|
|
470
|
+
const result = this[this.key(Type)];
|
|
471
|
+
if (result === null)
|
|
472
|
+
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
473
|
+
return result;
|
|
474
|
+
}
|
|
475
|
+
include(inputs, forEach) {
|
|
476
|
+
const init = /* @__PURE__ */ new Map();
|
|
477
|
+
Object.entries(inputs).forEach(([K, V]) => {
|
|
478
|
+
if (!(Model.is(V) || V instanceof Model))
|
|
479
|
+
throw new Error(`Context can only include Model or instance but got ${V}${K && " as " + K}.`);
|
|
480
|
+
});
|
|
481
|
+
for (const key in inputs) {
|
|
482
|
+
const input = inputs[key];
|
|
483
|
+
const exists = this.layer.get(key);
|
|
484
|
+
if (!exists) {
|
|
485
|
+
const instance = this.add(input);
|
|
486
|
+
this.layer.set(key, input);
|
|
487
|
+
init.set(instance, true);
|
|
488
|
+
} else if (exists !== input) {
|
|
489
|
+
this.pop();
|
|
490
|
+
this.id = uid();
|
|
491
|
+
this.include(inputs);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
for (const [model, explicit] of init) {
|
|
495
|
+
model.set();
|
|
496
|
+
if (forEach)
|
|
497
|
+
forEach(model, explicit);
|
|
498
|
+
for (const [_key, value] of model)
|
|
499
|
+
if (PARENT.get(value) === model) {
|
|
500
|
+
this.add(value, true);
|
|
501
|
+
init.set(value, false);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
put(T, I, implicit, writable) {
|
|
506
|
+
do {
|
|
507
|
+
const key = this.key(T, typeof I == "function");
|
|
508
|
+
const value = this.hasOwnProperty(key) ? null : I;
|
|
509
|
+
if (value || this[key] !== I && !implicit)
|
|
510
|
+
Object.defineProperty(this, key, {
|
|
511
|
+
configurable: true,
|
|
512
|
+
writable,
|
|
513
|
+
value
|
|
514
|
+
});
|
|
515
|
+
T = Object.getPrototypeOf(T);
|
|
516
|
+
} while (T !== Model);
|
|
517
|
+
}
|
|
518
|
+
add(input, implicit) {
|
|
519
|
+
let writable = true;
|
|
520
|
+
let T;
|
|
521
|
+
let I;
|
|
522
|
+
if (typeof input == "function") {
|
|
523
|
+
T = input;
|
|
524
|
+
I = new input();
|
|
525
|
+
} else {
|
|
526
|
+
I = input;
|
|
527
|
+
T = I.constructor;
|
|
528
|
+
writable = false;
|
|
529
|
+
}
|
|
530
|
+
this.has(I);
|
|
531
|
+
this.put(T, I, implicit, writable);
|
|
532
|
+
return I;
|
|
533
|
+
}
|
|
534
|
+
push(inputs) {
|
|
535
|
+
const next = Object.create(this);
|
|
536
|
+
next.layer = /* @__PURE__ */ new Map();
|
|
537
|
+
if (inputs)
|
|
538
|
+
next.include(inputs);
|
|
539
|
+
return next;
|
|
540
|
+
}
|
|
541
|
+
pop() {
|
|
542
|
+
const items = /* @__PURE__ */ new Set();
|
|
543
|
+
for (const key of Object.getOwnPropertySymbols(this)) {
|
|
544
|
+
const entry = Object.getOwnPropertyDescriptor(this, key);
|
|
545
|
+
if (entry.writable && entry.value)
|
|
546
|
+
items.add(entry.value);
|
|
547
|
+
delete this[key];
|
|
548
|
+
}
|
|
549
|
+
for (const model of items)
|
|
550
|
+
model.set(null);
|
|
551
|
+
this.layer.clear();
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
|
|
432
555
|
// src/instruction/use.ts
|
|
433
556
|
var INSTRUCT = /* @__PURE__ */ new Map();
|
|
434
557
|
function use(model, argument) {
|
|
@@ -500,20 +623,21 @@ Model.on((_, subject) => {
|
|
|
500
623
|
// src/instruction/get.ts
|
|
501
624
|
var STALE = /* @__PURE__ */ new WeakSet();
|
|
502
625
|
function get(arg0, arg1) {
|
|
503
|
-
return use((key, subject) => {
|
|
626
|
+
return use((key, subject, state) => {
|
|
504
627
|
let from = subject;
|
|
505
628
|
if (typeof arg0 == "symbol")
|
|
506
629
|
throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${from}.${key}. This is not allowed.`);
|
|
507
630
|
let source = (resolve) => resolve(from);
|
|
508
631
|
if (arg0 instanceof Model) {
|
|
509
632
|
from = arg0;
|
|
510
|
-
} else if (arg0
|
|
633
|
+
} else if (Model.is(arg0)) {
|
|
511
634
|
const hasParent = PARENT.get(from);
|
|
512
635
|
if (!hasParent) {
|
|
513
636
|
if (arg1 === true)
|
|
514
637
|
throw new Error(`${from} may only exist as a child of type ${arg0}.`);
|
|
515
638
|
source = (resolve) => {
|
|
516
|
-
|
|
639
|
+
Context.get(from, (context) => {
|
|
640
|
+
const got = context.get(arg0);
|
|
517
641
|
if (got)
|
|
518
642
|
resolve(got);
|
|
519
643
|
else if (arg1 !== false)
|
|
@@ -532,10 +656,8 @@ function get(arg0, arg1) {
|
|
|
532
656
|
let connect2 = function(model) {
|
|
533
657
|
reset = effect(model, (current) => {
|
|
534
658
|
proxy = current;
|
|
535
|
-
if (!
|
|
536
|
-
compute2(
|
|
537
|
-
else if (STALE.delete(compute2))
|
|
538
|
-
compute2();
|
|
659
|
+
if (!(key in state) || STALE.delete(compute2))
|
|
660
|
+
compute2(!reset);
|
|
539
661
|
return (didUpdate) => {
|
|
540
662
|
if (didUpdate) {
|
|
541
663
|
STALE.add(compute2);
|
|
@@ -699,172 +821,42 @@ function attempt(fn) {
|
|
|
699
821
|
return compute();
|
|
700
822
|
}
|
|
701
823
|
|
|
702
|
-
// src/context.ts
|
|
703
|
-
var Expects = /* @__PURE__ */ new WeakMap();
|
|
704
|
-
var Context = class {
|
|
705
|
-
constructor(inputs) {
|
|
706
|
-
this.downstream = /* @__PURE__ */ new WeakMap();
|
|
707
|
-
this.upstream = /* @__PURE__ */ new WeakMap();
|
|
708
|
-
this.layer = /* @__PURE__ */ new Map();
|
|
709
|
-
if (inputs)
|
|
710
|
-
this.include(inputs);
|
|
711
|
-
}
|
|
712
|
-
static request(type, from, callback) {
|
|
713
|
-
let map = Expects.get(from);
|
|
714
|
-
if (!map)
|
|
715
|
-
Expects.set(from, map = /* @__PURE__ */ new Map());
|
|
716
|
-
map.set(type, callback);
|
|
717
|
-
}
|
|
718
|
-
key(T, upstream) {
|
|
719
|
-
const table = upstream ? this.upstream : this.downstream;
|
|
720
|
-
let key = table.get(T);
|
|
721
|
-
if (!key) {
|
|
722
|
-
key = Symbol(T.name + (upstream ? " request" : ""));
|
|
723
|
-
table.set(T, key);
|
|
724
|
-
}
|
|
725
|
-
return key;
|
|
726
|
-
}
|
|
727
|
-
has(model) {
|
|
728
|
-
const key = this.key(model.constructor, true);
|
|
729
|
-
const result = this[key];
|
|
730
|
-
if (typeof result == "function")
|
|
731
|
-
return result(model);
|
|
732
|
-
}
|
|
733
|
-
get(Type) {
|
|
734
|
-
const result = this[this.key(Type)];
|
|
735
|
-
if (result === null)
|
|
736
|
-
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
737
|
-
return result;
|
|
738
|
-
}
|
|
739
|
-
include(inputs, forEach) {
|
|
740
|
-
const init = /* @__PURE__ */ new Map();
|
|
741
|
-
if (typeof inputs == "function" || inputs instanceof Model)
|
|
742
|
-
inputs = { [0]: inputs };
|
|
743
|
-
else if (!inputs)
|
|
744
|
-
reject(inputs);
|
|
745
|
-
Object.entries(inputs).forEach(([K, V]) => {
|
|
746
|
-
if (!(Model.is(V) || V instanceof Model))
|
|
747
|
-
reject(`${V} as ${K}`);
|
|
748
|
-
});
|
|
749
|
-
for (const key in inputs) {
|
|
750
|
-
const input = inputs[key];
|
|
751
|
-
const exists = this.layer.get(key);
|
|
752
|
-
if (!exists) {
|
|
753
|
-
const instance = this.add(input);
|
|
754
|
-
this.layer.set(key, input);
|
|
755
|
-
init.set(instance, true);
|
|
756
|
-
} else if (exists !== input) {
|
|
757
|
-
this.pop();
|
|
758
|
-
this.id = uid();
|
|
759
|
-
this.include(inputs);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
for (const [model, explicit] of init) {
|
|
763
|
-
if (forEach)
|
|
764
|
-
forEach(model, explicit);
|
|
765
|
-
model.set();
|
|
766
|
-
this.has(model);
|
|
767
|
-
const expects = Expects.get(model);
|
|
768
|
-
if (expects)
|
|
769
|
-
for (let [T, callback] of expects)
|
|
770
|
-
this.put(T, callback);
|
|
771
|
-
for (const [_key, value] of model)
|
|
772
|
-
if (PARENT.get(value) === model) {
|
|
773
|
-
this.add(value, true);
|
|
774
|
-
init.set(value, false);
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
put(T, I, implicit, writable) {
|
|
779
|
-
do {
|
|
780
|
-
const key = this.key(T, typeof I == "function");
|
|
781
|
-
const value = this.hasOwnProperty(key) ? null : I;
|
|
782
|
-
if (value || this[key] !== I && !implicit)
|
|
783
|
-
Object.defineProperty(this, key, {
|
|
784
|
-
configurable: true,
|
|
785
|
-
writable,
|
|
786
|
-
value
|
|
787
|
-
});
|
|
788
|
-
T = Object.getPrototypeOf(T);
|
|
789
|
-
} while (T !== Model);
|
|
790
|
-
}
|
|
791
|
-
add(input, implicit) {
|
|
792
|
-
let writable = true;
|
|
793
|
-
let T;
|
|
794
|
-
let I;
|
|
795
|
-
if (typeof input == "function") {
|
|
796
|
-
T = input;
|
|
797
|
-
I = new input();
|
|
798
|
-
} else {
|
|
799
|
-
I = input;
|
|
800
|
-
T = I.constructor;
|
|
801
|
-
writable = false;
|
|
802
|
-
}
|
|
803
|
-
this.put(T, I, implicit, writable);
|
|
804
|
-
return I;
|
|
805
|
-
}
|
|
806
|
-
push(inputs) {
|
|
807
|
-
const next = Object.create(this);
|
|
808
|
-
next.layer = /* @__PURE__ */ new Map();
|
|
809
|
-
if (inputs)
|
|
810
|
-
next.include(inputs);
|
|
811
|
-
return next;
|
|
812
|
-
}
|
|
813
|
-
pop() {
|
|
814
|
-
const items = /* @__PURE__ */ new Set();
|
|
815
|
-
for (const key of Object.getOwnPropertySymbols(this)) {
|
|
816
|
-
const entry = Object.getOwnPropertyDescriptor(this, key);
|
|
817
|
-
if (entry.writable && entry.value)
|
|
818
|
-
items.add(entry.value);
|
|
819
|
-
delete this[key];
|
|
820
|
-
}
|
|
821
|
-
for (const model of items)
|
|
822
|
-
model.set(null);
|
|
823
|
-
this.layer.clear();
|
|
824
|
-
}
|
|
825
|
-
};
|
|
826
|
-
function reject(argument) {
|
|
827
|
-
throw new Error(`Context can only include Model or instance but got ${argument}.`);
|
|
828
|
-
}
|
|
829
|
-
|
|
830
824
|
// src/instruction/has.ts
|
|
831
825
|
function has(type, argument) {
|
|
832
826
|
return use((key, subject, state) => {
|
|
827
|
+
const expect = (callback) => Context.get(subject, (context) => context.put(type, callback));
|
|
833
828
|
if (typeof argument == "boolean") {
|
|
834
|
-
|
|
829
|
+
expect((model) => {
|
|
835
830
|
subject.set(key, model);
|
|
836
831
|
const remove = () => {
|
|
837
|
-
drop();
|
|
838
832
|
if (state[key] === model)
|
|
839
833
|
delete state[key];
|
|
840
834
|
};
|
|
841
|
-
|
|
835
|
+
model.get(null, remove);
|
|
842
836
|
return remove;
|
|
843
837
|
});
|
|
844
838
|
return { get: argument };
|
|
845
839
|
}
|
|
846
|
-
const
|
|
847
|
-
|
|
848
|
-
if (
|
|
840
|
+
const value = /* @__PURE__ */ new Set();
|
|
841
|
+
expect((model) => {
|
|
842
|
+
if (value.has(model))
|
|
849
843
|
return;
|
|
850
844
|
const remove = typeof argument == "function" ? argument(model) : void 0;
|
|
851
845
|
if (remove === false)
|
|
852
846
|
return;
|
|
853
|
-
|
|
847
|
+
value.add(model);
|
|
854
848
|
subject.set(key);
|
|
855
849
|
const done = () => {
|
|
856
850
|
drop();
|
|
857
851
|
if (typeof remove == "function")
|
|
858
852
|
remove();
|
|
859
|
-
|
|
853
|
+
value.delete(model);
|
|
860
854
|
subject.set(key);
|
|
861
855
|
};
|
|
862
856
|
const drop = model.get(null, done);
|
|
863
857
|
return done;
|
|
864
858
|
});
|
|
865
|
-
return {
|
|
866
|
-
value: children
|
|
867
|
-
};
|
|
859
|
+
return { value };
|
|
868
860
|
});
|
|
869
861
|
}
|
|
870
862
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/index.mjs
CHANGED
|
@@ -117,7 +117,7 @@ function effect(target, callback) {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
// src/model.ts
|
|
120
|
-
var
|
|
120
|
+
var EXPORT;
|
|
121
121
|
var NAMES = /* @__PURE__ */ new WeakMap();
|
|
122
122
|
var STATE = /* @__PURE__ */ new WeakMap();
|
|
123
123
|
var NOTIFY = /* @__PURE__ */ new WeakMap();
|
|
@@ -202,16 +202,16 @@ var Model = class _Model {
|
|
|
202
202
|
}
|
|
203
203
|
if (arg1 === void 0) {
|
|
204
204
|
const values = {};
|
|
205
|
-
const current = !
|
|
205
|
+
const current = !EXPORT && (EXPORT = /* @__PURE__ */ new Map([[self, values]]));
|
|
206
206
|
for (let [key, value] of self) {
|
|
207
|
-
if (
|
|
208
|
-
value =
|
|
207
|
+
if (EXPORT.has(value))
|
|
208
|
+
value = EXPORT.get(value);
|
|
209
209
|
else if (value && typeof value.get === "function")
|
|
210
|
-
|
|
210
|
+
EXPORT.set(value, value = value.get());
|
|
211
211
|
values[key] = value;
|
|
212
212
|
}
|
|
213
213
|
if (current)
|
|
214
|
-
|
|
214
|
+
EXPORT = void 0;
|
|
215
215
|
return Object.freeze(values);
|
|
216
216
|
}
|
|
217
217
|
if (typeof arg2 == "function") {
|
|
@@ -290,9 +290,6 @@ var Model = class _Model {
|
|
|
290
290
|
notify.add(listener);
|
|
291
291
|
return () => notify.delete(listener);
|
|
292
292
|
}
|
|
293
|
-
static at(from, cb) {
|
|
294
|
-
throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
|
|
295
|
-
}
|
|
296
293
|
};
|
|
297
294
|
define(Model.prototype, "toString", {
|
|
298
295
|
value() {
|
|
@@ -312,14 +309,14 @@ function fetch(subject, property, required) {
|
|
|
312
309
|
return value;
|
|
313
310
|
}
|
|
314
311
|
const error = new Error(`${subject}.${property} is not yet available.`);
|
|
315
|
-
const promise = new Promise((resolve,
|
|
312
|
+
const promise = new Promise((resolve, reject) => {
|
|
316
313
|
addListener(subject, (key) => {
|
|
317
314
|
if (key === property) {
|
|
318
315
|
resolve(state[key]);
|
|
319
316
|
return null;
|
|
320
317
|
}
|
|
321
318
|
if (key === null)
|
|
322
|
-
|
|
319
|
+
reject(new Error(`${subject} is destroyed.`));
|
|
323
320
|
});
|
|
324
321
|
});
|
|
325
322
|
throw Object.assign(promise, {
|
|
@@ -396,6 +393,132 @@ function uid() {
|
|
|
396
393
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
397
394
|
}
|
|
398
395
|
|
|
396
|
+
// src/context.ts
|
|
397
|
+
var Register = /* @__PURE__ */ new WeakMap();
|
|
398
|
+
var Context = class _Context {
|
|
399
|
+
constructor(inputs) {
|
|
400
|
+
this.downstream = /* @__PURE__ */ new WeakMap();
|
|
401
|
+
this.upstream = /* @__PURE__ */ new WeakMap();
|
|
402
|
+
this.layer = /* @__PURE__ */ new Map();
|
|
403
|
+
if (inputs)
|
|
404
|
+
this.include(inputs);
|
|
405
|
+
}
|
|
406
|
+
static get(from, callback) {
|
|
407
|
+
const waiting = Register.get(from);
|
|
408
|
+
if (!callback)
|
|
409
|
+
return waiting instanceof _Context ? waiting : void 0;
|
|
410
|
+
if (waiting instanceof _Context)
|
|
411
|
+
callback(waiting);
|
|
412
|
+
else if (waiting)
|
|
413
|
+
waiting.push(callback);
|
|
414
|
+
else
|
|
415
|
+
Register.set(from, [callback]);
|
|
416
|
+
}
|
|
417
|
+
key(T, upstream) {
|
|
418
|
+
const table = upstream ? this.upstream : this.downstream;
|
|
419
|
+
let key = table.get(T);
|
|
420
|
+
if (!key) {
|
|
421
|
+
key = Symbol(T.name + (upstream ? " request" : ""));
|
|
422
|
+
table.set(T, key);
|
|
423
|
+
}
|
|
424
|
+
return key;
|
|
425
|
+
}
|
|
426
|
+
has(model) {
|
|
427
|
+
const key = this.key(model.constructor, true);
|
|
428
|
+
const result = this[key];
|
|
429
|
+
const waiting = Register.get(model);
|
|
430
|
+
if (waiting instanceof Array)
|
|
431
|
+
waiting.forEach((cb) => cb(this));
|
|
432
|
+
Register.set(model, this);
|
|
433
|
+
if (typeof result == "function")
|
|
434
|
+
return result(model);
|
|
435
|
+
}
|
|
436
|
+
get(Type) {
|
|
437
|
+
const result = this[this.key(Type)];
|
|
438
|
+
if (result === null)
|
|
439
|
+
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
440
|
+
return result;
|
|
441
|
+
}
|
|
442
|
+
include(inputs, forEach) {
|
|
443
|
+
const init = /* @__PURE__ */ new Map();
|
|
444
|
+
Object.entries(inputs).forEach(([K, V]) => {
|
|
445
|
+
if (!(Model.is(V) || V instanceof Model))
|
|
446
|
+
throw new Error(`Context can only include Model or instance but got ${V}${K && " as " + K}.`);
|
|
447
|
+
});
|
|
448
|
+
for (const key in inputs) {
|
|
449
|
+
const input = inputs[key];
|
|
450
|
+
const exists = this.layer.get(key);
|
|
451
|
+
if (!exists) {
|
|
452
|
+
const instance = this.add(input);
|
|
453
|
+
this.layer.set(key, input);
|
|
454
|
+
init.set(instance, true);
|
|
455
|
+
} else if (exists !== input) {
|
|
456
|
+
this.pop();
|
|
457
|
+
this.id = uid();
|
|
458
|
+
this.include(inputs);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
for (const [model, explicit] of init) {
|
|
462
|
+
model.set();
|
|
463
|
+
if (forEach)
|
|
464
|
+
forEach(model, explicit);
|
|
465
|
+
for (const [_key, value] of model)
|
|
466
|
+
if (PARENT.get(value) === model) {
|
|
467
|
+
this.add(value, true);
|
|
468
|
+
init.set(value, false);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
put(T, I, implicit, writable) {
|
|
473
|
+
do {
|
|
474
|
+
const key = this.key(T, typeof I == "function");
|
|
475
|
+
const value = this.hasOwnProperty(key) ? null : I;
|
|
476
|
+
if (value || this[key] !== I && !implicit)
|
|
477
|
+
Object.defineProperty(this, key, {
|
|
478
|
+
configurable: true,
|
|
479
|
+
writable,
|
|
480
|
+
value
|
|
481
|
+
});
|
|
482
|
+
T = Object.getPrototypeOf(T);
|
|
483
|
+
} while (T !== Model);
|
|
484
|
+
}
|
|
485
|
+
add(input, implicit) {
|
|
486
|
+
let writable = true;
|
|
487
|
+
let T;
|
|
488
|
+
let I;
|
|
489
|
+
if (typeof input == "function") {
|
|
490
|
+
T = input;
|
|
491
|
+
I = new input();
|
|
492
|
+
} else {
|
|
493
|
+
I = input;
|
|
494
|
+
T = I.constructor;
|
|
495
|
+
writable = false;
|
|
496
|
+
}
|
|
497
|
+
this.has(I);
|
|
498
|
+
this.put(T, I, implicit, writable);
|
|
499
|
+
return I;
|
|
500
|
+
}
|
|
501
|
+
push(inputs) {
|
|
502
|
+
const next = Object.create(this);
|
|
503
|
+
next.layer = /* @__PURE__ */ new Map();
|
|
504
|
+
if (inputs)
|
|
505
|
+
next.include(inputs);
|
|
506
|
+
return next;
|
|
507
|
+
}
|
|
508
|
+
pop() {
|
|
509
|
+
const items = /* @__PURE__ */ new Set();
|
|
510
|
+
for (const key of Object.getOwnPropertySymbols(this)) {
|
|
511
|
+
const entry = Object.getOwnPropertyDescriptor(this, key);
|
|
512
|
+
if (entry.writable && entry.value)
|
|
513
|
+
items.add(entry.value);
|
|
514
|
+
delete this[key];
|
|
515
|
+
}
|
|
516
|
+
for (const model of items)
|
|
517
|
+
model.set(null);
|
|
518
|
+
this.layer.clear();
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
|
|
399
522
|
// src/instruction/use.ts
|
|
400
523
|
var INSTRUCT = /* @__PURE__ */ new Map();
|
|
401
524
|
function use(model, argument) {
|
|
@@ -467,20 +590,21 @@ Model.on((_, subject) => {
|
|
|
467
590
|
// src/instruction/get.ts
|
|
468
591
|
var STALE = /* @__PURE__ */ new WeakSet();
|
|
469
592
|
function get(arg0, arg1) {
|
|
470
|
-
return use((key, subject) => {
|
|
593
|
+
return use((key, subject, state) => {
|
|
471
594
|
let from = subject;
|
|
472
595
|
if (typeof arg0 == "symbol")
|
|
473
596
|
throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${from}.${key}. This is not allowed.`);
|
|
474
597
|
let source = (resolve) => resolve(from);
|
|
475
598
|
if (arg0 instanceof Model) {
|
|
476
599
|
from = arg0;
|
|
477
|
-
} else if (arg0
|
|
600
|
+
} else if (Model.is(arg0)) {
|
|
478
601
|
const hasParent = PARENT.get(from);
|
|
479
602
|
if (!hasParent) {
|
|
480
603
|
if (arg1 === true)
|
|
481
604
|
throw new Error(`${from} may only exist as a child of type ${arg0}.`);
|
|
482
605
|
source = (resolve) => {
|
|
483
|
-
|
|
606
|
+
Context.get(from, (context) => {
|
|
607
|
+
const got = context.get(arg0);
|
|
484
608
|
if (got)
|
|
485
609
|
resolve(got);
|
|
486
610
|
else if (arg1 !== false)
|
|
@@ -499,10 +623,8 @@ function get(arg0, arg1) {
|
|
|
499
623
|
let connect2 = function(model) {
|
|
500
624
|
reset = effect(model, (current) => {
|
|
501
625
|
proxy = current;
|
|
502
|
-
if (!
|
|
503
|
-
compute2(
|
|
504
|
-
else if (STALE.delete(compute2))
|
|
505
|
-
compute2();
|
|
626
|
+
if (!(key in state) || STALE.delete(compute2))
|
|
627
|
+
compute2(!reset);
|
|
506
628
|
return (didUpdate) => {
|
|
507
629
|
if (didUpdate) {
|
|
508
630
|
STALE.add(compute2);
|
|
@@ -666,172 +788,42 @@ function attempt(fn) {
|
|
|
666
788
|
return compute();
|
|
667
789
|
}
|
|
668
790
|
|
|
669
|
-
// src/context.ts
|
|
670
|
-
var Expects = /* @__PURE__ */ new WeakMap();
|
|
671
|
-
var Context = class {
|
|
672
|
-
constructor(inputs) {
|
|
673
|
-
this.downstream = /* @__PURE__ */ new WeakMap();
|
|
674
|
-
this.upstream = /* @__PURE__ */ new WeakMap();
|
|
675
|
-
this.layer = /* @__PURE__ */ new Map();
|
|
676
|
-
if (inputs)
|
|
677
|
-
this.include(inputs);
|
|
678
|
-
}
|
|
679
|
-
static request(type, from, callback) {
|
|
680
|
-
let map = Expects.get(from);
|
|
681
|
-
if (!map)
|
|
682
|
-
Expects.set(from, map = /* @__PURE__ */ new Map());
|
|
683
|
-
map.set(type, callback);
|
|
684
|
-
}
|
|
685
|
-
key(T, upstream) {
|
|
686
|
-
const table = upstream ? this.upstream : this.downstream;
|
|
687
|
-
let key = table.get(T);
|
|
688
|
-
if (!key) {
|
|
689
|
-
key = Symbol(T.name + (upstream ? " request" : ""));
|
|
690
|
-
table.set(T, key);
|
|
691
|
-
}
|
|
692
|
-
return key;
|
|
693
|
-
}
|
|
694
|
-
has(model) {
|
|
695
|
-
const key = this.key(model.constructor, true);
|
|
696
|
-
const result = this[key];
|
|
697
|
-
if (typeof result == "function")
|
|
698
|
-
return result(model);
|
|
699
|
-
}
|
|
700
|
-
get(Type) {
|
|
701
|
-
const result = this[this.key(Type)];
|
|
702
|
-
if (result === null)
|
|
703
|
-
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
704
|
-
return result;
|
|
705
|
-
}
|
|
706
|
-
include(inputs, forEach) {
|
|
707
|
-
const init = /* @__PURE__ */ new Map();
|
|
708
|
-
if (typeof inputs == "function" || inputs instanceof Model)
|
|
709
|
-
inputs = { [0]: inputs };
|
|
710
|
-
else if (!inputs)
|
|
711
|
-
reject(inputs);
|
|
712
|
-
Object.entries(inputs).forEach(([K, V]) => {
|
|
713
|
-
if (!(Model.is(V) || V instanceof Model))
|
|
714
|
-
reject(`${V} as ${K}`);
|
|
715
|
-
});
|
|
716
|
-
for (const key in inputs) {
|
|
717
|
-
const input = inputs[key];
|
|
718
|
-
const exists = this.layer.get(key);
|
|
719
|
-
if (!exists) {
|
|
720
|
-
const instance = this.add(input);
|
|
721
|
-
this.layer.set(key, input);
|
|
722
|
-
init.set(instance, true);
|
|
723
|
-
} else if (exists !== input) {
|
|
724
|
-
this.pop();
|
|
725
|
-
this.id = uid();
|
|
726
|
-
this.include(inputs);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
for (const [model, explicit] of init) {
|
|
730
|
-
if (forEach)
|
|
731
|
-
forEach(model, explicit);
|
|
732
|
-
model.set();
|
|
733
|
-
this.has(model);
|
|
734
|
-
const expects = Expects.get(model);
|
|
735
|
-
if (expects)
|
|
736
|
-
for (let [T, callback] of expects)
|
|
737
|
-
this.put(T, callback);
|
|
738
|
-
for (const [_key, value] of model)
|
|
739
|
-
if (PARENT.get(value) === model) {
|
|
740
|
-
this.add(value, true);
|
|
741
|
-
init.set(value, false);
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
put(T, I, implicit, writable) {
|
|
746
|
-
do {
|
|
747
|
-
const key = this.key(T, typeof I == "function");
|
|
748
|
-
const value = this.hasOwnProperty(key) ? null : I;
|
|
749
|
-
if (value || this[key] !== I && !implicit)
|
|
750
|
-
Object.defineProperty(this, key, {
|
|
751
|
-
configurable: true,
|
|
752
|
-
writable,
|
|
753
|
-
value
|
|
754
|
-
});
|
|
755
|
-
T = Object.getPrototypeOf(T);
|
|
756
|
-
} while (T !== Model);
|
|
757
|
-
}
|
|
758
|
-
add(input, implicit) {
|
|
759
|
-
let writable = true;
|
|
760
|
-
let T;
|
|
761
|
-
let I;
|
|
762
|
-
if (typeof input == "function") {
|
|
763
|
-
T = input;
|
|
764
|
-
I = new input();
|
|
765
|
-
} else {
|
|
766
|
-
I = input;
|
|
767
|
-
T = I.constructor;
|
|
768
|
-
writable = false;
|
|
769
|
-
}
|
|
770
|
-
this.put(T, I, implicit, writable);
|
|
771
|
-
return I;
|
|
772
|
-
}
|
|
773
|
-
push(inputs) {
|
|
774
|
-
const next = Object.create(this);
|
|
775
|
-
next.layer = /* @__PURE__ */ new Map();
|
|
776
|
-
if (inputs)
|
|
777
|
-
next.include(inputs);
|
|
778
|
-
return next;
|
|
779
|
-
}
|
|
780
|
-
pop() {
|
|
781
|
-
const items = /* @__PURE__ */ new Set();
|
|
782
|
-
for (const key of Object.getOwnPropertySymbols(this)) {
|
|
783
|
-
const entry = Object.getOwnPropertyDescriptor(this, key);
|
|
784
|
-
if (entry.writable && entry.value)
|
|
785
|
-
items.add(entry.value);
|
|
786
|
-
delete this[key];
|
|
787
|
-
}
|
|
788
|
-
for (const model of items)
|
|
789
|
-
model.set(null);
|
|
790
|
-
this.layer.clear();
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
function reject(argument) {
|
|
794
|
-
throw new Error(`Context can only include Model or instance but got ${argument}.`);
|
|
795
|
-
}
|
|
796
|
-
|
|
797
791
|
// src/instruction/has.ts
|
|
798
792
|
function has(type, argument) {
|
|
799
793
|
return use((key, subject, state) => {
|
|
794
|
+
const expect = (callback) => Context.get(subject, (context) => context.put(type, callback));
|
|
800
795
|
if (typeof argument == "boolean") {
|
|
801
|
-
|
|
796
|
+
expect((model) => {
|
|
802
797
|
subject.set(key, model);
|
|
803
798
|
const remove = () => {
|
|
804
|
-
drop();
|
|
805
799
|
if (state[key] === model)
|
|
806
800
|
delete state[key];
|
|
807
801
|
};
|
|
808
|
-
|
|
802
|
+
model.get(null, remove);
|
|
809
803
|
return remove;
|
|
810
804
|
});
|
|
811
805
|
return { get: argument };
|
|
812
806
|
}
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
if (
|
|
807
|
+
const value = /* @__PURE__ */ new Set();
|
|
808
|
+
expect((model) => {
|
|
809
|
+
if (value.has(model))
|
|
816
810
|
return;
|
|
817
811
|
const remove = typeof argument == "function" ? argument(model) : void 0;
|
|
818
812
|
if (remove === false)
|
|
819
813
|
return;
|
|
820
|
-
|
|
814
|
+
value.add(model);
|
|
821
815
|
subject.set(key);
|
|
822
816
|
const done = () => {
|
|
823
817
|
drop();
|
|
824
818
|
if (typeof remove == "function")
|
|
825
819
|
remove();
|
|
826
|
-
|
|
820
|
+
value.delete(model);
|
|
827
821
|
subject.set(key);
|
|
828
822
|
};
|
|
829
823
|
const drop = model.get(null, done);
|
|
830
824
|
return done;
|
|
831
825
|
});
|
|
832
|
-
return {
|
|
833
|
-
value: children
|
|
834
|
-
};
|
|
826
|
+
return { value };
|
|
835
827
|
});
|
|
836
828
|
}
|
|
837
829
|
export {
|
package/package.json
CHANGED