@expressive/mvc 0.46.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 +7 -19
- package/dist/index.js +229 -238
- package/dist/index.mjs +229 -237
- 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,11 +198,8 @@ 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
|
-
declare function add<T = any>(instruction: Model.Instruction): T;
|
|
205
|
-
|
|
206
203
|
declare namespace get {
|
|
207
204
|
type Function<T, S = any> = (on: S, key: string) => T;
|
|
208
205
|
type Factory<T, S = any> = (this: S, key: string, thisArg: S) => T;
|
|
@@ -346,19 +343,9 @@ declare function set<T>(factory: set.Factory<T> | Promise<T>, required?: boolean
|
|
|
346
343
|
*/
|
|
347
344
|
declare function set<T>(value: T | undefined, onUpdate: set.Callback<T>): T;
|
|
348
345
|
|
|
349
|
-
|
|
350
|
-
declare function use<T extends Model>(): T | undefined;
|
|
351
|
-
/** Create a new child instance of model. */
|
|
346
|
+
declare function use<T = any>(instruction: Model.Instruction): T;
|
|
347
|
+
declare function use<T extends Model>(Type: Model.Type<T>, required: false): T | undefined;
|
|
352
348
|
declare function use<T extends Model>(Type: Model.Type<T>, ready?: (i: T) => void): T;
|
|
353
|
-
/**
|
|
354
|
-
* Use existing model as a child of model assigned to.
|
|
355
|
-
*
|
|
356
|
-
* Note: If `peer` is not already initialized before parent is
|
|
357
|
-
* (created with `new` as opposed to create method), that model will
|
|
358
|
-
* attach this via `parent()` instruction. It will not, however, if
|
|
359
|
-
* already active.
|
|
360
|
-
**/
|
|
361
|
-
declare function use<T extends Model>(model: T, ready?: (i: T) => void): T;
|
|
362
349
|
|
|
363
350
|
declare namespace has {
|
|
364
351
|
type Callback<T = any> = (model: T) => void | boolean | (() => void);
|
|
@@ -368,10 +355,11 @@ declare function has<T extends Model>(type: Model.Type<T>, required: boolean): T
|
|
|
368
355
|
declare function has<T extends Model>(type: Model.Type<T>, arg?: has.Callback<T>): Set<T>;
|
|
369
356
|
|
|
370
357
|
declare namespace Context {
|
|
371
|
-
type Input =
|
|
358
|
+
type Input = Record<string | number, Model | Model.Type<Model>>;
|
|
372
359
|
}
|
|
373
360
|
declare class Context {
|
|
374
|
-
static
|
|
361
|
+
static get<T extends Model>(on: Model, callback: ((got: Context) => void)): void;
|
|
362
|
+
static get<T extends Model>(on: Model): Context | undefined;
|
|
375
363
|
id: string;
|
|
376
364
|
protected downstream: WeakMap<Model.Type<Model>, symbol>;
|
|
377
365
|
protected upstream: WeakMap<Model.Type<Model>, symbol>;
|
|
@@ -404,4 +392,4 @@ declare global {
|
|
|
404
392
|
}
|
|
405
393
|
}
|
|
406
394
|
|
|
407
|
-
export { Context, Model,
|
|
395
|
+
export { Context, Model, Model as default, get, has, ref, set, use };
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,6 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
Context: () => Context,
|
|
24
24
|
Model: () => Model,
|
|
25
|
-
add: () => add,
|
|
26
25
|
default: () => Model,
|
|
27
26
|
get: () => get,
|
|
28
27
|
has: () => has,
|
|
@@ -151,7 +150,7 @@ function effect(target, callback) {
|
|
|
151
150
|
}
|
|
152
151
|
|
|
153
152
|
// src/model.ts
|
|
154
|
-
var
|
|
153
|
+
var EXPORT;
|
|
155
154
|
var NAMES = /* @__PURE__ */ new WeakMap();
|
|
156
155
|
var STATE = /* @__PURE__ */ new WeakMap();
|
|
157
156
|
var NOTIFY = /* @__PURE__ */ new WeakMap();
|
|
@@ -197,7 +196,7 @@ var Model = class _Model {
|
|
|
197
196
|
for (const key in this) {
|
|
198
197
|
const desc = Object.getOwnPropertyDescriptor(this, key);
|
|
199
198
|
if ("value" in desc) {
|
|
200
|
-
|
|
199
|
+
update(this, key, desc.value, true);
|
|
201
200
|
define(this, key, {
|
|
202
201
|
configurable: false,
|
|
203
202
|
set: (x) => update(this, key, x),
|
|
@@ -207,6 +206,8 @@ var Model = class _Model {
|
|
|
207
206
|
});
|
|
208
207
|
}
|
|
209
208
|
}
|
|
209
|
+
if (!PARENT.has(this))
|
|
210
|
+
PARENT.set(this, null);
|
|
210
211
|
addListener(this, () => {
|
|
211
212
|
if (!done)
|
|
212
213
|
throw new Error(`Tried to destroy ${this} but not fully initialized.`);
|
|
@@ -234,16 +235,16 @@ var Model = class _Model {
|
|
|
234
235
|
}
|
|
235
236
|
if (arg1 === void 0) {
|
|
236
237
|
const values = {};
|
|
237
|
-
const current = !
|
|
238
|
+
const current = !EXPORT && (EXPORT = /* @__PURE__ */ new Map([[self, values]]));
|
|
238
239
|
for (let [key, value] of self) {
|
|
239
|
-
if (
|
|
240
|
-
value =
|
|
240
|
+
if (EXPORT.has(value))
|
|
241
|
+
value = EXPORT.get(value);
|
|
241
242
|
else if (value && typeof value.get === "function")
|
|
242
|
-
|
|
243
|
+
EXPORT.set(value, value = value.get());
|
|
243
244
|
values[key] = value;
|
|
244
245
|
}
|
|
245
246
|
if (current)
|
|
246
|
-
|
|
247
|
+
EXPORT = void 0;
|
|
247
248
|
return Object.freeze(values);
|
|
248
249
|
}
|
|
249
250
|
if (typeof arg2 == "function") {
|
|
@@ -322,9 +323,6 @@ var Model = class _Model {
|
|
|
322
323
|
notify.add(listener);
|
|
323
324
|
return () => notify.delete(listener);
|
|
324
325
|
}
|
|
325
|
-
static at(from, cb) {
|
|
326
|
-
throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
|
|
327
|
-
}
|
|
328
326
|
};
|
|
329
327
|
define(Model.prototype, "toString", {
|
|
330
328
|
value() {
|
|
@@ -344,14 +342,14 @@ function fetch(subject, property, required) {
|
|
|
344
342
|
return value;
|
|
345
343
|
}
|
|
346
344
|
const error = new Error(`${subject}.${property} is not yet available.`);
|
|
347
|
-
const promise = new Promise((resolve,
|
|
345
|
+
const promise = new Promise((resolve, reject) => {
|
|
348
346
|
addListener(subject, (key) => {
|
|
349
347
|
if (key === property) {
|
|
350
348
|
resolve(state[key]);
|
|
351
349
|
return null;
|
|
352
350
|
}
|
|
353
351
|
if (key === null)
|
|
354
|
-
|
|
352
|
+
reject(new Error(`${subject} is destroyed.`));
|
|
355
353
|
});
|
|
356
354
|
});
|
|
357
355
|
throw Object.assign(promise, {
|
|
@@ -368,6 +366,10 @@ function update(subject, key, value, silent) {
|
|
|
368
366
|
const previous = state[key];
|
|
369
367
|
if (value === previous)
|
|
370
368
|
return true;
|
|
369
|
+
if (value instanceof Model && !PARENT.has(value)) {
|
|
370
|
+
PARENT.set(value, subject);
|
|
371
|
+
event(value, true);
|
|
372
|
+
}
|
|
371
373
|
state[key] = value;
|
|
372
374
|
if (silent !== true)
|
|
373
375
|
push(subject, key);
|
|
@@ -424,26 +426,168 @@ function uid() {
|
|
|
424
426
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
425
427
|
}
|
|
426
428
|
|
|
427
|
-
// src/
|
|
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
|
+
|
|
555
|
+
// src/instruction/use.ts
|
|
428
556
|
var INSTRUCT = /* @__PURE__ */ new Map();
|
|
429
|
-
function
|
|
557
|
+
function use(model, argument) {
|
|
430
558
|
const token = Symbol("instruction");
|
|
431
|
-
|
|
559
|
+
if (Model.is(model)) {
|
|
560
|
+
const type = model;
|
|
561
|
+
const value = new model();
|
|
562
|
+
model = (key, subject) => {
|
|
563
|
+
function set2(next) {
|
|
564
|
+
if (next ? !(next instanceof type) : argument !== false)
|
|
565
|
+
throw new Error(`${subject}.${key} expected Model of type ${type} but got ${next && next.constructor}.`);
|
|
566
|
+
update(subject, key, next);
|
|
567
|
+
if (next && typeof argument == "function")
|
|
568
|
+
argument(next);
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
571
|
+
set2(value);
|
|
572
|
+
return { set: set2, value };
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
INSTRUCT.set(token, model);
|
|
432
576
|
return token;
|
|
433
577
|
}
|
|
434
578
|
Model.on((_, subject) => {
|
|
435
579
|
const state = STATE.get(subject);
|
|
436
|
-
Object.
|
|
437
|
-
|
|
438
|
-
|
|
580
|
+
const props = Object.getOwnPropertyDescriptors(subject);
|
|
581
|
+
for (const key in props) {
|
|
582
|
+
const { value } = props[key];
|
|
439
583
|
const instruction = INSTRUCT.get(value);
|
|
440
584
|
if (!instruction)
|
|
441
|
-
|
|
585
|
+
continue;
|
|
442
586
|
INSTRUCT.delete(value);
|
|
443
587
|
delete subject[key];
|
|
444
588
|
const output = instruction.call(subject, key, subject, state);
|
|
445
589
|
if (!output)
|
|
446
|
-
|
|
590
|
+
continue;
|
|
447
591
|
const desc = typeof output == "object" ? output : { get: output };
|
|
448
592
|
const { enumerable = true } = desc;
|
|
449
593
|
if ("value" in desc)
|
|
@@ -472,26 +616,28 @@ Model.on((_, subject) => {
|
|
|
472
616
|
);
|
|
473
617
|
}
|
|
474
618
|
});
|
|
475
|
-
}
|
|
619
|
+
}
|
|
476
620
|
return null;
|
|
477
621
|
});
|
|
478
622
|
|
|
479
623
|
// src/instruction/get.ts
|
|
624
|
+
var STALE = /* @__PURE__ */ new WeakSet();
|
|
480
625
|
function get(arg0, arg1) {
|
|
481
|
-
return
|
|
626
|
+
return use((key, subject, state) => {
|
|
482
627
|
let from = subject;
|
|
483
628
|
if (typeof arg0 == "symbol")
|
|
484
629
|
throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${from}.${key}. This is not allowed.`);
|
|
485
630
|
let source = (resolve) => resolve(from);
|
|
486
|
-
if (arg0 instanceof Model)
|
|
631
|
+
if (arg0 instanceof Model) {
|
|
487
632
|
from = arg0;
|
|
488
|
-
else if (Model.is(arg0)) {
|
|
633
|
+
} else if (Model.is(arg0)) {
|
|
489
634
|
const hasParent = PARENT.get(from);
|
|
490
635
|
if (!hasParent) {
|
|
491
636
|
if (arg1 === true)
|
|
492
637
|
throw new Error(`${from} may only exist as a child of type ${arg0}.`);
|
|
493
638
|
source = (resolve) => {
|
|
494
|
-
|
|
639
|
+
Context.get(from, (context) => {
|
|
640
|
+
const got = context.get(arg0);
|
|
495
641
|
if (got)
|
|
496
642
|
resolve(got);
|
|
497
643
|
else if (arg1 !== false)
|
|
@@ -502,63 +648,59 @@ function get(arg0, arg1) {
|
|
|
502
648
|
from = hasParent;
|
|
503
649
|
else
|
|
504
650
|
throw new Error(`New ${from} created as child of ${hasParent}, but must be instanceof ${arg0}.`);
|
|
505
|
-
} else
|
|
651
|
+
} else {
|
|
506
652
|
const fn = METHOD.get(arg0) || arg0;
|
|
507
653
|
arg1 = (p, k) => fn.call(p, k, p);
|
|
508
654
|
}
|
|
509
|
-
if (typeof arg1 == "function")
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
655
|
+
if (typeof arg1 == "function") {
|
|
656
|
+
let connect2 = function(model) {
|
|
657
|
+
reset = effect(model, (current) => {
|
|
658
|
+
proxy = current;
|
|
659
|
+
if (!(key in state) || STALE.delete(compute2))
|
|
660
|
+
compute2(!reset);
|
|
661
|
+
return (didUpdate) => {
|
|
662
|
+
if (didUpdate) {
|
|
663
|
+
STALE.add(compute2);
|
|
664
|
+
push(subject, key, true);
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
});
|
|
668
|
+
}, compute2 = function(initial) {
|
|
669
|
+
let next;
|
|
670
|
+
try {
|
|
671
|
+
next = getter.call(proxy, proxy, key);
|
|
672
|
+
} catch (err) {
|
|
673
|
+
console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key}.`);
|
|
674
|
+
if (initial)
|
|
675
|
+
throw err;
|
|
676
|
+
console.error(err);
|
|
531
677
|
}
|
|
678
|
+
update(subject, key, next, !isAsync);
|
|
532
679
|
};
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
}
|
|
552
|
-
if (STALE.delete(compute2))
|
|
553
|
-
compute2();
|
|
554
|
-
return fetch(subject, key, !proxy);
|
|
555
|
-
};
|
|
680
|
+
var connect = connect2, compute = compute2;
|
|
681
|
+
const getter = arg1;
|
|
682
|
+
let reset;
|
|
683
|
+
let isAsync;
|
|
684
|
+
let proxy;
|
|
685
|
+
return () => {
|
|
686
|
+
if (!proxy) {
|
|
687
|
+
source(connect2);
|
|
688
|
+
isAsync = true;
|
|
689
|
+
}
|
|
690
|
+
if (STALE.delete(compute2))
|
|
691
|
+
compute2();
|
|
692
|
+
return fetch(subject, key, !proxy);
|
|
693
|
+
};
|
|
694
|
+
} else
|
|
695
|
+
source((got) => subject.set(key, got));
|
|
696
|
+
return { get: arg1 };
|
|
697
|
+
});
|
|
556
698
|
}
|
|
557
699
|
|
|
558
700
|
// src/instruction/ref.ts
|
|
559
701
|
var define2 = Object.defineProperty;
|
|
560
702
|
function ref(arg, arg2) {
|
|
561
|
-
return
|
|
703
|
+
return use((key, subject, state) => {
|
|
562
704
|
let value = {};
|
|
563
705
|
if (arg === subject)
|
|
564
706
|
subject.get(() => {
|
|
@@ -608,7 +750,7 @@ function ref(arg, arg2) {
|
|
|
608
750
|
|
|
609
751
|
// src/instruction/set.ts
|
|
610
752
|
function set(value, argument) {
|
|
611
|
-
return
|
|
753
|
+
return use((key, subject) => {
|
|
612
754
|
const output = {};
|
|
613
755
|
if (typeof value == "function" || value instanceof Promise) {
|
|
614
756
|
let init2 = function() {
|
|
@@ -664,11 +806,11 @@ function set(value, argument) {
|
|
|
664
806
|
function attempt(fn) {
|
|
665
807
|
function retry(err) {
|
|
666
808
|
if (err instanceof Promise)
|
|
667
|
-
return err.then(
|
|
809
|
+
return err.then(compute);
|
|
668
810
|
else
|
|
669
811
|
throw err;
|
|
670
812
|
}
|
|
671
|
-
function
|
|
813
|
+
function compute() {
|
|
672
814
|
try {
|
|
673
815
|
const output = fn();
|
|
674
816
|
return output instanceof Promise ? output.catch(retry) : output;
|
|
@@ -676,202 +818,51 @@ function attempt(fn) {
|
|
|
676
818
|
return retry(err);
|
|
677
819
|
}
|
|
678
820
|
}
|
|
679
|
-
return
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
// src/instruction/use.ts
|
|
683
|
-
function use(value, argument) {
|
|
684
|
-
return add((property, subject) => {
|
|
685
|
-
if (typeof value === "function")
|
|
686
|
-
value = new value();
|
|
687
|
-
function set2(next) {
|
|
688
|
-
if (value instanceof Model && !(next instanceof value.constructor))
|
|
689
|
-
throw new Error(`${subject}.${property} expected Model of type ${value.constructor} but got ${next}.`);
|
|
690
|
-
if (next instanceof Model) {
|
|
691
|
-
PARENT.set(next, subject);
|
|
692
|
-
event(next, true);
|
|
693
|
-
}
|
|
694
|
-
if (typeof argument == "function")
|
|
695
|
-
argument(next);
|
|
696
|
-
}
|
|
697
|
-
set2(value);
|
|
698
|
-
return { set: set2, value };
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
|
|
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}.`);
|
|
821
|
+
return compute();
|
|
828
822
|
}
|
|
829
823
|
|
|
830
824
|
// src/instruction/has.ts
|
|
831
825
|
function has(type, argument) {
|
|
832
|
-
return
|
|
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:
|
|
871
863
|
0 && (module.exports = {
|
|
872
864
|
Context,
|
|
873
865
|
Model,
|
|
874
|
-
add,
|
|
875
866
|
get,
|
|
876
867
|
has,
|
|
877
868
|
ref,
|
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();
|
|
@@ -163,7 +163,7 @@ var Model = class _Model {
|
|
|
163
163
|
for (const key in this) {
|
|
164
164
|
const desc = Object.getOwnPropertyDescriptor(this, key);
|
|
165
165
|
if ("value" in desc) {
|
|
166
|
-
|
|
166
|
+
update(this, key, desc.value, true);
|
|
167
167
|
define(this, key, {
|
|
168
168
|
configurable: false,
|
|
169
169
|
set: (x) => update(this, key, x),
|
|
@@ -173,6 +173,8 @@ var Model = class _Model {
|
|
|
173
173
|
});
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
+
if (!PARENT.has(this))
|
|
177
|
+
PARENT.set(this, null);
|
|
176
178
|
addListener(this, () => {
|
|
177
179
|
if (!done)
|
|
178
180
|
throw new Error(`Tried to destroy ${this} but not fully initialized.`);
|
|
@@ -200,16 +202,16 @@ var Model = class _Model {
|
|
|
200
202
|
}
|
|
201
203
|
if (arg1 === void 0) {
|
|
202
204
|
const values = {};
|
|
203
|
-
const current = !
|
|
205
|
+
const current = !EXPORT && (EXPORT = /* @__PURE__ */ new Map([[self, values]]));
|
|
204
206
|
for (let [key, value] of self) {
|
|
205
|
-
if (
|
|
206
|
-
value =
|
|
207
|
+
if (EXPORT.has(value))
|
|
208
|
+
value = EXPORT.get(value);
|
|
207
209
|
else if (value && typeof value.get === "function")
|
|
208
|
-
|
|
210
|
+
EXPORT.set(value, value = value.get());
|
|
209
211
|
values[key] = value;
|
|
210
212
|
}
|
|
211
213
|
if (current)
|
|
212
|
-
|
|
214
|
+
EXPORT = void 0;
|
|
213
215
|
return Object.freeze(values);
|
|
214
216
|
}
|
|
215
217
|
if (typeof arg2 == "function") {
|
|
@@ -288,9 +290,6 @@ var Model = class _Model {
|
|
|
288
290
|
notify.add(listener);
|
|
289
291
|
return () => notify.delete(listener);
|
|
290
292
|
}
|
|
291
|
-
static at(from, cb) {
|
|
292
|
-
throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
|
|
293
|
-
}
|
|
294
293
|
};
|
|
295
294
|
define(Model.prototype, "toString", {
|
|
296
295
|
value() {
|
|
@@ -310,14 +309,14 @@ function fetch(subject, property, required) {
|
|
|
310
309
|
return value;
|
|
311
310
|
}
|
|
312
311
|
const error = new Error(`${subject}.${property} is not yet available.`);
|
|
313
|
-
const promise = new Promise((resolve,
|
|
312
|
+
const promise = new Promise((resolve, reject) => {
|
|
314
313
|
addListener(subject, (key) => {
|
|
315
314
|
if (key === property) {
|
|
316
315
|
resolve(state[key]);
|
|
317
316
|
return null;
|
|
318
317
|
}
|
|
319
318
|
if (key === null)
|
|
320
|
-
|
|
319
|
+
reject(new Error(`${subject} is destroyed.`));
|
|
321
320
|
});
|
|
322
321
|
});
|
|
323
322
|
throw Object.assign(promise, {
|
|
@@ -334,6 +333,10 @@ function update(subject, key, value, silent) {
|
|
|
334
333
|
const previous = state[key];
|
|
335
334
|
if (value === previous)
|
|
336
335
|
return true;
|
|
336
|
+
if (value instanceof Model && !PARENT.has(value)) {
|
|
337
|
+
PARENT.set(value, subject);
|
|
338
|
+
event(value, true);
|
|
339
|
+
}
|
|
337
340
|
state[key] = value;
|
|
338
341
|
if (silent !== true)
|
|
339
342
|
push(subject, key);
|
|
@@ -390,26 +393,168 @@ function uid() {
|
|
|
390
393
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
391
394
|
}
|
|
392
395
|
|
|
393
|
-
// src/
|
|
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
|
+
|
|
522
|
+
// src/instruction/use.ts
|
|
394
523
|
var INSTRUCT = /* @__PURE__ */ new Map();
|
|
395
|
-
function
|
|
524
|
+
function use(model, argument) {
|
|
396
525
|
const token = Symbol("instruction");
|
|
397
|
-
|
|
526
|
+
if (Model.is(model)) {
|
|
527
|
+
const type = model;
|
|
528
|
+
const value = new model();
|
|
529
|
+
model = (key, subject) => {
|
|
530
|
+
function set2(next) {
|
|
531
|
+
if (next ? !(next instanceof type) : argument !== false)
|
|
532
|
+
throw new Error(`${subject}.${key} expected Model of type ${type} but got ${next && next.constructor}.`);
|
|
533
|
+
update(subject, key, next);
|
|
534
|
+
if (next && typeof argument == "function")
|
|
535
|
+
argument(next);
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
set2(value);
|
|
539
|
+
return { set: set2, value };
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
INSTRUCT.set(token, model);
|
|
398
543
|
return token;
|
|
399
544
|
}
|
|
400
545
|
Model.on((_, subject) => {
|
|
401
546
|
const state = STATE.get(subject);
|
|
402
|
-
Object.
|
|
403
|
-
|
|
404
|
-
|
|
547
|
+
const props = Object.getOwnPropertyDescriptors(subject);
|
|
548
|
+
for (const key in props) {
|
|
549
|
+
const { value } = props[key];
|
|
405
550
|
const instruction = INSTRUCT.get(value);
|
|
406
551
|
if (!instruction)
|
|
407
|
-
|
|
552
|
+
continue;
|
|
408
553
|
INSTRUCT.delete(value);
|
|
409
554
|
delete subject[key];
|
|
410
555
|
const output = instruction.call(subject, key, subject, state);
|
|
411
556
|
if (!output)
|
|
412
|
-
|
|
557
|
+
continue;
|
|
413
558
|
const desc = typeof output == "object" ? output : { get: output };
|
|
414
559
|
const { enumerable = true } = desc;
|
|
415
560
|
if ("value" in desc)
|
|
@@ -438,26 +583,28 @@ Model.on((_, subject) => {
|
|
|
438
583
|
);
|
|
439
584
|
}
|
|
440
585
|
});
|
|
441
|
-
}
|
|
586
|
+
}
|
|
442
587
|
return null;
|
|
443
588
|
});
|
|
444
589
|
|
|
445
590
|
// src/instruction/get.ts
|
|
591
|
+
var STALE = /* @__PURE__ */ new WeakSet();
|
|
446
592
|
function get(arg0, arg1) {
|
|
447
|
-
return
|
|
593
|
+
return use((key, subject, state) => {
|
|
448
594
|
let from = subject;
|
|
449
595
|
if (typeof arg0 == "symbol")
|
|
450
596
|
throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${from}.${key}. This is not allowed.`);
|
|
451
597
|
let source = (resolve) => resolve(from);
|
|
452
|
-
if (arg0 instanceof Model)
|
|
598
|
+
if (arg0 instanceof Model) {
|
|
453
599
|
from = arg0;
|
|
454
|
-
else if (Model.is(arg0)) {
|
|
600
|
+
} else if (Model.is(arg0)) {
|
|
455
601
|
const hasParent = PARENT.get(from);
|
|
456
602
|
if (!hasParent) {
|
|
457
603
|
if (arg1 === true)
|
|
458
604
|
throw new Error(`${from} may only exist as a child of type ${arg0}.`);
|
|
459
605
|
source = (resolve) => {
|
|
460
|
-
|
|
606
|
+
Context.get(from, (context) => {
|
|
607
|
+
const got = context.get(arg0);
|
|
461
608
|
if (got)
|
|
462
609
|
resolve(got);
|
|
463
610
|
else if (arg1 !== false)
|
|
@@ -468,63 +615,59 @@ function get(arg0, arg1) {
|
|
|
468
615
|
from = hasParent;
|
|
469
616
|
else
|
|
470
617
|
throw new Error(`New ${from} created as child of ${hasParent}, but must be instanceof ${arg0}.`);
|
|
471
|
-
} else
|
|
618
|
+
} else {
|
|
472
619
|
const fn = METHOD.get(arg0) || arg0;
|
|
473
620
|
arg1 = (p, k) => fn.call(p, k, p);
|
|
474
621
|
}
|
|
475
|
-
if (typeof arg1 == "function")
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
622
|
+
if (typeof arg1 == "function") {
|
|
623
|
+
let connect2 = function(model) {
|
|
624
|
+
reset = effect(model, (current) => {
|
|
625
|
+
proxy = current;
|
|
626
|
+
if (!(key in state) || STALE.delete(compute2))
|
|
627
|
+
compute2(!reset);
|
|
628
|
+
return (didUpdate) => {
|
|
629
|
+
if (didUpdate) {
|
|
630
|
+
STALE.add(compute2);
|
|
631
|
+
push(subject, key, true);
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
});
|
|
635
|
+
}, compute2 = function(initial) {
|
|
636
|
+
let next;
|
|
637
|
+
try {
|
|
638
|
+
next = getter.call(proxy, proxy, key);
|
|
639
|
+
} catch (err) {
|
|
640
|
+
console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key}.`);
|
|
641
|
+
if (initial)
|
|
642
|
+
throw err;
|
|
643
|
+
console.error(err);
|
|
497
644
|
}
|
|
645
|
+
update(subject, key, next, !isAsync);
|
|
498
646
|
};
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
}
|
|
518
|
-
if (STALE.delete(compute2))
|
|
519
|
-
compute2();
|
|
520
|
-
return fetch(subject, key, !proxy);
|
|
521
|
-
};
|
|
647
|
+
var connect = connect2, compute = compute2;
|
|
648
|
+
const getter = arg1;
|
|
649
|
+
let reset;
|
|
650
|
+
let isAsync;
|
|
651
|
+
let proxy;
|
|
652
|
+
return () => {
|
|
653
|
+
if (!proxy) {
|
|
654
|
+
source(connect2);
|
|
655
|
+
isAsync = true;
|
|
656
|
+
}
|
|
657
|
+
if (STALE.delete(compute2))
|
|
658
|
+
compute2();
|
|
659
|
+
return fetch(subject, key, !proxy);
|
|
660
|
+
};
|
|
661
|
+
} else
|
|
662
|
+
source((got) => subject.set(key, got));
|
|
663
|
+
return { get: arg1 };
|
|
664
|
+
});
|
|
522
665
|
}
|
|
523
666
|
|
|
524
667
|
// src/instruction/ref.ts
|
|
525
668
|
var define2 = Object.defineProperty;
|
|
526
669
|
function ref(arg, arg2) {
|
|
527
|
-
return
|
|
670
|
+
return use((key, subject, state) => {
|
|
528
671
|
let value = {};
|
|
529
672
|
if (arg === subject)
|
|
530
673
|
subject.get(() => {
|
|
@@ -574,7 +717,7 @@ function ref(arg, arg2) {
|
|
|
574
717
|
|
|
575
718
|
// src/instruction/set.ts
|
|
576
719
|
function set(value, argument) {
|
|
577
|
-
return
|
|
720
|
+
return use((key, subject) => {
|
|
578
721
|
const output = {};
|
|
579
722
|
if (typeof value == "function" || value instanceof Promise) {
|
|
580
723
|
let init2 = function() {
|
|
@@ -630,11 +773,11 @@ function set(value, argument) {
|
|
|
630
773
|
function attempt(fn) {
|
|
631
774
|
function retry(err) {
|
|
632
775
|
if (err instanceof Promise)
|
|
633
|
-
return err.then(
|
|
776
|
+
return err.then(compute);
|
|
634
777
|
else
|
|
635
778
|
throw err;
|
|
636
779
|
}
|
|
637
|
-
function
|
|
780
|
+
function compute() {
|
|
638
781
|
try {
|
|
639
782
|
const output = fn();
|
|
640
783
|
return output instanceof Promise ? output.catch(retry) : output;
|
|
@@ -642,201 +785,50 @@ function attempt(fn) {
|
|
|
642
785
|
return retry(err);
|
|
643
786
|
}
|
|
644
787
|
}
|
|
645
|
-
return
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
// src/instruction/use.ts
|
|
649
|
-
function use(value, argument) {
|
|
650
|
-
return add((property, subject) => {
|
|
651
|
-
if (typeof value === "function")
|
|
652
|
-
value = new value();
|
|
653
|
-
function set2(next) {
|
|
654
|
-
if (value instanceof Model && !(next instanceof value.constructor))
|
|
655
|
-
throw new Error(`${subject}.${property} expected Model of type ${value.constructor} but got ${next}.`);
|
|
656
|
-
if (next instanceof Model) {
|
|
657
|
-
PARENT.set(next, subject);
|
|
658
|
-
event(next, true);
|
|
659
|
-
}
|
|
660
|
-
if (typeof argument == "function")
|
|
661
|
-
argument(next);
|
|
662
|
-
}
|
|
663
|
-
set2(value);
|
|
664
|
-
return { set: set2, value };
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
// src/context.ts
|
|
669
|
-
var Expects = /* @__PURE__ */ new WeakMap();
|
|
670
|
-
var Context = class {
|
|
671
|
-
constructor(inputs) {
|
|
672
|
-
this.downstream = /* @__PURE__ */ new WeakMap();
|
|
673
|
-
this.upstream = /* @__PURE__ */ new WeakMap();
|
|
674
|
-
this.layer = /* @__PURE__ */ new Map();
|
|
675
|
-
if (inputs)
|
|
676
|
-
this.include(inputs);
|
|
677
|
-
}
|
|
678
|
-
static request(type, from, callback) {
|
|
679
|
-
let map = Expects.get(from);
|
|
680
|
-
if (!map)
|
|
681
|
-
Expects.set(from, map = /* @__PURE__ */ new Map());
|
|
682
|
-
map.set(type, callback);
|
|
683
|
-
}
|
|
684
|
-
key(T, upstream) {
|
|
685
|
-
const table = upstream ? this.upstream : this.downstream;
|
|
686
|
-
let key = table.get(T);
|
|
687
|
-
if (!key) {
|
|
688
|
-
key = Symbol(T.name + (upstream ? " request" : ""));
|
|
689
|
-
table.set(T, key);
|
|
690
|
-
}
|
|
691
|
-
return key;
|
|
692
|
-
}
|
|
693
|
-
has(model) {
|
|
694
|
-
const key = this.key(model.constructor, true);
|
|
695
|
-
const result = this[key];
|
|
696
|
-
if (typeof result == "function")
|
|
697
|
-
return result(model);
|
|
698
|
-
}
|
|
699
|
-
get(Type) {
|
|
700
|
-
const result = this[this.key(Type)];
|
|
701
|
-
if (result === null)
|
|
702
|
-
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
703
|
-
return result;
|
|
704
|
-
}
|
|
705
|
-
include(inputs, forEach) {
|
|
706
|
-
const init = /* @__PURE__ */ new Map();
|
|
707
|
-
if (typeof inputs == "function" || inputs instanceof Model)
|
|
708
|
-
inputs = { [0]: inputs };
|
|
709
|
-
else if (!inputs)
|
|
710
|
-
reject(inputs);
|
|
711
|
-
Object.entries(inputs).forEach(([K, V]) => {
|
|
712
|
-
if (!(Model.is(V) || V instanceof Model))
|
|
713
|
-
reject(`${V} as ${K}`);
|
|
714
|
-
});
|
|
715
|
-
for (const key in inputs) {
|
|
716
|
-
const input = inputs[key];
|
|
717
|
-
const exists = this.layer.get(key);
|
|
718
|
-
if (!exists) {
|
|
719
|
-
const instance = this.add(input);
|
|
720
|
-
this.layer.set(key, input);
|
|
721
|
-
init.set(instance, true);
|
|
722
|
-
} else if (exists !== input) {
|
|
723
|
-
this.pop();
|
|
724
|
-
this.id = uid();
|
|
725
|
-
this.include(inputs);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
for (const [model, explicit] of init) {
|
|
729
|
-
if (forEach)
|
|
730
|
-
forEach(model, explicit);
|
|
731
|
-
model.set();
|
|
732
|
-
this.has(model);
|
|
733
|
-
const expects = Expects.get(model);
|
|
734
|
-
if (expects)
|
|
735
|
-
for (let [T, callback] of expects)
|
|
736
|
-
this.put(T, callback);
|
|
737
|
-
for (const [_key, value] of model)
|
|
738
|
-
if (PARENT.get(value) === model) {
|
|
739
|
-
this.add(value, true);
|
|
740
|
-
init.set(value, false);
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
put(T, I, implicit, writable) {
|
|
745
|
-
do {
|
|
746
|
-
const key = this.key(T, typeof I == "function");
|
|
747
|
-
const value = this.hasOwnProperty(key) ? null : I;
|
|
748
|
-
if (value || this[key] !== I && !implicit)
|
|
749
|
-
Object.defineProperty(this, key, {
|
|
750
|
-
configurable: true,
|
|
751
|
-
writable,
|
|
752
|
-
value
|
|
753
|
-
});
|
|
754
|
-
T = Object.getPrototypeOf(T);
|
|
755
|
-
} while (T !== Model);
|
|
756
|
-
}
|
|
757
|
-
add(input, implicit) {
|
|
758
|
-
let writable = true;
|
|
759
|
-
let T;
|
|
760
|
-
let I;
|
|
761
|
-
if (typeof input == "function") {
|
|
762
|
-
T = input;
|
|
763
|
-
I = new input();
|
|
764
|
-
} else {
|
|
765
|
-
I = input;
|
|
766
|
-
T = I.constructor;
|
|
767
|
-
writable = false;
|
|
768
|
-
}
|
|
769
|
-
this.put(T, I, implicit, writable);
|
|
770
|
-
return I;
|
|
771
|
-
}
|
|
772
|
-
push(inputs) {
|
|
773
|
-
const next = Object.create(this);
|
|
774
|
-
next.layer = /* @__PURE__ */ new Map();
|
|
775
|
-
if (inputs)
|
|
776
|
-
next.include(inputs);
|
|
777
|
-
return next;
|
|
778
|
-
}
|
|
779
|
-
pop() {
|
|
780
|
-
const items = /* @__PURE__ */ new Set();
|
|
781
|
-
for (const key of Object.getOwnPropertySymbols(this)) {
|
|
782
|
-
const entry = Object.getOwnPropertyDescriptor(this, key);
|
|
783
|
-
if (entry.writable && entry.value)
|
|
784
|
-
items.add(entry.value);
|
|
785
|
-
delete this[key];
|
|
786
|
-
}
|
|
787
|
-
for (const model of items)
|
|
788
|
-
model.set(null);
|
|
789
|
-
this.layer.clear();
|
|
790
|
-
}
|
|
791
|
-
};
|
|
792
|
-
function reject(argument) {
|
|
793
|
-
throw new Error(`Context can only include Model or instance but got ${argument}.`);
|
|
788
|
+
return compute();
|
|
794
789
|
}
|
|
795
790
|
|
|
796
791
|
// src/instruction/has.ts
|
|
797
792
|
function has(type, argument) {
|
|
798
|
-
return
|
|
793
|
+
return use((key, subject, state) => {
|
|
794
|
+
const expect = (callback) => Context.get(subject, (context) => context.put(type, callback));
|
|
799
795
|
if (typeof argument == "boolean") {
|
|
800
|
-
|
|
796
|
+
expect((model) => {
|
|
801
797
|
subject.set(key, model);
|
|
802
798
|
const remove = () => {
|
|
803
|
-
drop();
|
|
804
799
|
if (state[key] === model)
|
|
805
800
|
delete state[key];
|
|
806
801
|
};
|
|
807
|
-
|
|
802
|
+
model.get(null, remove);
|
|
808
803
|
return remove;
|
|
809
804
|
});
|
|
810
805
|
return { get: argument };
|
|
811
806
|
}
|
|
812
|
-
const
|
|
813
|
-
|
|
814
|
-
if (
|
|
807
|
+
const value = /* @__PURE__ */ new Set();
|
|
808
|
+
expect((model) => {
|
|
809
|
+
if (value.has(model))
|
|
815
810
|
return;
|
|
816
811
|
const remove = typeof argument == "function" ? argument(model) : void 0;
|
|
817
812
|
if (remove === false)
|
|
818
813
|
return;
|
|
819
|
-
|
|
814
|
+
value.add(model);
|
|
820
815
|
subject.set(key);
|
|
821
816
|
const done = () => {
|
|
822
817
|
drop();
|
|
823
818
|
if (typeof remove == "function")
|
|
824
819
|
remove();
|
|
825
|
-
|
|
820
|
+
value.delete(model);
|
|
826
821
|
subject.set(key);
|
|
827
822
|
};
|
|
828
823
|
const drop = model.get(null, done);
|
|
829
824
|
return done;
|
|
830
825
|
});
|
|
831
|
-
return {
|
|
832
|
-
value: children
|
|
833
|
-
};
|
|
826
|
+
return { value };
|
|
834
827
|
});
|
|
835
828
|
}
|
|
836
829
|
export {
|
|
837
830
|
Context,
|
|
838
831
|
Model,
|
|
839
|
-
add,
|
|
840
832
|
Model as default,
|
|
841
833
|
get,
|
|
842
834
|
has,
|
package/package.json
CHANGED