@expressive/mvc 0.36.0 → 0.36.2

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
@@ -28,7 +28,7 @@ declare namespace Model {
28
28
  current: T | null;
29
29
  };
30
30
  /** A callback function which is subscribed to parent and updates when values change. */
31
- type Effect<T> = (this: T, argument: T) => ((update: boolean | null) => void) | Promise<void> | null | void;
31
+ type Effect<T> = (this: T, current: T, updated: Set<Model.Key<T>>) => ((update: boolean | null) => void) | Promise<void> | null | void;
32
32
  type Event<T extends Model> = (this: T, key: unknown, source: T) => (() => void) | void | null;
33
33
  namespace Instruction {
34
34
  type Getter<T> = (source: Model) => T;
@@ -54,7 +54,7 @@ interface Model {
54
54
  is: this;
55
55
  }
56
56
  declare class Model {
57
- constructor(id?: string | number | (() => void | (() => void)));
57
+ constructor(arg?: string | (() => void | (() => void)));
58
58
  /** Pull current values from state. Flattens all models and exotic values recursively. */
59
59
  get(): Model.State<this>;
60
60
  /** Run a function which will run automatically when accessed values change. */
package/dist/index.js CHANGED
@@ -159,50 +159,39 @@ var NOTIFY = /* @__PURE__ */ new WeakMap();
159
159
  var PENDING2 = /* @__PURE__ */ new WeakMap();
160
160
  var define = Object.defineProperty;
161
161
  var Model = class _Model {
162
- constructor(id) {
162
+ constructor(arg) {
163
163
  let Type = this.constructor;
164
- const state = {};
165
164
  define(this, "is", { value: this });
166
- if (typeof id == "function") {
167
- const cb = id;
168
- id = void 0;
169
- this.get(() => cb());
170
- }
171
- STATE.set(this, state);
172
- ID.set(this, id ? String(id) : `${Type}-${uid()}`);
165
+ STATE.set(this, {});
166
+ ID.set(this, typeof arg == "string" ? arg : `${Type}-${uid()}`);
173
167
  while (true) {
174
168
  new Set(NOTIFY.get(Type)).forEach((x) => addListener(this, x));
175
169
  if (Type === _Model)
176
170
  break;
177
171
  Type = Object.getPrototypeOf(Type);
178
172
  }
179
- addListener(this, () => {
180
- for (const key in this) {
181
- const desc = Object.getOwnPropertyDescriptor(this, key);
182
- if ("value" in desc) {
183
- state[key] = desc.value;
184
- define(this, key, {
185
- enumerable: true,
186
- set: (x) => update(this, key, x),
187
- get() {
188
- return watch(this, key, state[key]);
189
- }
190
- });
191
- }
192
- }
173
+ addListener(this, bootstrap);
174
+ if (typeof arg == "function")
193
175
  addListener(this, () => {
194
- for (const [_, value] of this)
195
- if (value instanceof _Model && PARENT.get(value) === this)
196
- value.set(null);
197
- Object.freeze(state);
198
- }, null);
199
- return null;
200
- });
176
+ const cleanup = arg();
177
+ if (typeof cleanup == "function")
178
+ addListener(this, cleanup, null);
179
+ return null;
180
+ });
201
181
  }
202
182
  get(arg1, arg2) {
203
183
  const self = this.is;
204
- if (typeof arg1 == "function")
205
- return effect(self, arg1);
184
+ if (typeof arg1 == "function") {
185
+ let pending = /* @__PURE__ */ new Set();
186
+ return effect(self, (state) => {
187
+ const cb = arg1.call(state, state, pending);
188
+ return cb === null ? null : (update2) => {
189
+ pending = PENDING2.get(self);
190
+ if (typeof cb == "function")
191
+ return cb(update2);
192
+ };
193
+ });
194
+ }
206
195
  if (arg1 === void 0)
207
196
  return extract(self);
208
197
  if (typeof arg2 == "function") {
@@ -286,6 +275,29 @@ define(Model, "toString", {
286
275
  return this.name;
287
276
  }
288
277
  });
278
+ function bootstrap() {
279
+ const state = STATE.get(this);
280
+ for (const key in this) {
281
+ const desc = Object.getOwnPropertyDescriptor(this, key);
282
+ if ("value" in desc) {
283
+ state[key] = desc.value;
284
+ define(this, key, {
285
+ configurable: false,
286
+ set: (x) => update(this, key, x),
287
+ get() {
288
+ return watch(this, key, state[key]);
289
+ }
290
+ });
291
+ }
292
+ }
293
+ addListener(this, () => {
294
+ for (const [_, value] of this)
295
+ if (value instanceof Model && PARENT.get(value) === this)
296
+ value.set(null);
297
+ Object.freeze(state);
298
+ }, null);
299
+ return null;
300
+ }
289
301
  function fetch(subject, property, required) {
290
302
  const state = STATE.get(subject);
291
303
  if (property in state || required === false) {
@@ -363,7 +375,9 @@ function add(instruction) {
363
375
  }
364
376
  Model.on((_, subject) => {
365
377
  const state = STATE.get(subject);
366
- Object.entries(Object.getOwnPropertyDescriptors(subject)).forEach(([key, { value }]) => {
378
+ Object.entries(
379
+ Object.getOwnPropertyDescriptors(subject)
380
+ ).forEach(([key, { value }]) => {
367
381
  const instruction = INSTRUCT.get(value);
368
382
  if (!instruction)
369
383
  return;
package/dist/index.mjs CHANGED
@@ -126,50 +126,39 @@ var NOTIFY = /* @__PURE__ */ new WeakMap();
126
126
  var PENDING2 = /* @__PURE__ */ new WeakMap();
127
127
  var define = Object.defineProperty;
128
128
  var Model = class _Model {
129
- constructor(id) {
129
+ constructor(arg) {
130
130
  let Type = this.constructor;
131
- const state = {};
132
131
  define(this, "is", { value: this });
133
- if (typeof id == "function") {
134
- const cb = id;
135
- id = void 0;
136
- this.get(() => cb());
137
- }
138
- STATE.set(this, state);
139
- ID.set(this, id ? String(id) : `${Type}-${uid()}`);
132
+ STATE.set(this, {});
133
+ ID.set(this, typeof arg == "string" ? arg : `${Type}-${uid()}`);
140
134
  while (true) {
141
135
  new Set(NOTIFY.get(Type)).forEach((x) => addListener(this, x));
142
136
  if (Type === _Model)
143
137
  break;
144
138
  Type = Object.getPrototypeOf(Type);
145
139
  }
146
- addListener(this, () => {
147
- for (const key in this) {
148
- const desc = Object.getOwnPropertyDescriptor(this, key);
149
- if ("value" in desc) {
150
- state[key] = desc.value;
151
- define(this, key, {
152
- enumerable: true,
153
- set: (x) => update(this, key, x),
154
- get() {
155
- return watch(this, key, state[key]);
156
- }
157
- });
158
- }
159
- }
140
+ addListener(this, bootstrap);
141
+ if (typeof arg == "function")
160
142
  addListener(this, () => {
161
- for (const [_, value] of this)
162
- if (value instanceof _Model && PARENT.get(value) === this)
163
- value.set(null);
164
- Object.freeze(state);
165
- }, null);
166
- return null;
167
- });
143
+ const cleanup = arg();
144
+ if (typeof cleanup == "function")
145
+ addListener(this, cleanup, null);
146
+ return null;
147
+ });
168
148
  }
169
149
  get(arg1, arg2) {
170
150
  const self = this.is;
171
- if (typeof arg1 == "function")
172
- return effect(self, arg1);
151
+ if (typeof arg1 == "function") {
152
+ let pending = /* @__PURE__ */ new Set();
153
+ return effect(self, (state) => {
154
+ const cb = arg1.call(state, state, pending);
155
+ return cb === null ? null : (update2) => {
156
+ pending = PENDING2.get(self);
157
+ if (typeof cb == "function")
158
+ return cb(update2);
159
+ };
160
+ });
161
+ }
173
162
  if (arg1 === void 0)
174
163
  return extract(self);
175
164
  if (typeof arg2 == "function") {
@@ -253,6 +242,29 @@ define(Model, "toString", {
253
242
  return this.name;
254
243
  }
255
244
  });
245
+ function bootstrap() {
246
+ const state = STATE.get(this);
247
+ for (const key in this) {
248
+ const desc = Object.getOwnPropertyDescriptor(this, key);
249
+ if ("value" in desc) {
250
+ state[key] = desc.value;
251
+ define(this, key, {
252
+ configurable: false,
253
+ set: (x) => update(this, key, x),
254
+ get() {
255
+ return watch(this, key, state[key]);
256
+ }
257
+ });
258
+ }
259
+ }
260
+ addListener(this, () => {
261
+ for (const [_, value] of this)
262
+ if (value instanceof Model && PARENT.get(value) === this)
263
+ value.set(null);
264
+ Object.freeze(state);
265
+ }, null);
266
+ return null;
267
+ }
256
268
  function fetch(subject, property, required) {
257
269
  const state = STATE.get(subject);
258
270
  if (property in state || required === false) {
@@ -330,7 +342,9 @@ function add(instruction) {
330
342
  }
331
343
  Model.on((_, subject) => {
332
344
  const state = STATE.get(subject);
333
- Object.entries(Object.getOwnPropertyDescriptors(subject)).forEach(([key, { value }]) => {
345
+ Object.entries(
346
+ Object.getOwnPropertyDescriptors(subject)
347
+ ).forEach(([key, { value }]) => {
334
348
  const instruction = INSTRUCT.get(value);
335
349
  if (!instruction)
336
350
  return;
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.36.0",
32
- "gitHead": "09b42668a6cdd0eb10be56985e0b72bbead26a88"
31
+ "version": "0.36.2",
32
+ "gitHead": "6bd9a56d67a2972248ed85a27e22f96d8577495a"
33
33
  }