@expressive/mvc 1.0.0-beta.22 → 1.0.0-beta.23
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 +56 -31
- package/package.json +5 -2
- package/types/context.d.ts +4 -6
- package/types/instructions.d.ts +6 -0
package/lib/index.js
CHANGED
|
@@ -1080,51 +1080,76 @@ function from(source, setter, getter) {
|
|
|
1080
1080
|
const Oops$1 = issues({
|
|
1081
1081
|
ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
1082
1082
|
});
|
|
1083
|
+
function pending(source, compute) {
|
|
1084
|
+
return (source === undefined ?
|
|
1085
|
+
suspendForValue() :
|
|
1086
|
+
typeof source == "function" && !source.prototype ?
|
|
1087
|
+
suspendForAsync(source) :
|
|
1088
|
+
suspendForComputed(source, compute));
|
|
1089
|
+
}
|
|
1083
1090
|
/**
|
|
1084
|
-
*
|
|
1085
|
-
*
|
|
1091
|
+
* Get value, suspend instead if undefined.
|
|
1092
|
+
*
|
|
1093
|
+
* Throws suspense promise also interpretable as an error.
|
|
1094
|
+
* React could handle it but other contexts probably not.
|
|
1086
1095
|
*/
|
|
1087
|
-
function
|
|
1088
|
-
const
|
|
1096
|
+
function pendingValue(via, key) {
|
|
1097
|
+
const value = via.state[key];
|
|
1098
|
+
if (value !== undefined)
|
|
1099
|
+
return value;
|
|
1100
|
+
const error = Oops$1.ValueNotReady(via.subject, key);
|
|
1089
1101
|
const promise = new Promise(resolve => {
|
|
1090
|
-
const release =
|
|
1091
|
-
|
|
1092
|
-
|
|
1102
|
+
const release = via.addListener({
|
|
1103
|
+
[key](value) {
|
|
1104
|
+
if (value !== undefined) {
|
|
1105
|
+
release();
|
|
1106
|
+
resolve();
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1093
1109
|
});
|
|
1094
1110
|
});
|
|
1095
|
-
|
|
1111
|
+
throw Object.assign(promise, {
|
|
1112
|
+
toString: () => String(error),
|
|
1113
|
+
message: error.message,
|
|
1114
|
+
stack: error.stack
|
|
1115
|
+
});
|
|
1096
1116
|
}
|
|
1097
|
-
function
|
|
1098
|
-
|
|
1099
|
-
return
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1117
|
+
function suspendForComputed(source, compute) {
|
|
1118
|
+
function getter(_value, key) {
|
|
1119
|
+
return pendingValue(manage(this), key);
|
|
1120
|
+
}
|
|
1121
|
+
return from(source, compute, getter);
|
|
1122
|
+
}
|
|
1123
|
+
function suspendForValue() {
|
|
1124
|
+
return apply(function pending(key) {
|
|
1125
|
+
this.state[key] = undefined;
|
|
1126
|
+
return {
|
|
1127
|
+
set: this.setter(key),
|
|
1128
|
+
get: () => pendingValue(this, key)
|
|
1129
|
+
};
|
|
1130
|
+
});
|
|
1106
1131
|
}
|
|
1107
1132
|
function suspendForAsync(source) {
|
|
1108
1133
|
return apply(function suspense(key) {
|
|
1134
|
+
const subject = this.subject;
|
|
1109
1135
|
let waiting = true;
|
|
1110
|
-
let
|
|
1136
|
+
let value;
|
|
1111
1137
|
let error;
|
|
1112
1138
|
return () => {
|
|
1113
|
-
if (waiting) {
|
|
1114
|
-
const issue = Oops$1.ValueNotReady(this.subject, key);
|
|
1115
|
-
const promise = source
|
|
1116
|
-
.call(this.subject, key)
|
|
1117
|
-
.catch(err => error = err)
|
|
1118
|
-
.then((value) => output = value)
|
|
1119
|
-
.finally(() => waiting = false);
|
|
1120
|
-
throw Object.assign(promise, {
|
|
1121
|
-
message: issue.message,
|
|
1122
|
-
stack: issue.stack
|
|
1123
|
-
});
|
|
1124
|
-
}
|
|
1125
1139
|
if (error)
|
|
1126
1140
|
throw error;
|
|
1127
|
-
|
|
1141
|
+
if (!waiting)
|
|
1142
|
+
return value;
|
|
1143
|
+
const issue = Oops$1.ValueNotReady(subject, key);
|
|
1144
|
+
let suspend = source
|
|
1145
|
+
.call(subject, key)
|
|
1146
|
+
.catch(err => error = err)
|
|
1147
|
+
.then(out => value = out)
|
|
1148
|
+
.finally(() => waiting = false);
|
|
1149
|
+
throw Object.assign(suspend, {
|
|
1150
|
+
message: issue.message,
|
|
1151
|
+
stack: issue.stack
|
|
1152
|
+
});
|
|
1128
1153
|
};
|
|
1129
1154
|
});
|
|
1130
1155
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expressive/mvc",
|
|
3
|
+
"version": "1.0.0-beta.23",
|
|
3
4
|
"description": "Use classes to define state in React!",
|
|
4
|
-
"version": "1.0.0-beta.22",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Gabe Klein",
|
|
7
7
|
"email": "gabe@termtm.com",
|
|
@@ -50,7 +50,10 @@
|
|
|
50
50
|
},
|
|
51
51
|
"release": {
|
|
52
52
|
"branches": [
|
|
53
|
-
{
|
|
53
|
+
{
|
|
54
|
+
"name": "beta",
|
|
55
|
+
"prerelease": true
|
|
56
|
+
}
|
|
54
57
|
]
|
|
55
58
|
}
|
|
56
59
|
}
|
package/types/context.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { Consumer, ReactElement, ReactNode
|
|
1
|
+
import { Consumer, ReactElement, ReactNode } from "react";
|
|
2
2
|
import { Model } from "./model"
|
|
3
3
|
import { Class } from "./types";
|
|
4
4
|
|
|
5
|
-
type Output = ReactElement<any, any> | null;
|
|
6
|
-
|
|
7
5
|
export namespace Provider {
|
|
8
6
|
type Item = Model | typeof Model;
|
|
9
7
|
type Collection<T extends Item> = T[] | { [key: string]: T };
|
|
@@ -21,7 +19,7 @@ export namespace Provider {
|
|
|
21
19
|
type Props<T extends Item> = MultipleProps<T> | NormalProps<T>;
|
|
22
20
|
}
|
|
23
21
|
|
|
24
|
-
export function Provider<T extends Provider.Item>(props: Provider.Props<T>):
|
|
22
|
+
export function Provider<T extends Provider.Item>(props: Provider.Props<T>): ReactElement<typeof props>;
|
|
25
23
|
|
|
26
24
|
export namespace Consumer {
|
|
27
25
|
type HasProps<E extends Class> = {
|
|
@@ -50,10 +48,10 @@ export namespace Consumer {
|
|
|
50
48
|
* Similar to `tap()`, updates to properties accessed in
|
|
51
49
|
* this function will cause a refresh when they change.
|
|
52
50
|
*/
|
|
53
|
-
children: (value: InstanceType<E>) =>
|
|
51
|
+
children: (value: InstanceType<E>) => ReactElement<any, any> | null;
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
type Props<T extends Class> = HasProps<T> | GetProps<T> | RenderProps<T>
|
|
57
55
|
}
|
|
58
56
|
|
|
59
|
-
export function Consumer<T extends Class>(props: Consumer.Props<T>):
|
|
57
|
+
export function Consumer<T extends Class>(props: Consumer.Props<T>): null;
|
package/types/instructions.d.ts
CHANGED
|
@@ -194,6 +194,12 @@ export function memo <T> (compute: () => T, lazy?: boolean): T;
|
|
|
194
194
|
*/
|
|
195
195
|
export function lazy <T> (value?: T): T;
|
|
196
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Pending value. Will suspend unless value is defined,
|
|
199
|
+
* suspense resolves when a value is aquired.
|
|
200
|
+
*/
|
|
201
|
+
export function pending <T = boolean> (): Exclude<T, undefined>;
|
|
202
|
+
|
|
197
203
|
/**
|
|
198
204
|
* Suspend during the execution of given function to obtain value.
|
|
199
205
|
*
|