@expressive/mvc 0.46.0 → 0.47.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 CHANGED
@@ -201,8 +201,6 @@ declare class Model {
201
201
  static at<T extends Model>(this: Model.Type<T>, from: Model, cb: (got: T | undefined) => void): void;
202
202
  }
203
203
 
204
- declare function add<T = any>(instruction: Model.Instruction): T;
205
-
206
204
  declare namespace get {
207
205
  type Function<T, S = any> = (on: S, key: string) => T;
208
206
  type Factory<T, S = any> = (this: S, key: string, thisArg: S) => T;
@@ -346,19 +344,9 @@ declare function set<T>(factory: set.Factory<T> | Promise<T>, required?: boolean
346
344
  */
347
345
  declare function set<T>(value: T | undefined, onUpdate: set.Callback<T>): T;
348
346
 
349
- /** Create a placeholder for specified Model type. */
350
- declare function use<T extends Model>(): T | undefined;
351
- /** Create a new child instance of model. */
347
+ declare function use<T = any>(instruction: Model.Instruction): T;
348
+ declare function use<T extends Model>(Type: Model.Type<T>, required: false): T | undefined;
352
349
  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
350
 
363
351
  declare namespace has {
364
352
  type Callback<T = any> = (model: T) => void | boolean | (() => void);
@@ -404,4 +392,4 @@ declare global {
404
392
  }
405
393
  }
406
394
 
407
- export { Context, Model, add, Model as default, get, has, ref, set, use };
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,
@@ -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
- state[key] = desc.value;
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.`);
@@ -368,6 +369,10 @@ function update(subject, key, value, silent) {
368
369
  const previous = state[key];
369
370
  if (value === previous)
370
371
  return true;
372
+ if (value instanceof Model && !PARENT.has(value)) {
373
+ PARENT.set(value, subject);
374
+ event(value, true);
375
+ }
371
376
  state[key] = value;
372
377
  if (silent !== true)
373
378
  push(subject, key);
@@ -424,26 +429,42 @@ function uid() {
424
429
  return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
425
430
  }
426
431
 
427
- // src/instruction/add.ts
432
+ // src/instruction/use.ts
428
433
  var INSTRUCT = /* @__PURE__ */ new Map();
429
- function add(instruction) {
434
+ function use(model, argument) {
430
435
  const token = Symbol("instruction");
431
- INSTRUCT.set(token, instruction);
436
+ if (Model.is(model)) {
437
+ const type = model;
438
+ const value = new model();
439
+ model = (key, subject) => {
440
+ function set2(next) {
441
+ if (next ? !(next instanceof type) : argument !== false)
442
+ throw new Error(`${subject}.${key} expected Model of type ${type} but got ${next && next.constructor}.`);
443
+ update(subject, key, next);
444
+ if (next && typeof argument == "function")
445
+ argument(next);
446
+ return false;
447
+ }
448
+ set2(value);
449
+ return { set: set2, value };
450
+ };
451
+ }
452
+ INSTRUCT.set(token, model);
432
453
  return token;
433
454
  }
434
455
  Model.on((_, subject) => {
435
456
  const state = STATE.get(subject);
436
- Object.entries(
437
- Object.getOwnPropertyDescriptors(subject)
438
- ).forEach(([key, { value }]) => {
457
+ const props = Object.getOwnPropertyDescriptors(subject);
458
+ for (const key in props) {
459
+ const { value } = props[key];
439
460
  const instruction = INSTRUCT.get(value);
440
461
  if (!instruction)
441
- return;
462
+ continue;
442
463
  INSTRUCT.delete(value);
443
464
  delete subject[key];
444
465
  const output = instruction.call(subject, key, subject, state);
445
466
  if (!output)
446
- return;
467
+ continue;
447
468
  const desc = typeof output == "object" ? output : { get: output };
448
469
  const { enumerable = true } = desc;
449
470
  if ("value" in desc)
@@ -472,20 +493,21 @@ Model.on((_, subject) => {
472
493
  );
473
494
  }
474
495
  });
475
- });
496
+ }
476
497
  return null;
477
498
  });
478
499
 
479
500
  // src/instruction/get.ts
501
+ var STALE = /* @__PURE__ */ new WeakSet();
480
502
  function get(arg0, arg1) {
481
- return add((key, subject) => {
503
+ return use((key, subject) => {
482
504
  let from = subject;
483
505
  if (typeof arg0 == "symbol")
484
506
  throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${from}.${key}. This is not allowed.`);
485
507
  let source = (resolve) => resolve(from);
486
- if (arg0 instanceof Model)
508
+ if (arg0 instanceof Model) {
487
509
  from = arg0;
488
- else if (Model.is(arg0)) {
510
+ } else if (arg0.prototype instanceof Model) {
489
511
  const hasParent = PARENT.get(from);
490
512
  if (!hasParent) {
491
513
  if (arg1 === true)
@@ -502,63 +524,61 @@ function get(arg0, arg1) {
502
524
  from = hasParent;
503
525
  else
504
526
  throw new Error(`New ${from} created as child of ${hasParent}, but must be instanceof ${arg0}.`);
505
- } else if (typeof arg0 == "function") {
527
+ } else {
506
528
  const fn = METHOD.get(arg0) || arg0;
507
529
  arg1 = (p, k) => fn.call(p, k, p);
508
530
  }
509
- if (typeof arg1 == "function")
510
- return compute(subject, key, source, arg1);
511
- source((got) => subject.set(key, got));
512
- return { get: arg1 };
513
- });
514
- }
515
- var STALE = /* @__PURE__ */ new WeakSet();
516
- function compute(subject, key, source, setter) {
517
- let reset;
518
- let isAsync;
519
- let proxy;
520
- function connect(model) {
521
- reset = effect(model, (current) => {
522
- proxy = current;
523
- if (!reset)
524
- compute2(true);
525
- else if (STALE.delete(compute2))
526
- compute2();
527
- return (didUpdate) => {
528
- if (didUpdate) {
529
- STALE.add(compute2);
530
- push(subject, key, true);
531
+ if (typeof arg1 == "function") {
532
+ let connect2 = function(model) {
533
+ reset = effect(model, (current) => {
534
+ proxy = current;
535
+ if (!reset)
536
+ compute2(true);
537
+ else if (STALE.delete(compute2))
538
+ compute2();
539
+ return (didUpdate) => {
540
+ if (didUpdate) {
541
+ STALE.add(compute2);
542
+ push(subject, key, true);
543
+ }
544
+ };
545
+ });
546
+ }, compute2 = function(initial) {
547
+ let next;
548
+ try {
549
+ next = getter.call(proxy, proxy, key);
550
+ } catch (err) {
551
+ console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key}.`);
552
+ if (initial)
553
+ throw err;
554
+ console.error(err);
531
555
  }
556
+ update(subject, key, next, !isAsync);
532
557
  };
533
- });
534
- }
535
- function compute2(initial) {
536
- let next;
537
- try {
538
- next = setter.call(proxy, proxy, key);
539
- } catch (err) {
540
- console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key}.`);
541
- if (initial)
542
- throw err;
543
- console.error(err);
544
- }
545
- update(subject, key, next, !isAsync);
546
- }
547
- return () => {
548
- if (!proxy) {
549
- source(connect);
550
- isAsync = true;
551
- }
552
- if (STALE.delete(compute2))
553
- compute2();
554
- return fetch(subject, key, !proxy);
555
- };
558
+ var connect = connect2, compute = compute2;
559
+ const getter = arg1;
560
+ let reset;
561
+ let isAsync;
562
+ let proxy;
563
+ return () => {
564
+ if (!proxy) {
565
+ source(connect2);
566
+ isAsync = true;
567
+ }
568
+ if (STALE.delete(compute2))
569
+ compute2();
570
+ return fetch(subject, key, !proxy);
571
+ };
572
+ } else
573
+ source((got) => subject.set(key, got));
574
+ return { get: arg1 };
575
+ });
556
576
  }
557
577
 
558
578
  // src/instruction/ref.ts
559
579
  var define2 = Object.defineProperty;
560
580
  function ref(arg, arg2) {
561
- return add((key, subject, state) => {
581
+ return use((key, subject, state) => {
562
582
  let value = {};
563
583
  if (arg === subject)
564
584
  subject.get(() => {
@@ -608,7 +628,7 @@ function ref(arg, arg2) {
608
628
 
609
629
  // src/instruction/set.ts
610
630
  function set(value, argument) {
611
- return add((key, subject) => {
631
+ return use((key, subject) => {
612
632
  const output = {};
613
633
  if (typeof value == "function" || value instanceof Promise) {
614
634
  let init2 = function() {
@@ -664,11 +684,11 @@ function set(value, argument) {
664
684
  function attempt(fn) {
665
685
  function retry(err) {
666
686
  if (err instanceof Promise)
667
- return err.then(compute2);
687
+ return err.then(compute);
668
688
  else
669
689
  throw err;
670
690
  }
671
- function compute2() {
691
+ function compute() {
672
692
  try {
673
693
  const output = fn();
674
694
  return output instanceof Promise ? output.catch(retry) : output;
@@ -676,27 +696,7 @@ function attempt(fn) {
676
696
  return retry(err);
677
697
  }
678
698
  }
679
- return compute2();
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
- });
699
+ return compute();
700
700
  }
701
701
 
702
702
  // src/context.ts
@@ -829,7 +829,7 @@ function reject(argument) {
829
829
 
830
830
  // src/instruction/has.ts
831
831
  function has(type, argument) {
832
- return add((key, subject, state) => {
832
+ return use((key, subject, state) => {
833
833
  if (typeof argument == "boolean") {
834
834
  Context.request(type, subject, (model) => {
835
835
  subject.set(key, model);
@@ -871,7 +871,6 @@ function has(type, argument) {
871
871
  0 && (module.exports = {
872
872
  Context,
873
873
  Model,
874
- add,
875
874
  get,
876
875
  has,
877
876
  ref,
package/dist/index.mjs CHANGED
@@ -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
- state[key] = desc.value;
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.`);
@@ -334,6 +336,10 @@ function update(subject, key, value, silent) {
334
336
  const previous = state[key];
335
337
  if (value === previous)
336
338
  return true;
339
+ if (value instanceof Model && !PARENT.has(value)) {
340
+ PARENT.set(value, subject);
341
+ event(value, true);
342
+ }
337
343
  state[key] = value;
338
344
  if (silent !== true)
339
345
  push(subject, key);
@@ -390,26 +396,42 @@ function uid() {
390
396
  return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
391
397
  }
392
398
 
393
- // src/instruction/add.ts
399
+ // src/instruction/use.ts
394
400
  var INSTRUCT = /* @__PURE__ */ new Map();
395
- function add(instruction) {
401
+ function use(model, argument) {
396
402
  const token = Symbol("instruction");
397
- INSTRUCT.set(token, instruction);
403
+ if (Model.is(model)) {
404
+ const type = model;
405
+ const value = new model();
406
+ model = (key, subject) => {
407
+ function set2(next) {
408
+ if (next ? !(next instanceof type) : argument !== false)
409
+ throw new Error(`${subject}.${key} expected Model of type ${type} but got ${next && next.constructor}.`);
410
+ update(subject, key, next);
411
+ if (next && typeof argument == "function")
412
+ argument(next);
413
+ return false;
414
+ }
415
+ set2(value);
416
+ return { set: set2, value };
417
+ };
418
+ }
419
+ INSTRUCT.set(token, model);
398
420
  return token;
399
421
  }
400
422
  Model.on((_, subject) => {
401
423
  const state = STATE.get(subject);
402
- Object.entries(
403
- Object.getOwnPropertyDescriptors(subject)
404
- ).forEach(([key, { value }]) => {
424
+ const props = Object.getOwnPropertyDescriptors(subject);
425
+ for (const key in props) {
426
+ const { value } = props[key];
405
427
  const instruction = INSTRUCT.get(value);
406
428
  if (!instruction)
407
- return;
429
+ continue;
408
430
  INSTRUCT.delete(value);
409
431
  delete subject[key];
410
432
  const output = instruction.call(subject, key, subject, state);
411
433
  if (!output)
412
- return;
434
+ continue;
413
435
  const desc = typeof output == "object" ? output : { get: output };
414
436
  const { enumerable = true } = desc;
415
437
  if ("value" in desc)
@@ -438,20 +460,21 @@ Model.on((_, subject) => {
438
460
  );
439
461
  }
440
462
  });
441
- });
463
+ }
442
464
  return null;
443
465
  });
444
466
 
445
467
  // src/instruction/get.ts
468
+ var STALE = /* @__PURE__ */ new WeakSet();
446
469
  function get(arg0, arg1) {
447
- return add((key, subject) => {
470
+ return use((key, subject) => {
448
471
  let from = subject;
449
472
  if (typeof arg0 == "symbol")
450
473
  throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${from}.${key}. This is not allowed.`);
451
474
  let source = (resolve) => resolve(from);
452
- if (arg0 instanceof Model)
475
+ if (arg0 instanceof Model) {
453
476
  from = arg0;
454
- else if (Model.is(arg0)) {
477
+ } else if (arg0.prototype instanceof Model) {
455
478
  const hasParent = PARENT.get(from);
456
479
  if (!hasParent) {
457
480
  if (arg1 === true)
@@ -468,63 +491,61 @@ function get(arg0, arg1) {
468
491
  from = hasParent;
469
492
  else
470
493
  throw new Error(`New ${from} created as child of ${hasParent}, but must be instanceof ${arg0}.`);
471
- } else if (typeof arg0 == "function") {
494
+ } else {
472
495
  const fn = METHOD.get(arg0) || arg0;
473
496
  arg1 = (p, k) => fn.call(p, k, p);
474
497
  }
475
- if (typeof arg1 == "function")
476
- return compute(subject, key, source, arg1);
477
- source((got) => subject.set(key, got));
478
- return { get: arg1 };
479
- });
480
- }
481
- var STALE = /* @__PURE__ */ new WeakSet();
482
- function compute(subject, key, source, setter) {
483
- let reset;
484
- let isAsync;
485
- let proxy;
486
- function connect(model) {
487
- reset = effect(model, (current) => {
488
- proxy = current;
489
- if (!reset)
490
- compute2(true);
491
- else if (STALE.delete(compute2))
492
- compute2();
493
- return (didUpdate) => {
494
- if (didUpdate) {
495
- STALE.add(compute2);
496
- push(subject, key, true);
498
+ if (typeof arg1 == "function") {
499
+ let connect2 = function(model) {
500
+ reset = effect(model, (current) => {
501
+ proxy = current;
502
+ if (!reset)
503
+ compute2(true);
504
+ else if (STALE.delete(compute2))
505
+ compute2();
506
+ return (didUpdate) => {
507
+ if (didUpdate) {
508
+ STALE.add(compute2);
509
+ push(subject, key, true);
510
+ }
511
+ };
512
+ });
513
+ }, compute2 = function(initial) {
514
+ let next;
515
+ try {
516
+ next = getter.call(proxy, proxy, key);
517
+ } catch (err) {
518
+ console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key}.`);
519
+ if (initial)
520
+ throw err;
521
+ console.error(err);
497
522
  }
523
+ update(subject, key, next, !isAsync);
498
524
  };
499
- });
500
- }
501
- function compute2(initial) {
502
- let next;
503
- try {
504
- next = setter.call(proxy, proxy, key);
505
- } catch (err) {
506
- console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key}.`);
507
- if (initial)
508
- throw err;
509
- console.error(err);
510
- }
511
- update(subject, key, next, !isAsync);
512
- }
513
- return () => {
514
- if (!proxy) {
515
- source(connect);
516
- isAsync = true;
517
- }
518
- if (STALE.delete(compute2))
519
- compute2();
520
- return fetch(subject, key, !proxy);
521
- };
525
+ var connect = connect2, compute = compute2;
526
+ const getter = arg1;
527
+ let reset;
528
+ let isAsync;
529
+ let proxy;
530
+ return () => {
531
+ if (!proxy) {
532
+ source(connect2);
533
+ isAsync = true;
534
+ }
535
+ if (STALE.delete(compute2))
536
+ compute2();
537
+ return fetch(subject, key, !proxy);
538
+ };
539
+ } else
540
+ source((got) => subject.set(key, got));
541
+ return { get: arg1 };
542
+ });
522
543
  }
523
544
 
524
545
  // src/instruction/ref.ts
525
546
  var define2 = Object.defineProperty;
526
547
  function ref(arg, arg2) {
527
- return add((key, subject, state) => {
548
+ return use((key, subject, state) => {
528
549
  let value = {};
529
550
  if (arg === subject)
530
551
  subject.get(() => {
@@ -574,7 +595,7 @@ function ref(arg, arg2) {
574
595
 
575
596
  // src/instruction/set.ts
576
597
  function set(value, argument) {
577
- return add((key, subject) => {
598
+ return use((key, subject) => {
578
599
  const output = {};
579
600
  if (typeof value == "function" || value instanceof Promise) {
580
601
  let init2 = function() {
@@ -630,11 +651,11 @@ function set(value, argument) {
630
651
  function attempt(fn) {
631
652
  function retry(err) {
632
653
  if (err instanceof Promise)
633
- return err.then(compute2);
654
+ return err.then(compute);
634
655
  else
635
656
  throw err;
636
657
  }
637
- function compute2() {
658
+ function compute() {
638
659
  try {
639
660
  const output = fn();
640
661
  return output instanceof Promise ? output.catch(retry) : output;
@@ -642,27 +663,7 @@ function attempt(fn) {
642
663
  return retry(err);
643
664
  }
644
665
  }
645
- return compute2();
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
+ return compute();
666
667
  }
667
668
 
668
669
  // src/context.ts
@@ -795,7 +796,7 @@ function reject(argument) {
795
796
 
796
797
  // src/instruction/has.ts
797
798
  function has(type, argument) {
798
- return add((key, subject, state) => {
799
+ return use((key, subject, state) => {
799
800
  if (typeof argument == "boolean") {
800
801
  Context.request(type, subject, (model) => {
801
802
  subject.set(key, model);
@@ -836,7 +837,6 @@ function has(type, argument) {
836
837
  export {
837
838
  Context,
838
839
  Model,
839
- add,
840
840
  Model as default,
841
841
  get,
842
842
  has,
package/package.json CHANGED
@@ -28,6 +28,6 @@
28
28
  "prebuild": "rm -rf dist",
29
29
  "preversion": "npm run test && npm run build"
30
30
  },
31
- "version": "0.46.0",
32
- "gitHead": "22ffbbadad0ab45f73c71e178183941e78ed2a56"
31
+ "version": "0.47.0",
32
+ "gitHead": "7c0ddd5ea9b7e08bd5aa21aa8e1ab65ceef17fcf"
33
33
  }