@expressive/mvc 0.0.4 → 0.1.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.d.ts CHANGED
@@ -75,6 +75,11 @@ declare namespace Model {
75
75
  export type Methods<T> = {
76
76
  [K in keyof T]: T[K] extends Ref ? never : T[K] extends Function ? K : never;
77
77
  }[keyof T];
78
+ export type Refs<T extends Model> = {
79
+ <K extends Field<T>>(key: K, value: T[K]): void;
80
+ } & {
81
+ [P in Field<T>]: (next: any) => void;
82
+ };
78
83
  /**
79
84
  * Subset of `keyof T` which are not methods or defined by base Model U.
80
85
  *
@@ -110,11 +115,12 @@ interface Model extends Stateful {
110
115
  */
111
116
  get: this;
112
117
  /**
113
- * Circular reference to `this` controller.
118
+ * Setter utility
114
119
  *
115
- * Shortcut is mainly to update values, while having destructured already.
120
+ * Can be used to set (and force-update) values.
121
+ * Shortcut to update values, contains refs for all controlled values.
116
122
  */
117
- set: this;
123
+ set: Model.Refs<this>;
118
124
  }
119
125
  declare class Model {
120
126
  static [CONTROL]: Controller;
@@ -186,7 +192,7 @@ declare class Controller<T extends Stateful = any> {
186
192
  constructor(subject: T);
187
193
  start(): void;
188
194
  stop(): void;
189
- private manage;
195
+ manage(key: Model.Field<T>, value: any): void;
190
196
  ref(key: Model.Field<T>, handler?: Controller.OnValue<T>): (value: any) => void;
191
197
  addListener(listener: Controller.OnEvent<T>): () => void;
192
198
  emit(keys: readonly Model.Event<T>[]): void;
package/lib/index.esm.js CHANGED
@@ -148,9 +148,18 @@ const LOCAL = Symbol("LOCAL");
148
148
  const STATE = Symbol("STATE");
149
149
  class Model {
150
150
  constructor() {
151
- define(this, CONTROL, new Controller(this));
151
+ const control = new Controller(this);
152
+ define(this, CONTROL, control);
152
153
  define(this, "get", this);
153
- define(this, "set", this);
154
+ defineLazy(this, "set", () => {
155
+ const assign = (key, value) => {
156
+ control.update(key, value);
157
+ };
158
+ ready(control);
159
+ for (const key of getOwnPropertyNames(control.proxy))
160
+ define(assign, key, control.ref(key));
161
+ return assign;
162
+ });
154
163
  }
155
164
  get [STATE]() {
156
165
  return this[CONTROL].state;
@@ -287,10 +296,7 @@ class Model {
287
296
  return (typeof maybe == "function" &&
288
297
  maybe.prototype instanceof this);
289
298
  }
290
- }
291
- defineLazy(Model, CONTROL, function () {
292
- return new Controller(this);
293
- });
299
+ }
294
300
 
295
301
  class Subscriber {
296
302
  constructor(target, onUpdate) {
@@ -492,26 +498,28 @@ class Controller {
492
498
  this.proxy = Object.create(subject);
493
499
  }
494
500
  start() {
495
- for (const key in this.subject)
496
- this.manage(key);
501
+ READY.add(this);
502
+ for (const key in this.subject) {
503
+ const { value: entry } = getOwnPropertyDescriptor(this.subject, key);
504
+ if (typeof entry == "function")
505
+ continue;
506
+ if (typeof entry == "symbol") {
507
+ const instruction = PENDING.get(entry);
508
+ if (instruction)
509
+ instruction.call(this, key, this);
510
+ continue;
511
+ }
512
+ this.manage(key, entry);
513
+ }
497
514
  this.emit([]);
498
515
  }
499
516
  stop() {
500
517
  this.followers.clear();
501
518
  this.onDestroy.forEach(x => x());
502
519
  }
503
- manage(key) {
520
+ manage(key, value) {
504
521
  const { proxy, state, subject } = this;
505
- const { value: entry } = getOwnPropertyDescriptor(subject, key);
506
- if (typeof entry == "function")
507
- return;
508
- if (typeof entry == "symbol") {
509
- const instruction = PENDING.get(entry);
510
- if (instruction)
511
- instruction.call(this, key, this);
512
- return;
513
- }
514
- state[key] = entry;
522
+ state[key] = value;
515
523
  const set = this.ref(key);
516
524
  defineProperty(subject, key, {
517
525
  enumerable: false,
@@ -603,26 +611,23 @@ class Controller {
603
611
  }
604
612
  function control(subject, cb) {
605
613
  let control = subject[CONTROL];
606
- const ready = READY.has(control);
607
614
  if (!control) {
608
615
  control = new Controller(subject);
609
616
  define(subject, CONTROL, control);
610
617
  }
611
- if (!cb) {
612
- if (!ready) {
613
- READY.add(control);
614
- control.start();
615
- }
616
- return control;
617
- }
618
+ return ready(control, cb);
619
+ }
620
+ function ready(control, cb) {
621
+ const ready = READY.has(control);
618
622
  if (!ready) {
619
- let done;
620
- control.requestUpdate(() => {
621
- done = cb(control);
622
- });
623
- return () => done && done();
623
+ if (cb) {
624
+ let done;
625
+ control.requestUpdate(() => done = cb(control));
626
+ return () => done && done();
627
+ }
628
+ control.start();
624
629
  }
625
- return cb(control);
630
+ return cb ? cb(control) : control;
626
631
  }
627
632
 
628
633
  function apply(fn, label) {