@expressive/mvc 0.1.0 → 0.2.1

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 CHANGED
@@ -51,10 +51,10 @@ function issues(register) {
51
51
  }
52
52
 
53
53
  const Oops$c = issues({
54
- ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
54
+ NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
55
55
  });
56
56
  function suspend(source, key) {
57
- const error = Oops$c.ValueNotReady(source.subject, key);
57
+ const error = Oops$c.NotReady(source.subject, key);
58
58
  const promise = new Promise(resolve => {
59
59
  const release = source.addListener(forKey => {
60
60
  if (forKey == key)
@@ -95,7 +95,7 @@ function mayRetry(fn) {
95
95
  }
96
96
 
97
97
  const Oops$b = issues({
98
- BadEffectCallback: () => `Callback for effect-callback may only return a function.`
98
+ BadCallback: () => `Callback for effect-callback may only return a function.`
99
99
  });
100
100
  const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
101
101
  function define(target, key, value) {
@@ -120,7 +120,7 @@ function createEffect(callback) {
120
120
  if (unSet instanceof Promise)
121
121
  unSet = undefined;
122
122
  if (unSet && typeof unSet !== "function")
123
- throw Oops$b.BadEffectCallback();
123
+ throw Oops$b.BadCallback();
124
124
  };
125
125
  }
126
126
  function createValueEffect(callback) {
@@ -136,7 +136,7 @@ function createValueEffect(callback) {
136
136
  if (typeof out == "function")
137
137
  unSet = out;
138
138
  else
139
- throw Oops$b.BadEffectCallback();
139
+ throw Oops$b.BadCallback();
140
140
  };
141
141
  }
142
142
 
@@ -156,16 +156,16 @@ const LOCAL = Symbol("LOCAL");
156
156
  const STATE = Symbol("STATE");
157
157
  class Model {
158
158
  constructor() {
159
- const control = new Controller(this);
160
- define(this, CONTROL, control);
159
+ define(this, CONTROL, new Controller(this));
161
160
  define(this, "get", this);
161
+ define(this, "is", this);
162
162
  defineLazy(this, "set", () => {
163
+ const controller = control(this);
163
164
  const assign = (key, value) => {
164
- control.update(key, value);
165
+ controller.update(key, value);
165
166
  };
166
- ready(control);
167
- for (const key of getOwnPropertyNames(control.proxy))
168
- define(assign, key, control.ref(key));
167
+ for (const key of getOwnPropertyNames(controller.proxy))
168
+ define(assign, key, controller.ref(key));
169
169
  return assign;
170
170
  });
171
171
  }
@@ -353,10 +353,10 @@ class Subscriber {
353
353
  }
354
354
 
355
355
  const Oops$a = issues({
356
- BadComputedSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
356
+ BadSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
357
357
  PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
358
- ComputeFailed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
359
- ComputedEarly: (property) => `Note: Computed values don't run until accessed, except when subscribed to. '${property}' getter may have run earlier than intended.`
358
+ Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
359
+ Early: (property) => `Note: Computed values don't run until accessed, except when subscribed to. '${property}' getter may have run earlier than intended.`
360
360
  });
361
361
  const INIT = new WeakSet();
362
362
  const INFO = new WeakMap();
@@ -383,7 +383,7 @@ function from(source, arg1, arg2) {
383
383
  }
384
384
  // Regular function is too ambiguous so not allowed.
385
385
  else
386
- throw Oops$a.BadComputedSource(subject, key, source);
386
+ throw Oops$a.BadSource(subject, key, source);
387
387
  let sub;
388
388
  const setter = arg1;
389
389
  const info = { key, parent, priority: 1 };
@@ -398,7 +398,7 @@ function from(source, arg1, arg2) {
398
398
  return setter.call(sub.proxy, sub.proxy);
399
399
  }
400
400
  catch (err) {
401
- Oops$a.ComputeFailed(subject, key, !!initial).warn();
401
+ Oops$a.Failed(subject, key, !!initial).warn();
402
402
  throw err;
403
403
  }
404
404
  }
@@ -439,7 +439,7 @@ function from(source, arg1, arg2) {
439
439
  }
440
440
  catch (e) {
441
441
  if (early)
442
- Oops$a.ComputedEarly(key).warn();
442
+ Oops$a.Early(key).warn();
443
443
  throw e;
444
444
  }
445
445
  finally {
@@ -623,9 +623,6 @@ function control(subject, cb) {
623
623
  control = new Controller(subject);
624
624
  define(subject, CONTROL, control);
625
625
  }
626
- return ready(control, cb);
627
- }
628
- function ready(control, cb) {
629
626
  const ready = READY.has(control);
630
627
  if (!ready) {
631
628
  if (cb) {
@@ -723,14 +720,14 @@ function forSubscriber(fn) {
723
720
  }
724
721
 
725
722
  const Oops$8 = issues({
726
- DuplicateAction: (key) => `Invoked action ${key} but one is already active.`
723
+ DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
727
724
  });
728
725
  function act(task) {
729
726
  return apply(function act(key) {
730
727
  let pending = false;
731
728
  const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
732
729
  if (pending)
733
- return Promise.reject(Oops$8.DuplicateAction(key));
730
+ return Promise.reject(Oops$8.DuplicatePending(key));
734
731
  pending = true;
735
732
  this.update(key);
736
733
  try {
@@ -835,28 +832,74 @@ function createRef(key, cb) {
835
832
 
836
833
  const Oops$7 = issues({
837
834
  NonOptional: (Parent, key) => `Property ${Parent}.${key} is marked as required.`,
838
- BadFactory: () => `Set instruction can only accept a factory or undefined.`,
839
- ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
840
- FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`
835
+ NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
836
+ Failed: (model, key) => `Generating initial value for ${model}.${key} failed.`
841
837
  });
842
838
  function set(factory, argument) {
843
839
  return apply(function set(key) {
840
+ const { subject, state } = this;
841
+ const required = argument === true || argument === undefined;
844
842
  let set;
845
843
  let get;
846
844
  let suspense;
847
- const required = argument === true || argument === undefined;
848
845
  if (factory === undefined)
849
846
  suspense = true;
850
- else if (typeof factory === "function")
851
- get = pendingFactory(this, key, factory, required);
852
- else
853
- throw Oops$7.BadFactory();
847
+ else {
848
+ let pending;
849
+ let error;
850
+ const init = () => {
851
+ const output = typeof factory == "function" ?
852
+ mayRetry(() => factory.call(subject, key, subject)) :
853
+ factory;
854
+ if (output instanceof Promise) {
855
+ pending = output
856
+ .catch(err => error = err)
857
+ .then(val => state[key] = val)
858
+ .finally(() => {
859
+ pending = undefined;
860
+ this.update(key);
861
+ });
862
+ return;
863
+ }
864
+ return state[key] = output;
865
+ };
866
+ const suspend = () => {
867
+ if (required === false)
868
+ return undefined;
869
+ const issue = Oops$7.NotReady(subject, key);
870
+ Object.assign(pending, {
871
+ message: issue.message,
872
+ stack: issue.stack
873
+ });
874
+ throw pending;
875
+ };
876
+ if (required)
877
+ try {
878
+ init();
879
+ }
880
+ catch (err) {
881
+ Oops$7.Failed(subject, key).warn();
882
+ throw err;
883
+ }
884
+ get = () => {
885
+ if (pending)
886
+ return suspend();
887
+ if (error)
888
+ throw error;
889
+ if (key in state)
890
+ return state[key];
891
+ let output = init();
892
+ return pending
893
+ ? suspend()
894
+ : output;
895
+ };
896
+ }
854
897
  if (typeof argument == "function")
855
898
  set = createValueEffect(argument);
856
899
  else
857
900
  set = (value) => {
858
901
  if (value === undefined && required)
859
- throw Oops$7.NonOptional(this.subject, key);
902
+ throw Oops$7.NonOptional(subject, key);
860
903
  };
861
904
  return {
862
905
  set,
@@ -864,63 +907,12 @@ function set(factory, argument) {
864
907
  suspense
865
908
  };
866
909
  });
867
- }
868
- function pendingFactory(parent, key, fn, required) {
869
- const { subject, state } = parent;
870
- let pending;
871
- let error;
872
- const init = () => {
873
- const output = mayRetry(() => {
874
- return fn.call(subject, key, subject);
875
- });
876
- if (output instanceof Promise) {
877
- pending = output
878
- .catch(err => error = err)
879
- .then(val => state[key] = val)
880
- .finally(() => {
881
- pending = undefined;
882
- parent.update(key);
883
- });
884
- return;
885
- }
886
- return state[key] = output;
887
- };
888
- const suspend = () => {
889
- if (required === false)
890
- return undefined;
891
- const issue = Oops$7.ValueNotReady(subject, key);
892
- Object.assign(pending, {
893
- message: issue.message,
894
- stack: issue.stack
895
- });
896
- throw pending;
897
- };
898
- if (required)
899
- try {
900
- init();
901
- }
902
- catch (err) {
903
- Oops$7.FactoryFailed(subject, key).warn();
904
- throw err;
905
- }
906
- return () => {
907
- if (pending)
908
- return suspend();
909
- if (error)
910
- throw error;
911
- if (key in state)
912
- return state[key];
913
- let output = init();
914
- return pending
915
- ? suspend()
916
- : output;
917
- };
918
910
  }
919
911
 
920
912
  const Parent = new WeakMap();
921
913
  const Oops$6 = issues({
922
- ParentRequired: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
923
- UnexpectedParent: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
914
+ Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
915
+ Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
924
916
  });
925
917
  function parent(Expects, required) {
926
918
  return apply(function parent() {
@@ -929,10 +921,10 @@ function parent(Expects, required) {
929
921
  const expected = Expects.name;
930
922
  if (!value) {
931
923
  if (required !== false)
932
- throw Oops$6.ParentRequired(expected, child);
924
+ throw Oops$6.Required(expected, child);
933
925
  }
934
926
  else if (!(value instanceof Expects))
935
- throw Oops$6.UnexpectedParent(expected, child, value);
927
+ throw Oops$6.Unexpected(expected, child, value);
936
928
  return { value };
937
929
  });
938
930
  }
@@ -1037,19 +1029,19 @@ class Lookup {
1037
1029
  const LookupContext = React__default["default"].createContext(new Lookup());
1038
1030
  const useLookup = () => React__default["default"].useContext(LookupContext);
1039
1031
  const Oops$4 = issues({
1040
- NothingInContext: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`
1032
+ NotFound: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`
1041
1033
  });
1042
- function useInContext(Type, arg) {
1034
+ function useLocal(Type, arg) {
1043
1035
  const instance = useLookup().get(Type);
1044
1036
  if (!instance && arg !== false)
1045
- throw Oops$4.NothingInContext(Type.name);
1037
+ throw Oops$4.NotFound(Type.name);
1046
1038
  return typeof arg == "string" ?
1047
1039
  instance[arg] :
1048
1040
  instance;
1049
1041
  }
1050
1042
 
1051
1043
  const Oops$3 = issues({
1052
- CantAttachGlobal: (parent, child) => `Global '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
1044
+ NotAllowed: (parent, child) => `Global '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
1053
1045
  AmbientRequired: (requested, requester, key) => `Attempted to find an instance of ${requested} in context. It is required for [${requester}.${key}], but one could not be found.`
1054
1046
  });
1055
1047
  const PendingContext = new WeakMap();
@@ -1063,7 +1055,7 @@ function tap(type, argument) {
1063
1055
  };
1064
1056
  const { subject } = this;
1065
1057
  if ("set" in subject.constructor)
1066
- throw Oops$3.CantAttachGlobal(subject, type.name);
1058
+ throw Oops$3.NotAllowed(subject, type.name);
1067
1059
  getPending(subject).push(context => {
1068
1060
  let instance = context.get(type);
1069
1061
  if (typeof argument == "function") {
@@ -1207,7 +1199,7 @@ function useTap(source, path, expect) {
1207
1199
  if ("get" in source)
1208
1200
  return () => source.get();
1209
1201
  if ("prototype" in source)
1210
- return () => useInContext(source);
1202
+ return () => useLocal(source);
1211
1203
  else
1212
1204
  return source;
1213
1205
  }, [])();
@@ -1242,7 +1234,7 @@ class MVC extends Model {
1242
1234
  return useModel(this, arg, callback);
1243
1235
  }
1244
1236
  static get(required) {
1245
- return useInContext(this, required);
1237
+ return useLocal(this, required);
1246
1238
  }
1247
1239
  static tap(key, expect) {
1248
1240
  return useTap(this, key, expect);
@@ -1288,25 +1280,28 @@ class MVC extends Model {
1288
1280
  }
1289
1281
 
1290
1282
  const Oops$2 = issues({
1291
- BadConsumerProps: () => `Provider expects either a render function, 'get' or 'has' props.`
1283
+ BadProps: () => `Provider expects either a render function, 'get' or 'has' props.`
1292
1284
  });
1293
1285
  function Consumer(props) {
1294
- const { get, has, children, of: Control } = props;
1286
+ const { get, has, children, for: type } = props;
1295
1287
  if (typeof children == "function")
1296
- return children(useTap(Control));
1288
+ return children(useTap(type));
1297
1289
  const callback = has || get;
1298
1290
  if (typeof callback == "function")
1299
- callback(useInContext(Control, !!has));
1291
+ callback(useLocal(type, !!has));
1300
1292
  else
1301
- throw Oops$2.BadConsumerProps();
1293
+ throw Oops$2.BadProps();
1302
1294
  return null;
1303
1295
  }
1304
1296
 
1305
1297
  const Oops$1 = issues({
1306
- NoProviderType: () => `Provider 'of' prop must be Model, typeof Model or a collection of them.`
1298
+ NoType: () => "Provider 'of' prop must be Model, typeof Model or a collection of them.",
1299
+ PropDeprecated: () => "Provider `of` prop is deprecated, use `for` instead."
1307
1300
  });
1308
1301
  function Provider(props) {
1309
- const context = useNewContext(props.of);
1302
+ if ("of" in props)
1303
+ throw Oops$1.PropDeprecated();
1304
+ const context = useNewContext(props.for);
1310
1305
  const render = props.children;
1311
1306
  useAppliedProps(context, props);
1312
1307
  React__default["default"].useLayoutEffect(() => () => context.pop(), []);
@@ -1318,7 +1313,7 @@ function useNewContext(inject) {
1318
1313
  const from = useLookup();
1319
1314
  return React__default["default"].useMemo(() => {
1320
1315
  if (!inject)
1321
- throw Oops$1.NoProviderType();
1316
+ throw Oops$1.NoType();
1322
1317
  const context = from.push(inject);
1323
1318
  for (const instance of context.local)
1324
1319
  if (instance)
@@ -1332,7 +1327,7 @@ function useAppliedProps(within, props) {
1332
1327
  const targets = within.local;
1333
1328
  return function integrate(props) {
1334
1329
  for (const [key, value] of entries(props))
1335
- if (key != "of" && key != "children")
1330
+ if (["of", "for", "children"].indexOf(key) < 0)
1336
1331
  for (const into of targets)
1337
1332
  if (into && key in into)
1338
1333
  into[key] = value;
@@ -1353,15 +1348,15 @@ function RenderFunction(props) {
1353
1348
  }
1354
1349
 
1355
1350
  const Oops = issues({
1356
- GlobalDoesNotExist: (name) => `Tried to access singleton ${name}, but none exist! Did you forget to initialize?\nCall ${name}.create() before attempting to access, or consider using ${name}.use() instead.`,
1357
- GlobalExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
1351
+ DoesNotExist: (name) => `Tried to access singleton ${name}, but none exist! Did you forget to initialize?\nCall ${name}.create() before attempting to access, or consider using ${name}.use() instead.`,
1352
+ AlreadyExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
1358
1353
  });
1359
1354
  const Active = new WeakMap();
1360
1355
  class Global extends MVC {
1361
1356
  static create(...args) {
1362
1357
  const Type = this;
1363
1358
  if (Active.has(Type))
1364
- throw Oops.GlobalExists(this.name);
1359
+ throw Oops.AlreadyExists(this.name);
1365
1360
  const instance = super.create(...args);
1366
1361
  Active.set(Type, instance);
1367
1362
  return instance;
@@ -1379,7 +1374,7 @@ class Global extends MVC {
1379
1374
  static get(arg) {
1380
1375
  const instance = Active.get(this);
1381
1376
  if (!instance && arg !== false)
1382
- throw Oops.GlobalDoesNotExist(this.name);
1377
+ throw Oops.DoesNotExist(this.name);
1383
1378
  return (typeof arg == "string" ?
1384
1379
  instance[arg] :
1385
1380
  instance);
@@ -1415,7 +1410,7 @@ exports.set = set;
1415
1410
  exports.tap = tap;
1416
1411
  exports.use = use$1;
1417
1412
  exports.useFrom = useFrom;
1418
- exports.useInContext = useInContext;
1413
+ exports.useLocal = useLocal;
1419
1414
  exports.useModel = useModel;
1420
1415
  exports.useTap = useTap;
1421
1416
  //# sourceMappingURL=index.js.map