@expressive/mvc 0.37.0 → 0.39.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 +20 -9
- package/dist/index.js +175 -109
- package/dist/index.mjs +174 -109
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -181,6 +181,7 @@ declare class Model {
|
|
|
181
181
|
* Register a callback to run when any instance of this Model is updated.
|
|
182
182
|
*/
|
|
183
183
|
static on<T extends Model>(this: Model.Type<T>, listener: Model.OnEvent<T>): () => boolean;
|
|
184
|
+
static at<T extends Model>(this: Model.Type<T>, from: Model, cb: (got: T | undefined) => void): void;
|
|
184
185
|
}
|
|
185
186
|
|
|
186
187
|
declare function add<T = any>(instruction: Model.Instruction): T;
|
|
@@ -196,9 +197,9 @@ declare namespace get {
|
|
|
196
197
|
* will be made available to child upon this request.
|
|
197
198
|
*
|
|
198
199
|
* @param Type - Type of controller compatible with this class.
|
|
199
|
-
* @param
|
|
200
|
+
* @param expectParent - If true, will throw if Model is created without a parent.
|
|
200
201
|
*/
|
|
201
|
-
declare function get<T extends Model>(Type: Model.Type<T>,
|
|
202
|
+
declare function get<T extends Model>(Type: Model.Type<T>, asParent?: true): T;
|
|
202
203
|
/**
|
|
203
204
|
* Fetches and assigns the controller which spawned this host.
|
|
204
205
|
* When parent assigns an instance via `use()` directive, it
|
|
@@ -207,7 +208,7 @@ declare function get<T extends Model>(Type: Model.Type<T>, required?: true): T;
|
|
|
207
208
|
* @param Type - Type of controller compatible with this class.
|
|
208
209
|
* @param required - If false, property may be undefined. Otherwise will throw suspense.
|
|
209
210
|
*/
|
|
210
|
-
declare function get<T extends Model>(Type: Model.Type<T>, required
|
|
211
|
+
declare function get<T extends Model>(Type: Model.Type<T>, required?: false): T | undefined;
|
|
211
212
|
/**
|
|
212
213
|
* Implement a computed value from a foreign model. Output will be generated by provided function,
|
|
213
214
|
* where the foreign model will be passed to that function.
|
|
@@ -345,19 +346,29 @@ declare function use<T extends Model>(model: T, ready?: (i: T) => void): T;
|
|
|
345
346
|
/** Create a managed object with observable entries. */
|
|
346
347
|
declare function use<T extends {}, O = use.Object<T>>(data: T, ready?: (object: O) => void): O;
|
|
347
348
|
|
|
349
|
+
declare namespace has {
|
|
350
|
+
type Callback<T = any> = (model: T) => void | boolean | (() => void);
|
|
351
|
+
}
|
|
352
|
+
declare function has<T extends Model>(type: Model.Type<T>, one: true): T;
|
|
353
|
+
declare function has<T extends Model>(type: Model.Type<T>, required: boolean): T | undefined;
|
|
354
|
+
declare function has<T extends Model>(type: Model.Type<T>, arg?: has.Callback<T>): Set<T>;
|
|
355
|
+
|
|
348
356
|
declare namespace Context {
|
|
349
357
|
type Input = Model | Model.New<Model> | Record<string | number, Model | Model.New<Model>>;
|
|
350
358
|
}
|
|
351
359
|
declare class Context {
|
|
352
|
-
static
|
|
353
|
-
|
|
354
|
-
protected
|
|
360
|
+
static request<T extends Model>(type: Model.Type<T>, from: Model, callback: (got: T) => void): void;
|
|
361
|
+
id: string;
|
|
362
|
+
protected downstream: WeakMap<Model.Type<Model>, symbol>;
|
|
363
|
+
protected upstream: WeakMap<Model.Type<Model>, symbol>;
|
|
355
364
|
protected layer: Map<string | number, Model | Model.Type<Model>>;
|
|
356
365
|
constructor(inputs?: Context.Input);
|
|
357
|
-
|
|
366
|
+
key(T: Model.Type, upstream?: boolean): keyof this;
|
|
367
|
+
has(model: Model): (() => void) | undefined;
|
|
358
368
|
get<T extends Model>(Type: Model.Type<T>): T | undefined;
|
|
359
369
|
include(inputs: Context.Input): Map<Model, boolean>;
|
|
360
|
-
|
|
370
|
+
put<T extends Model>(T: Model.New<T>, I: T | ((model: T) => void), implicit?: boolean, writable?: boolean): void;
|
|
371
|
+
add<T extends Model>(input: T | Model.New<T>, implicit?: boolean): T;
|
|
361
372
|
push(inputs?: Context.Input): this;
|
|
362
373
|
pop(): void;
|
|
363
374
|
}
|
|
@@ -379,4 +390,4 @@ declare global {
|
|
|
379
390
|
}
|
|
380
391
|
}
|
|
381
392
|
|
|
382
|
-
export { Context, Model, add, Model as default, get, ref, set, use };
|
|
393
|
+
export { Context, Model, add, Model as default, get, has, ref, set, use };
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,7 @@ __export(src_exports, {
|
|
|
25
25
|
add: () => add,
|
|
26
26
|
default: () => Model,
|
|
27
27
|
get: () => get,
|
|
28
|
+
has: () => has,
|
|
28
29
|
ref: () => ref,
|
|
29
30
|
set: () => set,
|
|
30
31
|
use: () => use
|
|
@@ -295,6 +296,9 @@ var Model = class _Model {
|
|
|
295
296
|
notify.add(listener);
|
|
296
297
|
return () => notify.delete(listener);
|
|
297
298
|
}
|
|
299
|
+
static at(from, cb) {
|
|
300
|
+
throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
|
|
301
|
+
}
|
|
298
302
|
};
|
|
299
303
|
define(Model.prototype, "toString", {
|
|
300
304
|
value() {
|
|
@@ -412,111 +416,6 @@ Model.on((_, subject) => {
|
|
|
412
416
|
return null;
|
|
413
417
|
});
|
|
414
418
|
|
|
415
|
-
// src/context.ts
|
|
416
|
-
var Context = class {
|
|
417
|
-
constructor(inputs) {
|
|
418
|
-
this.table = /* @__PURE__ */ new WeakMap();
|
|
419
|
-
this.layer = /* @__PURE__ */ new Map();
|
|
420
|
-
if (inputs)
|
|
421
|
-
this.include(inputs);
|
|
422
|
-
}
|
|
423
|
-
static get() {
|
|
424
|
-
throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
|
|
425
|
-
}
|
|
426
|
-
has(T) {
|
|
427
|
-
let key = this.table.get(T);
|
|
428
|
-
if (!key) {
|
|
429
|
-
key = Symbol(T.name);
|
|
430
|
-
this.table.set(T, key);
|
|
431
|
-
}
|
|
432
|
-
return key;
|
|
433
|
-
}
|
|
434
|
-
get(Type) {
|
|
435
|
-
const result = this[this.has(Type)];
|
|
436
|
-
if (result === null)
|
|
437
|
-
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
438
|
-
return result;
|
|
439
|
-
}
|
|
440
|
-
include(inputs) {
|
|
441
|
-
const init = /* @__PURE__ */ new Map();
|
|
442
|
-
if (typeof inputs == "function" || inputs instanceof Model)
|
|
443
|
-
inputs = { [0]: inputs };
|
|
444
|
-
else if (!inputs)
|
|
445
|
-
reject(inputs);
|
|
446
|
-
Object.entries(inputs).forEach(([K, V]) => {
|
|
447
|
-
if (!(Model.is(V) || V instanceof Model))
|
|
448
|
-
reject(`${V} as ${K}`);
|
|
449
|
-
});
|
|
450
|
-
for (const key in inputs) {
|
|
451
|
-
const input = inputs[key];
|
|
452
|
-
const exists = this.layer.get(key);
|
|
453
|
-
if (!exists) {
|
|
454
|
-
const instance = this.add(input);
|
|
455
|
-
this.layer.set(key, input);
|
|
456
|
-
init.set(instance, true);
|
|
457
|
-
} else if (exists !== input) {
|
|
458
|
-
this.pop();
|
|
459
|
-
this.key = uid();
|
|
460
|
-
return this.include(inputs);
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
for (const [model] of init)
|
|
464
|
-
for (const [_key, value] of model)
|
|
465
|
-
if (PARENT.get(value) === model) {
|
|
466
|
-
this.add(value, true);
|
|
467
|
-
init.set(value, false);
|
|
468
|
-
}
|
|
469
|
-
return init;
|
|
470
|
-
}
|
|
471
|
-
add(input, implicit) {
|
|
472
|
-
let writable = true;
|
|
473
|
-
let T;
|
|
474
|
-
let I;
|
|
475
|
-
if (typeof input == "function") {
|
|
476
|
-
T = input;
|
|
477
|
-
I = input.new();
|
|
478
|
-
} else {
|
|
479
|
-
I = input;
|
|
480
|
-
T = I.constructor;
|
|
481
|
-
writable = false;
|
|
482
|
-
}
|
|
483
|
-
do {
|
|
484
|
-
const key = this.has(T);
|
|
485
|
-
const value = this.hasOwnProperty(key) ? null : I;
|
|
486
|
-
if (value || I !== this[key] && !implicit)
|
|
487
|
-
Object.defineProperty(this, key, {
|
|
488
|
-
configurable: true,
|
|
489
|
-
writable,
|
|
490
|
-
value
|
|
491
|
-
});
|
|
492
|
-
T = Object.getPrototypeOf(T);
|
|
493
|
-
} while (T !== Model);
|
|
494
|
-
return I;
|
|
495
|
-
}
|
|
496
|
-
push(inputs) {
|
|
497
|
-
const next = Object.create(this);
|
|
498
|
-
next.layer = /* @__PURE__ */ new Map();
|
|
499
|
-
if (inputs)
|
|
500
|
-
next.include(inputs);
|
|
501
|
-
return next;
|
|
502
|
-
}
|
|
503
|
-
pop() {
|
|
504
|
-
const items = /* @__PURE__ */ new Set();
|
|
505
|
-
for (const key of Object.getOwnPropertySymbols(this)) {
|
|
506
|
-
const entry = Object.getOwnPropertyDescriptor(this, key);
|
|
507
|
-
if (entry.writable && entry.value)
|
|
508
|
-
items.add(entry.value);
|
|
509
|
-
delete this[key];
|
|
510
|
-
}
|
|
511
|
-
for (const model of items)
|
|
512
|
-
model.set(null);
|
|
513
|
-
this.layer.clear();
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
|
-
function reject(argument) {
|
|
517
|
-
throw new Error(`Context can only include Model or instance but got ${argument}.`);
|
|
518
|
-
}
|
|
519
|
-
|
|
520
419
|
// src/instruction/get.ts
|
|
521
420
|
function get(arg0, arg1) {
|
|
522
421
|
return add((key, subject) => {
|
|
@@ -532,10 +431,9 @@ function get(arg0, arg1) {
|
|
|
532
431
|
if (arg1 === true)
|
|
533
432
|
throw new Error(`${from} may only exist as a child of type ${arg0}.`);
|
|
534
433
|
source = (resolve) => {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
resolve(model);
|
|
434
|
+
arg0.at(from, (got) => {
|
|
435
|
+
if (got)
|
|
436
|
+
resolve(got);
|
|
539
437
|
else if (arg1 !== false)
|
|
540
438
|
throw new Error(`Required ${arg0} not found in context for ${from}.`);
|
|
541
439
|
});
|
|
@@ -753,12 +651,180 @@ function use(value, argument) {
|
|
|
753
651
|
return output;
|
|
754
652
|
});
|
|
755
653
|
}
|
|
654
|
+
|
|
655
|
+
// src/context.ts
|
|
656
|
+
var Expects = /* @__PURE__ */ new WeakMap();
|
|
657
|
+
var Context = class {
|
|
658
|
+
constructor(inputs) {
|
|
659
|
+
this.downstream = /* @__PURE__ */ new WeakMap();
|
|
660
|
+
this.upstream = /* @__PURE__ */ new WeakMap();
|
|
661
|
+
this.layer = /* @__PURE__ */ new Map();
|
|
662
|
+
if (inputs)
|
|
663
|
+
this.include(inputs);
|
|
664
|
+
}
|
|
665
|
+
static request(type, from, callback) {
|
|
666
|
+
let map = Expects.get(from);
|
|
667
|
+
if (!map)
|
|
668
|
+
Expects.set(from, map = /* @__PURE__ */ new Map());
|
|
669
|
+
map.set(type, callback);
|
|
670
|
+
}
|
|
671
|
+
key(T, upstream) {
|
|
672
|
+
const table = upstream ? this.upstream : this.downstream;
|
|
673
|
+
let key = table.get(T);
|
|
674
|
+
if (!key) {
|
|
675
|
+
key = Symbol(T.name + (upstream ? " request" : ""));
|
|
676
|
+
table.set(T, key);
|
|
677
|
+
}
|
|
678
|
+
return key;
|
|
679
|
+
}
|
|
680
|
+
has(model) {
|
|
681
|
+
const key = this.key(model.constructor, true);
|
|
682
|
+
const result = this[key];
|
|
683
|
+
if (typeof result == "function")
|
|
684
|
+
return result(model);
|
|
685
|
+
}
|
|
686
|
+
get(Type) {
|
|
687
|
+
const result = this[this.key(Type)];
|
|
688
|
+
if (result === null)
|
|
689
|
+
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
690
|
+
return result;
|
|
691
|
+
}
|
|
692
|
+
include(inputs) {
|
|
693
|
+
const init = /* @__PURE__ */ new Map();
|
|
694
|
+
if (typeof inputs == "function" || inputs instanceof Model)
|
|
695
|
+
inputs = { [0]: inputs };
|
|
696
|
+
else if (!inputs)
|
|
697
|
+
reject(inputs);
|
|
698
|
+
Object.entries(inputs).forEach(([K, V]) => {
|
|
699
|
+
if (!(Model.is(V) || V instanceof Model))
|
|
700
|
+
reject(`${V} as ${K}`);
|
|
701
|
+
});
|
|
702
|
+
for (const key in inputs) {
|
|
703
|
+
const input = inputs[key];
|
|
704
|
+
const exists = this.layer.get(key);
|
|
705
|
+
if (!exists) {
|
|
706
|
+
const instance = this.add(input);
|
|
707
|
+
this.layer.set(key, input);
|
|
708
|
+
init.set(instance, true);
|
|
709
|
+
} else if (exists !== input) {
|
|
710
|
+
this.pop();
|
|
711
|
+
this.id = uid();
|
|
712
|
+
return this.include(inputs);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
for (const [model] of init) {
|
|
716
|
+
this.has(model);
|
|
717
|
+
const expects = Expects.get(model);
|
|
718
|
+
if (expects)
|
|
719
|
+
for (let [T, callback] of expects)
|
|
720
|
+
this.put(T, callback);
|
|
721
|
+
for (const [_key, value] of model)
|
|
722
|
+
if (PARENT.get(value) === model) {
|
|
723
|
+
this.add(value, true);
|
|
724
|
+
init.set(value, false);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
return init;
|
|
728
|
+
}
|
|
729
|
+
put(T, I, implicit, writable) {
|
|
730
|
+
do {
|
|
731
|
+
const key = this.key(T, typeof I == "function");
|
|
732
|
+
const value = this.hasOwnProperty(key) ? null : I;
|
|
733
|
+
if (value || this[key] !== I && !implicit)
|
|
734
|
+
Object.defineProperty(this, key, {
|
|
735
|
+
configurable: true,
|
|
736
|
+
writable,
|
|
737
|
+
value
|
|
738
|
+
});
|
|
739
|
+
T = Object.getPrototypeOf(T);
|
|
740
|
+
} while (T !== Model);
|
|
741
|
+
}
|
|
742
|
+
add(input, implicit) {
|
|
743
|
+
let writable = true;
|
|
744
|
+
let T;
|
|
745
|
+
let I;
|
|
746
|
+
if (typeof input == "function") {
|
|
747
|
+
T = input;
|
|
748
|
+
I = input.new();
|
|
749
|
+
} else {
|
|
750
|
+
I = input;
|
|
751
|
+
T = I.constructor;
|
|
752
|
+
writable = false;
|
|
753
|
+
}
|
|
754
|
+
this.put(T, I, implicit, writable);
|
|
755
|
+
return I;
|
|
756
|
+
}
|
|
757
|
+
push(inputs) {
|
|
758
|
+
const next = Object.create(this);
|
|
759
|
+
next.layer = /* @__PURE__ */ new Map();
|
|
760
|
+
if (inputs)
|
|
761
|
+
next.include(inputs);
|
|
762
|
+
return next;
|
|
763
|
+
}
|
|
764
|
+
pop() {
|
|
765
|
+
const items = /* @__PURE__ */ new Set();
|
|
766
|
+
for (const key of Object.getOwnPropertySymbols(this)) {
|
|
767
|
+
const entry = Object.getOwnPropertyDescriptor(this, key);
|
|
768
|
+
if (entry.writable && entry.value)
|
|
769
|
+
items.add(entry.value);
|
|
770
|
+
delete this[key];
|
|
771
|
+
}
|
|
772
|
+
for (const model of items)
|
|
773
|
+
model.set(null);
|
|
774
|
+
this.layer.clear();
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
function reject(argument) {
|
|
778
|
+
throw new Error(`Context can only include Model or instance but got ${argument}.`);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// src/instruction/has.ts
|
|
782
|
+
function has(type, argument) {
|
|
783
|
+
return add((key, subject, state) => {
|
|
784
|
+
if (typeof argument == "boolean") {
|
|
785
|
+
Context.request(type, subject, (model) => {
|
|
786
|
+
const remove = () => {
|
|
787
|
+
drop();
|
|
788
|
+
if (state[key] === model)
|
|
789
|
+
delete state[key];
|
|
790
|
+
};
|
|
791
|
+
subject.set(key, model);
|
|
792
|
+
const drop = model.get(null, remove);
|
|
793
|
+
return remove;
|
|
794
|
+
});
|
|
795
|
+
return { get: argument };
|
|
796
|
+
}
|
|
797
|
+
const children = /* @__PURE__ */ new Set();
|
|
798
|
+
Context.request(type, subject, (model) => {
|
|
799
|
+
if (children.has(model))
|
|
800
|
+
return;
|
|
801
|
+
const remove = typeof argument == "function" ? argument(model) : void 0;
|
|
802
|
+
if (remove === false)
|
|
803
|
+
return;
|
|
804
|
+
children.add(model);
|
|
805
|
+
subject.set(key);
|
|
806
|
+
const done = () => {
|
|
807
|
+
drop();
|
|
808
|
+
if (typeof remove == "function")
|
|
809
|
+
remove();
|
|
810
|
+
children.delete(model);
|
|
811
|
+
subject.set(key);
|
|
812
|
+
};
|
|
813
|
+
const drop = model.get(null, done);
|
|
814
|
+
return done;
|
|
815
|
+
});
|
|
816
|
+
return {
|
|
817
|
+
value: children
|
|
818
|
+
};
|
|
819
|
+
});
|
|
820
|
+
}
|
|
756
821
|
// Annotate the CommonJS export names for ESM import in node:
|
|
757
822
|
0 && (module.exports = {
|
|
758
823
|
Context,
|
|
759
824
|
Model,
|
|
760
825
|
add,
|
|
761
826
|
get,
|
|
827
|
+
has,
|
|
762
828
|
ref,
|
|
763
829
|
set,
|
|
764
830
|
use
|
package/dist/index.mjs
CHANGED
|
@@ -262,6 +262,9 @@ var Model = class _Model {
|
|
|
262
262
|
notify.add(listener);
|
|
263
263
|
return () => notify.delete(listener);
|
|
264
264
|
}
|
|
265
|
+
static at(from, cb) {
|
|
266
|
+
throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
|
|
267
|
+
}
|
|
265
268
|
};
|
|
266
269
|
define(Model.prototype, "toString", {
|
|
267
270
|
value() {
|
|
@@ -379,111 +382,6 @@ Model.on((_, subject) => {
|
|
|
379
382
|
return null;
|
|
380
383
|
});
|
|
381
384
|
|
|
382
|
-
// src/context.ts
|
|
383
|
-
var Context = class {
|
|
384
|
-
constructor(inputs) {
|
|
385
|
-
this.table = /* @__PURE__ */ new WeakMap();
|
|
386
|
-
this.layer = /* @__PURE__ */ new Map();
|
|
387
|
-
if (inputs)
|
|
388
|
-
this.include(inputs);
|
|
389
|
-
}
|
|
390
|
-
static get() {
|
|
391
|
-
throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
|
|
392
|
-
}
|
|
393
|
-
has(T) {
|
|
394
|
-
let key = this.table.get(T);
|
|
395
|
-
if (!key) {
|
|
396
|
-
key = Symbol(T.name);
|
|
397
|
-
this.table.set(T, key);
|
|
398
|
-
}
|
|
399
|
-
return key;
|
|
400
|
-
}
|
|
401
|
-
get(Type) {
|
|
402
|
-
const result = this[this.has(Type)];
|
|
403
|
-
if (result === null)
|
|
404
|
-
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
405
|
-
return result;
|
|
406
|
-
}
|
|
407
|
-
include(inputs) {
|
|
408
|
-
const init = /* @__PURE__ */ new Map();
|
|
409
|
-
if (typeof inputs == "function" || inputs instanceof Model)
|
|
410
|
-
inputs = { [0]: inputs };
|
|
411
|
-
else if (!inputs)
|
|
412
|
-
reject(inputs);
|
|
413
|
-
Object.entries(inputs).forEach(([K, V]) => {
|
|
414
|
-
if (!(Model.is(V) || V instanceof Model))
|
|
415
|
-
reject(`${V} as ${K}`);
|
|
416
|
-
});
|
|
417
|
-
for (const key in inputs) {
|
|
418
|
-
const input = inputs[key];
|
|
419
|
-
const exists = this.layer.get(key);
|
|
420
|
-
if (!exists) {
|
|
421
|
-
const instance = this.add(input);
|
|
422
|
-
this.layer.set(key, input);
|
|
423
|
-
init.set(instance, true);
|
|
424
|
-
} else if (exists !== input) {
|
|
425
|
-
this.pop();
|
|
426
|
-
this.key = uid();
|
|
427
|
-
return this.include(inputs);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
for (const [model] of init)
|
|
431
|
-
for (const [_key, value] of model)
|
|
432
|
-
if (PARENT.get(value) === model) {
|
|
433
|
-
this.add(value, true);
|
|
434
|
-
init.set(value, false);
|
|
435
|
-
}
|
|
436
|
-
return init;
|
|
437
|
-
}
|
|
438
|
-
add(input, implicit) {
|
|
439
|
-
let writable = true;
|
|
440
|
-
let T;
|
|
441
|
-
let I;
|
|
442
|
-
if (typeof input == "function") {
|
|
443
|
-
T = input;
|
|
444
|
-
I = input.new();
|
|
445
|
-
} else {
|
|
446
|
-
I = input;
|
|
447
|
-
T = I.constructor;
|
|
448
|
-
writable = false;
|
|
449
|
-
}
|
|
450
|
-
do {
|
|
451
|
-
const key = this.has(T);
|
|
452
|
-
const value = this.hasOwnProperty(key) ? null : I;
|
|
453
|
-
if (value || I !== this[key] && !implicit)
|
|
454
|
-
Object.defineProperty(this, key, {
|
|
455
|
-
configurable: true,
|
|
456
|
-
writable,
|
|
457
|
-
value
|
|
458
|
-
});
|
|
459
|
-
T = Object.getPrototypeOf(T);
|
|
460
|
-
} while (T !== Model);
|
|
461
|
-
return I;
|
|
462
|
-
}
|
|
463
|
-
push(inputs) {
|
|
464
|
-
const next = Object.create(this);
|
|
465
|
-
next.layer = /* @__PURE__ */ new Map();
|
|
466
|
-
if (inputs)
|
|
467
|
-
next.include(inputs);
|
|
468
|
-
return next;
|
|
469
|
-
}
|
|
470
|
-
pop() {
|
|
471
|
-
const items = /* @__PURE__ */ new Set();
|
|
472
|
-
for (const key of Object.getOwnPropertySymbols(this)) {
|
|
473
|
-
const entry = Object.getOwnPropertyDescriptor(this, key);
|
|
474
|
-
if (entry.writable && entry.value)
|
|
475
|
-
items.add(entry.value);
|
|
476
|
-
delete this[key];
|
|
477
|
-
}
|
|
478
|
-
for (const model of items)
|
|
479
|
-
model.set(null);
|
|
480
|
-
this.layer.clear();
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
function reject(argument) {
|
|
484
|
-
throw new Error(`Context can only include Model or instance but got ${argument}.`);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
385
|
// src/instruction/get.ts
|
|
488
386
|
function get(arg0, arg1) {
|
|
489
387
|
return add((key, subject) => {
|
|
@@ -499,10 +397,9 @@ function get(arg0, arg1) {
|
|
|
499
397
|
if (arg1 === true)
|
|
500
398
|
throw new Error(`${from} may only exist as a child of type ${arg0}.`);
|
|
501
399
|
source = (resolve) => {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
resolve(model);
|
|
400
|
+
arg0.at(from, (got) => {
|
|
401
|
+
if (got)
|
|
402
|
+
resolve(got);
|
|
506
403
|
else if (arg1 !== false)
|
|
507
404
|
throw new Error(`Required ${arg0} not found in context for ${from}.`);
|
|
508
405
|
});
|
|
@@ -720,12 +617,180 @@ function use(value, argument) {
|
|
|
720
617
|
return output;
|
|
721
618
|
});
|
|
722
619
|
}
|
|
620
|
+
|
|
621
|
+
// src/context.ts
|
|
622
|
+
var Expects = /* @__PURE__ */ new WeakMap();
|
|
623
|
+
var Context = class {
|
|
624
|
+
constructor(inputs) {
|
|
625
|
+
this.downstream = /* @__PURE__ */ new WeakMap();
|
|
626
|
+
this.upstream = /* @__PURE__ */ new WeakMap();
|
|
627
|
+
this.layer = /* @__PURE__ */ new Map();
|
|
628
|
+
if (inputs)
|
|
629
|
+
this.include(inputs);
|
|
630
|
+
}
|
|
631
|
+
static request(type, from, callback) {
|
|
632
|
+
let map = Expects.get(from);
|
|
633
|
+
if (!map)
|
|
634
|
+
Expects.set(from, map = /* @__PURE__ */ new Map());
|
|
635
|
+
map.set(type, callback);
|
|
636
|
+
}
|
|
637
|
+
key(T, upstream) {
|
|
638
|
+
const table = upstream ? this.upstream : this.downstream;
|
|
639
|
+
let key = table.get(T);
|
|
640
|
+
if (!key) {
|
|
641
|
+
key = Symbol(T.name + (upstream ? " request" : ""));
|
|
642
|
+
table.set(T, key);
|
|
643
|
+
}
|
|
644
|
+
return key;
|
|
645
|
+
}
|
|
646
|
+
has(model) {
|
|
647
|
+
const key = this.key(model.constructor, true);
|
|
648
|
+
const result = this[key];
|
|
649
|
+
if (typeof result == "function")
|
|
650
|
+
return result(model);
|
|
651
|
+
}
|
|
652
|
+
get(Type) {
|
|
653
|
+
const result = this[this.key(Type)];
|
|
654
|
+
if (result === null)
|
|
655
|
+
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
656
|
+
return result;
|
|
657
|
+
}
|
|
658
|
+
include(inputs) {
|
|
659
|
+
const init = /* @__PURE__ */ new Map();
|
|
660
|
+
if (typeof inputs == "function" || inputs instanceof Model)
|
|
661
|
+
inputs = { [0]: inputs };
|
|
662
|
+
else if (!inputs)
|
|
663
|
+
reject(inputs);
|
|
664
|
+
Object.entries(inputs).forEach(([K, V]) => {
|
|
665
|
+
if (!(Model.is(V) || V instanceof Model))
|
|
666
|
+
reject(`${V} as ${K}`);
|
|
667
|
+
});
|
|
668
|
+
for (const key in inputs) {
|
|
669
|
+
const input = inputs[key];
|
|
670
|
+
const exists = this.layer.get(key);
|
|
671
|
+
if (!exists) {
|
|
672
|
+
const instance = this.add(input);
|
|
673
|
+
this.layer.set(key, input);
|
|
674
|
+
init.set(instance, true);
|
|
675
|
+
} else if (exists !== input) {
|
|
676
|
+
this.pop();
|
|
677
|
+
this.id = uid();
|
|
678
|
+
return this.include(inputs);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
for (const [model] of init) {
|
|
682
|
+
this.has(model);
|
|
683
|
+
const expects = Expects.get(model);
|
|
684
|
+
if (expects)
|
|
685
|
+
for (let [T, callback] of expects)
|
|
686
|
+
this.put(T, callback);
|
|
687
|
+
for (const [_key, value] of model)
|
|
688
|
+
if (PARENT.get(value) === model) {
|
|
689
|
+
this.add(value, true);
|
|
690
|
+
init.set(value, false);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
return init;
|
|
694
|
+
}
|
|
695
|
+
put(T, I, implicit, writable) {
|
|
696
|
+
do {
|
|
697
|
+
const key = this.key(T, typeof I == "function");
|
|
698
|
+
const value = this.hasOwnProperty(key) ? null : I;
|
|
699
|
+
if (value || this[key] !== I && !implicit)
|
|
700
|
+
Object.defineProperty(this, key, {
|
|
701
|
+
configurable: true,
|
|
702
|
+
writable,
|
|
703
|
+
value
|
|
704
|
+
});
|
|
705
|
+
T = Object.getPrototypeOf(T);
|
|
706
|
+
} while (T !== Model);
|
|
707
|
+
}
|
|
708
|
+
add(input, implicit) {
|
|
709
|
+
let writable = true;
|
|
710
|
+
let T;
|
|
711
|
+
let I;
|
|
712
|
+
if (typeof input == "function") {
|
|
713
|
+
T = input;
|
|
714
|
+
I = input.new();
|
|
715
|
+
} else {
|
|
716
|
+
I = input;
|
|
717
|
+
T = I.constructor;
|
|
718
|
+
writable = false;
|
|
719
|
+
}
|
|
720
|
+
this.put(T, I, implicit, writable);
|
|
721
|
+
return I;
|
|
722
|
+
}
|
|
723
|
+
push(inputs) {
|
|
724
|
+
const next = Object.create(this);
|
|
725
|
+
next.layer = /* @__PURE__ */ new Map();
|
|
726
|
+
if (inputs)
|
|
727
|
+
next.include(inputs);
|
|
728
|
+
return next;
|
|
729
|
+
}
|
|
730
|
+
pop() {
|
|
731
|
+
const items = /* @__PURE__ */ new Set();
|
|
732
|
+
for (const key of Object.getOwnPropertySymbols(this)) {
|
|
733
|
+
const entry = Object.getOwnPropertyDescriptor(this, key);
|
|
734
|
+
if (entry.writable && entry.value)
|
|
735
|
+
items.add(entry.value);
|
|
736
|
+
delete this[key];
|
|
737
|
+
}
|
|
738
|
+
for (const model of items)
|
|
739
|
+
model.set(null);
|
|
740
|
+
this.layer.clear();
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
function reject(argument) {
|
|
744
|
+
throw new Error(`Context can only include Model or instance but got ${argument}.`);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// src/instruction/has.ts
|
|
748
|
+
function has(type, argument) {
|
|
749
|
+
return add((key, subject, state) => {
|
|
750
|
+
if (typeof argument == "boolean") {
|
|
751
|
+
Context.request(type, subject, (model) => {
|
|
752
|
+
const remove = () => {
|
|
753
|
+
drop();
|
|
754
|
+
if (state[key] === model)
|
|
755
|
+
delete state[key];
|
|
756
|
+
};
|
|
757
|
+
subject.set(key, model);
|
|
758
|
+
const drop = model.get(null, remove);
|
|
759
|
+
return remove;
|
|
760
|
+
});
|
|
761
|
+
return { get: argument };
|
|
762
|
+
}
|
|
763
|
+
const children = /* @__PURE__ */ new Set();
|
|
764
|
+
Context.request(type, subject, (model) => {
|
|
765
|
+
if (children.has(model))
|
|
766
|
+
return;
|
|
767
|
+
const remove = typeof argument == "function" ? argument(model) : void 0;
|
|
768
|
+
if (remove === false)
|
|
769
|
+
return;
|
|
770
|
+
children.add(model);
|
|
771
|
+
subject.set(key);
|
|
772
|
+
const done = () => {
|
|
773
|
+
drop();
|
|
774
|
+
if (typeof remove == "function")
|
|
775
|
+
remove();
|
|
776
|
+
children.delete(model);
|
|
777
|
+
subject.set(key);
|
|
778
|
+
};
|
|
779
|
+
const drop = model.get(null, done);
|
|
780
|
+
return done;
|
|
781
|
+
});
|
|
782
|
+
return {
|
|
783
|
+
value: children
|
|
784
|
+
};
|
|
785
|
+
});
|
|
786
|
+
}
|
|
723
787
|
export {
|
|
724
788
|
Context,
|
|
725
789
|
Model,
|
|
726
790
|
add,
|
|
727
791
|
Model as default,
|
|
728
792
|
get,
|
|
793
|
+
has,
|
|
729
794
|
ref,
|
|
730
795
|
set,
|
|
731
796
|
use
|
package/package.json
CHANGED