@expressive/mvc 0.34.0 → 0.35.0-alpha.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/lib/index.js DELETED
@@ -1,803 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- /******************************************************************************
6
- Copyright (c) Microsoft Corporation.
7
-
8
- Permission to use, copy, modify, and/or distribute this software for any
9
- purpose with or without fee is hereby granted.
10
-
11
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
- PERFORMANCE OF THIS SOFTWARE.
18
- ***************************************************************************** */
19
-
20
- function __awaiter(thisArg, _arguments, P, generator) {
21
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
22
- return new (P || (P = Promise))(function (resolve, reject) {
23
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
24
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
25
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
26
- step((generator = generator.apply(thisArg, _arguments || [])).next());
27
- });
28
- }
29
-
30
- const { assign, create, defineProperty, entries, freeze, isFrozen, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
31
-
32
- const REGISTER = new WeakMap();
33
- const OBSERVER = new WeakMap();
34
- const INSTRUCT = new Map();
35
- const PENDING$1 = new WeakMap();
36
- const PARENTS = new WeakMap();
37
- const LIFECYCLE = {
38
- ready: new Set(),
39
- dispatch: new Set(),
40
- update: new Set(),
41
- didUpdate: new Set(),
42
- };
43
- class Control {
44
- static on(event, callback) {
45
- LIFECYCLE[event].add(callback);
46
- return () => LIFECYCLE[event].delete(callback);
47
- }
48
- constructor(subject, id) {
49
- this.state = {};
50
- this.frame = freeze({});
51
- this.listeners = new Map();
52
- this.id = `${subject.constructor}-${id ? String(id) : uid()}`;
53
- this.subject = subject;
54
- REGISTER.set(subject, this);
55
- if (id !== false)
56
- PENDING$1.set(this, new Set(LIFECYCLE.ready));
57
- }
58
- watch(key, output) {
59
- const { state, subject, listeners } = this;
60
- const { set, enumerable = true } = output;
61
- if ("value" in output)
62
- state[key] = output.value;
63
- defineProperty(subject, key, {
64
- enumerable,
65
- set: set === false
66
- ? undefined
67
- : (next) => {
68
- const previous = state[key];
69
- if (next !== previous) {
70
- state[key] = next;
71
- if (set && set.call(subject, next, previous) === false)
72
- state[key] = previous;
73
- else
74
- this.update(key);
75
- }
76
- },
77
- get() {
78
- const value = output.get
79
- ? output.get(this)
80
- : state[key];
81
- const observer = OBSERVER.get(this);
82
- if (observer) {
83
- const keys = listeners.get(observer);
84
- listeners.set(observer, new Set(keys).add(key));
85
- return watch(value, observer);
86
- }
87
- return value;
88
- }
89
- });
90
- }
91
- update(key, value) {
92
- const { state, subject, listeners } = this;
93
- if (!listeners || 1 in arguments && value === state[key])
94
- return;
95
- if (isFrozen(this.frame)) {
96
- this.frame = {};
97
- enqueue(() => {
98
- freeze(this.frame);
99
- listeners.forEach((subs, cb) => {
100
- if (!subs) {
101
- const notify = cb(undefined, subject);
102
- if (notify)
103
- enqueue(notify);
104
- }
105
- });
106
- });
107
- }
108
- if (1 in arguments)
109
- state[key] = value;
110
- if (key in this.frame)
111
- return;
112
- this.frame[key] = state[key];
113
- for (const [cb, keys] of listeners)
114
- if (!keys || keys.has(key)) {
115
- const notify = cb(key, subject);
116
- if (notify === null)
117
- listeners.delete(cb);
118
- else if (notify)
119
- enqueue(notify);
120
- }
121
- }
122
- fetch(key, required) {
123
- const { state, subject } = this;
124
- return () => {
125
- if (key in state || required === false) {
126
- const value = state[key];
127
- if (value !== undefined || !required)
128
- return value;
129
- }
130
- const error = new Error(`${subject}.${key} is not yet available.`);
131
- const promise = new Promise((resolve, reject) => {
132
- function check() {
133
- if (state[key] !== undefined) {
134
- remove();
135
- resolve();
136
- }
137
- }
138
- const remove = this.addListener((k) => {
139
- if (k === key)
140
- return check;
141
- if (k === null)
142
- reject(new Error(`${subject} is destroyed.`));
143
- });
144
- });
145
- throw assign(promise, {
146
- toString: () => String(error),
147
- name: "Suspense",
148
- message: error.message,
149
- stack: error.stack
150
- });
151
- };
152
- }
153
- addListener(fn) {
154
- this.listeners.set(fn, undefined);
155
- return () => this.listeners.delete(fn);
156
- }
157
- clear() {
158
- this.listeners.forEach((_, fn) => fn(null, this));
159
- this.listeners.clear();
160
- freeze(this.state);
161
- }
162
- }
163
- Control.watch = watch;
164
- Control.for = control;
165
- Control.add = add;
166
- function control(subject, ready) {
167
- const self = REGISTER.get(subject.is);
168
- const pending = PENDING$1.get(self);
169
- if (typeof ready == "function") {
170
- if (pending) {
171
- let done;
172
- pending.add(() => done = ready(self));
173
- return () => done && done();
174
- }
175
- return ready(self);
176
- }
177
- if (pending && ready) {
178
- for (const key in subject) {
179
- const { value } = getOwnPropertyDescriptor(subject, key);
180
- const instruction = INSTRUCT.get(value);
181
- let desc = { value };
182
- if (instruction) {
183
- INSTRUCT.delete(value);
184
- delete subject[key];
185
- const out = instruction.call(self, key, self);
186
- desc = typeof out == "function" ? { get: out } : out;
187
- }
188
- if (desc)
189
- self.watch(key, desc);
190
- }
191
- PENDING$1.delete(self);
192
- pending.forEach(cb => cb(self));
193
- }
194
- return self;
195
- }
196
- function enqueue(event) {
197
- const { update, didUpdate, dispatch } = LIFECYCLE;
198
- if (!dispatch.size)
199
- setTimeout(() => {
200
- update.forEach(x => x());
201
- dispatch.forEach(event => {
202
- try {
203
- event();
204
- }
205
- catch (err) {
206
- console.error(err);
207
- }
208
- });
209
- dispatch.clear();
210
- didUpdate.forEach(x => x());
211
- }, 0);
212
- dispatch.add(event);
213
- }
214
- function parent(from, assign) {
215
- if (!assign)
216
- return PARENTS.get(from);
217
- PARENTS.set(from, assign);
218
- }
219
- function watch(value, argument) {
220
- const control = REGISTER.get(value);
221
- if (control) {
222
- if (!OBSERVER.has(value))
223
- REGISTER.set(value = create(value), control);
224
- OBSERVER.set(value, argument);
225
- }
226
- return value;
227
- }
228
- function add(instruction) {
229
- const placeholder = Symbol("instruction");
230
- INSTRUCT.set(placeholder, instruction);
231
- return placeholder;
232
- }
233
- /** Random alphanumberic of length 6. Will always start with a letter. */
234
- function uid() {
235
- return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
236
- }
237
-
238
- class Model {
239
- constructor(id) {
240
- defineProperty(this, "is", { value: this });
241
- new Control(this, id);
242
- }
243
- get(arg1) {
244
- return typeof arg1 == "function"
245
- ? effect(this, arg1)
246
- : extract(this);
247
- }
248
- set(arg1, arg2) {
249
- return typeof arg1 == "function"
250
- ? control(this, c => c.addListener(k => k && arg1(k)))
251
- : nextUpdate(this, arg1, arg2);
252
- }
253
- /** Mark this instance for garbage collection. */
254
- null() {
255
- control(this).clear();
256
- }
257
- /**
258
- * Creates a new instance of this controller.
259
- *
260
- * Beyond `new this(...)`, method will activate managed-state.
261
- *
262
- * @param args - arguments sent to constructor
263
- */
264
- static new(...args) {
265
- const instance = new this(...args);
266
- control(instance, true);
267
- return instance;
268
- }
269
- /**
270
- * Static equivalent of `x instanceof this`.
271
- * Determines if provided class is a subtype of this one.
272
- * If so, language server will make available all static
273
- * methods and properties of this class.
274
- */
275
- static is(maybe) {
276
- return typeof maybe == "function" && maybe.prototype instanceof this;
277
- }
278
- }
279
- defineProperty(Model.prototype, "toString", {
280
- value() {
281
- return control(this).id;
282
- }
283
- });
284
- defineProperty(Model, "toString", {
285
- value() {
286
- return this.name;
287
- }
288
- });
289
-
290
- function extract(target) {
291
- const cache = new Map();
292
- function get(value) {
293
- if (value instanceof Model) {
294
- let flat = cache.get(value);
295
- if (!flat) {
296
- cache.set(value, flat = {});
297
- const { state } = control(value);
298
- entries(state).forEach(([key, value]) => {
299
- flat[key] = get(value);
300
- });
301
- }
302
- return flat;
303
- }
304
- return value;
305
- }
306
- return get(target);
307
- }
308
- function nextUpdate(target, arg1, arg2) {
309
- return new Promise((resolve, reject) => {
310
- control(target, self => {
311
- if (isFrozen(self.frame) && typeof arg1 != "number") {
312
- resolve(false);
313
- return;
314
- }
315
- const callback = () => resolve(self.frame);
316
- const remove = self.addListener((key) => {
317
- if (!arg2 || key && arg2(key) === true) {
318
- remove();
319
- if (timeout)
320
- clearTimeout(timeout);
321
- return callback;
322
- }
323
- });
324
- const timeout = typeof arg1 == "number" && setTimeout(() => {
325
- remove();
326
- reject(arg1);
327
- }, arg1);
328
- });
329
- });
330
- }
331
- function effect(target, callback) {
332
- return control(target, self => {
333
- let refresh;
334
- let unSet;
335
- function invoke() {
336
- if (unSet)
337
- unSet();
338
- try {
339
- const out = callback.call(target, target);
340
- unSet = typeof out == "function" ? out : undefined;
341
- }
342
- catch (err) {
343
- if (err instanceof Promise) {
344
- err.then(() => (refresh = invoke)());
345
- refresh = undefined;
346
- }
347
- else
348
- console.error(err);
349
- }
350
- }
351
- target = watch(target, () => refresh);
352
- self.addListener(key => {
353
- if (!refresh)
354
- return refresh;
355
- if (key === null && unSet)
356
- unSet();
357
- });
358
- invoke();
359
- refresh = invoke;
360
- return () => {
361
- refresh = null;
362
- };
363
- });
364
- }
365
- function attempt(fn) {
366
- function retry(err) {
367
- if (err instanceof Promise)
368
- return err.then(compute);
369
- else
370
- throw err;
371
- }
372
- function compute() {
373
- try {
374
- const output = fn();
375
- return output instanceof Promise
376
- ? output.catch(retry)
377
- : output;
378
- }
379
- catch (err) {
380
- return retry(err);
381
- }
382
- }
383
- return compute();
384
- }
385
-
386
- function run(task) {
387
- return add((key, control) => {
388
- let pending = false;
389
- const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
390
- if (pending)
391
- return Promise.reject(new Error(`Invoked action ${key} but one is already active.`));
392
- pending = true;
393
- control.update(key);
394
- try {
395
- return yield attempt(() => task.apply(control.subject, args));
396
- }
397
- finally {
398
- pending = false;
399
- control.update(key);
400
- }
401
- });
402
- defineProperty(invoke, "active", {
403
- get: () => pending
404
- });
405
- return {
406
- value: invoke,
407
- set: false
408
- };
409
- });
410
- }
411
-
412
- function get(arg0, arg1) {
413
- return add((key, control) => {
414
- let { subject } = control;
415
- if (typeof arg0 == "symbol")
416
- throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${subject}.${key}. This is not allowed.`);
417
- let source = resolve => resolve(subject);
418
- if (arg0 instanceof Model)
419
- subject = arg0;
420
- else if (Model.is(arg0)) {
421
- const hasParent = parent(subject);
422
- if (!hasParent) {
423
- if (arg1 === true)
424
- throw new Error(`New ${subject} created standalone but requires parent of type ${arg0}.`);
425
- if (!get.from)
426
- throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
427
- const fetch = get.from(subject);
428
- source = (resolve) => {
429
- fetch(context => {
430
- const model = context.get(arg0);
431
- if (model)
432
- resolve(model);
433
- else if (arg1 !== false)
434
- throw new Error(`Attempted to find an instance of ${arg0} in context. It is required by ${subject}, but one could not be found.`);
435
- });
436
- };
437
- }
438
- else if (!arg0 || hasParent instanceof arg0)
439
- subject = hasParent;
440
- else
441
- throw new Error(`New ${subject} created as child of ${hasParent}, but must be instanceof ${arg0}.`);
442
- }
443
- else if (typeof arg0 == "function")
444
- arg1 = arg0.call(subject, key, subject);
445
- if (typeof arg1 == "function")
446
- return compute(control, key, source, arg1);
447
- source(got => control.update(key, got));
448
- return control.fetch(key, arg1 !== false);
449
- });
450
- }
451
- const ORDER = new WeakMap();
452
- const PENDING = new Set();
453
- let OFFSET = 0;
454
- function compute(parent, key, source, setter) {
455
- const { state, subject } = parent;
456
- let proxy;
457
- let isAsync;
458
- let reset;
459
- function compute(initial) {
460
- if (key in parent.frame)
461
- return;
462
- let next;
463
- try {
464
- next = setter.call(proxy, proxy);
465
- }
466
- catch (err) {
467
- // TODO: address possibility of loop
468
- if (err instanceof Promise)
469
- throw err.finally(compute);
470
- console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key}.`);
471
- if (initial)
472
- throw err;
473
- console.error(err);
474
- }
475
- if (next !== state[key]) {
476
- if (key in state || isAsync)
477
- parent.update(key);
478
- state[key] = next;
479
- }
480
- }
481
- function connect(model) {
482
- let done;
483
- if (reset)
484
- reset();
485
- reset = () => done = true;
486
- proxy = watch(model, (_, updated) => {
487
- if (done)
488
- return null;
489
- if (updated == subject)
490
- PENDING.add(compute);
491
- else
492
- compute();
493
- });
494
- output.get = () => {
495
- if (PENDING.delete(compute))
496
- compute();
497
- return state[key];
498
- };
499
- try {
500
- compute(true);
501
- }
502
- finally {
503
- ORDER.set(compute, OFFSET++);
504
- }
505
- }
506
- const output = {
507
- get() {
508
- output.get = parent.fetch(key);
509
- source(connect);
510
- isAsync = true;
511
- return output.get();
512
- }
513
- };
514
- return output;
515
- }
516
- Control.on("update", () => {
517
- while (PENDING.size) {
518
- let compute;
519
- for (const item of PENDING)
520
- if (!compute || ORDER.get(item) < ORDER.get(compute))
521
- compute = item;
522
- PENDING.delete(compute);
523
- compute();
524
- }
525
- });
526
-
527
- function ref(arg, arg2) {
528
- return add((key, source) => {
529
- const { subject, state } = source;
530
- let value = {};
531
- if (arg === subject)
532
- for (const key in state)
533
- defineProperty(value, key, typeof arg2 == "function" ? {
534
- configurable: true,
535
- get() {
536
- const out = arg2(key);
537
- defineProperty(value, key, { value: out });
538
- return out;
539
- }
540
- } : {
541
- value: createRef(source, key)
542
- });
543
- else if (typeof arg == "object")
544
- throw new Error("ref instruction does not support object which is not 'this'");
545
- else {
546
- let unSet;
547
- const set = (value) => {
548
- source.update(key, value);
549
- if (!arg)
550
- return;
551
- if (unSet)
552
- unSet = void unSet(value);
553
- if (value !== null || arg2 === false) {
554
- const out = arg.call(subject, value);
555
- if (typeof out == "function")
556
- unSet = out;
557
- }
558
- };
559
- value = defineProperty(set, "current", {
560
- get: () => state[key],
561
- set
562
- });
563
- }
564
- defineProperty(subject, key, { value });
565
- });
566
- }
567
- function createRef(src, key) {
568
- const refObjectFunction = src.update.bind(src, key);
569
- defineProperty(refObjectFunction, "current", {
570
- set: refObjectFunction,
571
- get: () => src.state[key]
572
- });
573
- return refObjectFunction;
574
- }
575
-
576
- function set(value, argument) {
577
- return add((key, control) => {
578
- const { state, subject } = control;
579
- const output = {};
580
- if (typeof value == "function" || value instanceof Promise) {
581
- function init() {
582
- try {
583
- if (typeof value == "function")
584
- value = attempt(value.bind(subject, key, subject));
585
- if (value instanceof Promise) {
586
- const pending = value
587
- .then(value => {
588
- output.get = undefined;
589
- control.update(key, value);
590
- return value;
591
- })
592
- .catch(err => {
593
- output.get = () => { throw err; };
594
- control.update(key);
595
- });
596
- assign(pending, {
597
- message: `${subject}.${key} is not yet available.`,
598
- stack: new Error().stack
599
- });
600
- if (argument !== false)
601
- return output.get = () => {
602
- throw pending;
603
- };
604
- }
605
- else
606
- control.update(key, value);
607
- }
608
- catch (err) {
609
- console.warn(`Generating initial value for ${subject}.${key} failed.`);
610
- throw err;
611
- }
612
- }
613
- if (argument)
614
- init();
615
- else
616
- output.get = () => {
617
- const get = key in state ? null : init();
618
- return get ? get() : state[key];
619
- };
620
- }
621
- else {
622
- if (value !== undefined)
623
- output.value = value;
624
- else
625
- output.get = control.fetch(key);
626
- if (typeof argument == "function") {
627
- let unSet;
628
- output.set = function (value, previous) {
629
- const out = argument.call(this, value, previous);
630
- if (out === false)
631
- return out;
632
- if (typeof unSet == "function")
633
- unSet = void unSet(value);
634
- if (typeof out == "function")
635
- unSet = out;
636
- };
637
- }
638
- }
639
- return output;
640
- });
641
- }
642
-
643
- function use(input, argument) {
644
- return add((key, source) => {
645
- const { subject, state } = source;
646
- if (typeof input === "function")
647
- input = new input();
648
- function set(next) {
649
- if (input instanceof Model && !(next instanceof input.constructor))
650
- throw new Error(`${subject}.${key} expected Model of type ${input.constructor} but got ${next}.`);
651
- if (next instanceof Model) {
652
- parent(next, subject);
653
- control(next, true);
654
- }
655
- else if (next) {
656
- const subject = create(next);
657
- const control = new Control(subject, false);
658
- for (const key in control.state = next)
659
- control.watch(key, {});
660
- next = subject;
661
- }
662
- state[key] = next;
663
- if (typeof argument == "function")
664
- argument(next);
665
- }
666
- set(input);
667
- return { set };
668
- });
669
- }
670
-
671
- class Context {
672
- constructor() {
673
- this.table = new WeakMap();
674
- this.layer = new Map();
675
- }
676
- has(T) {
677
- let key = this.table.get(T);
678
- if (!key) {
679
- key = Symbol(T.name);
680
- this.table.set(T, key);
681
- }
682
- return key;
683
- }
684
- get(Type) {
685
- const result = this[this.has(Type)];
686
- if (result === null)
687
- throw new Error(`Did find ${Type} in context, but multiple were defined.`);
688
- return result;
689
- }
690
- include(inputs) {
691
- const init = new Map();
692
- for (const key in inputs) {
693
- const input = inputs[key];
694
- const exists = this.layer.get(key);
695
- if (!exists) {
696
- const instance = this.add(input);
697
- this.layer.set(key, input);
698
- init.set(instance, true);
699
- }
700
- // Context must force-reset becasue inputs are no longer safe.
701
- else if (exists !== input) {
702
- this.pop();
703
- this.key = uid();
704
- return this.include(inputs);
705
- }
706
- }
707
- for (const [model] of init)
708
- values(control(model, true).state).forEach(value => {
709
- if (parent(value) === model) {
710
- this.add(value, true);
711
- init.set(value, false);
712
- }
713
- });
714
- return init;
715
- }
716
- add(input, implicit) {
717
- let writable = true;
718
- let T;
719
- let I;
720
- if (typeof input == "function") {
721
- T = input;
722
- I = new input();
723
- }
724
- else {
725
- I = input;
726
- T = I.constructor;
727
- writable = false;
728
- }
729
- do {
730
- const key = this.has(T);
731
- const value = this.hasOwnProperty(key) ? null : I;
732
- if (value || I !== this[key] && !implicit)
733
- defineProperty(this, key, {
734
- configurable: true,
735
- value,
736
- writable
737
- });
738
- T = getPrototypeOf(T);
739
- } while (T !== Model);
740
- return I;
741
- }
742
- push() {
743
- const next = create(this);
744
- next.layer = new Map();
745
- return next;
746
- }
747
- pop() {
748
- const items = new Set();
749
- for (const key of getOwnPropertySymbols(this)) {
750
- const entry = getOwnPropertyDescriptor(this, key);
751
- if (entry.writable && entry.value)
752
- items.add(entry.value);
753
- delete this[key];
754
- }
755
- for (const model of items)
756
- model.null();
757
- this.layer.clear();
758
- }
759
- }
760
-
761
- const STATE = "__state";
762
- const UPDATE = "__update";
763
- const CONTROL = "__control";
764
- const PARENT = "__parent";
765
- Object.defineProperties(Model.prototype, {
766
- [CONTROL]: {
767
- get() {
768
- return control(this);
769
- }
770
- },
771
- [STATE]: {
772
- get() {
773
- return Object.assign({}, control(this).state);
774
- }
775
- },
776
- [UPDATE]: {
777
- get() {
778
- return control(this).frame;
779
- }
780
- },
781
- [PARENT]: {
782
- get() {
783
- return parent(this);
784
- }
785
- }
786
- });
787
- const Debug = {
788
- CONTROL,
789
- STATE,
790
- UPDATE,
791
- PARENT
792
- };
793
-
794
- exports.Context = Context;
795
- exports.Control = Control;
796
- exports.Debug = Debug;
797
- exports.Model = Model;
798
- exports["default"] = Model;
799
- exports.get = get;
800
- exports.ref = ref;
801
- exports.run = run;
802
- exports.set = set;
803
- exports.use = use;