@expressive/mvc 0.6.0 → 0.6.3
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 +37 -39
- package/lib/index.esm.js +119 -111
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +119 -111
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -229,10 +229,8 @@ declare function act<S>(action: Async<S>): typeof action & {
|
|
|
229
229
|
};
|
|
230
230
|
|
|
231
231
|
declare namespace get {
|
|
232
|
-
type Function<T,
|
|
233
|
-
type Factory<T,
|
|
234
|
-
type Getter = (controller: Controller, key: string) => any;
|
|
235
|
-
type Factory2<T, S = unknown> = (this: S, key: string, thisArg: S) => T;
|
|
232
|
+
type Function<T, S = any> = (this: S, on: S) => T;
|
|
233
|
+
type Factory<T, S = unknown> = (this: S, key: string, thisArg: S) => T;
|
|
236
234
|
}
|
|
237
235
|
/**
|
|
238
236
|
* Implement a computed value; output will be generated by provided function.
|
|
@@ -249,43 +247,43 @@ declare function get<R, T>(source: T, compute: (this: T, on: T) => R, suspend?:
|
|
|
249
247
|
* @param compute - Factory function to generate a getter to subscribe dependancies.
|
|
250
248
|
* @param suspend - Value will throw suspense when evaulating to undefined.
|
|
251
249
|
*/
|
|
252
|
-
declare function get<R, T>(compute: (property: string) => (this: T, state: T) => R, suspend: true): Exclude<R, undefined>;
|
|
253
|
-
declare function get<R, T>(compute: (property: string) => (this: T, state: T) => R, suspend?: boolean): R;
|
|
250
|
+
declare function get<R, T>(compute: (property: string, on: T) => (this: T, state: T) => R, suspend: true): Exclude<R, undefined>;
|
|
251
|
+
declare function get<R, T>(compute: (property: string, on: T) => (this: T, state: T) => R, suspend?: boolean): R;
|
|
254
252
|
/**
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
declare function get<T>(factory: get.
|
|
270
|
-
declare function get<T, S>(factory: get.
|
|
271
|
-
declare function get<T>(factory: get.
|
|
272
|
-
declare function get<T, S>(factory: get.
|
|
253
|
+
* Set property with an async function.
|
|
254
|
+
*
|
|
255
|
+
* Property cannot be accessed until factory resolves, yeilding a result.
|
|
256
|
+
* If accessed while processing, React Suspense will be thrown.
|
|
257
|
+
*
|
|
258
|
+
* - `required: true` (default) -
|
|
259
|
+
* Run factory immediately upon creation of model instance.
|
|
260
|
+
* - `required: false` -
|
|
261
|
+
* Run factory only if/when accessed.
|
|
262
|
+
* Value will always throw suspense at least once - use with caution.
|
|
263
|
+
*
|
|
264
|
+
* @param factory - Callback run to derrive property value.
|
|
265
|
+
* @param required - (default: true) Run factory immediately on creation, otherwise on access.
|
|
266
|
+
*/
|
|
267
|
+
declare function get<T>(factory: get.Factory<Promise<T>>, required: false): T | undefined;
|
|
268
|
+
declare function get<T, S>(factory: get.Factory<Promise<T>, S>, required: false): T | undefined;
|
|
269
|
+
declare function get<T>(factory: get.Factory<Promise<T>>, required?: boolean): T;
|
|
270
|
+
declare function get<T, S>(factory: get.Factory<Promise<T>, S>, required?: boolean): T;
|
|
273
271
|
/**
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
declare function get<T>(factory: get.
|
|
286
|
-
declare function get<T, S>(factory: get.
|
|
287
|
-
declare function get<T>(factory: get.
|
|
288
|
-
declare function get<T, S>(factory: get.
|
|
272
|
+
* Set property with a factory function.
|
|
273
|
+
*
|
|
274
|
+
* - `required: true` (default) -
|
|
275
|
+
* Run factory immediately upon creation of model instance.
|
|
276
|
+
* - `required: false` -
|
|
277
|
+
* Run factory only if/when accessed.
|
|
278
|
+
* Value will always throw suspense at least once - use with caution.
|
|
279
|
+
*
|
|
280
|
+
* @param factory - Callback run to derrive property value.
|
|
281
|
+
* @param required - (default: true) Run factory immediately on creation, otherwise on access.
|
|
282
|
+
*/
|
|
283
|
+
declare function get<T>(factory: get.Factory<T>, required: false): T | undefined;
|
|
284
|
+
declare function get<T, S>(factory: get.Factory<T, S>, required: false): T | undefined;
|
|
285
|
+
declare function get<T>(factory: get.Factory<T>, required?: boolean): T;
|
|
286
|
+
declare function get<T, S>(factory: get.Factory<T, S>, required?: boolean): T;
|
|
289
287
|
/**
|
|
290
288
|
* Assign a property with result of a promise.
|
|
291
289
|
*/
|
package/lib/index.esm.js
CHANGED
|
@@ -17,11 +17,11 @@ function issues(register) {
|
|
|
17
17
|
return Library;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const Oops$
|
|
20
|
+
const Oops$c = issues({
|
|
21
21
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
22
22
|
});
|
|
23
23
|
function suspend(source, key) {
|
|
24
|
-
const error = Oops$
|
|
24
|
+
const error = Oops$c.NotReady(source.subject, key);
|
|
25
25
|
const promise = new Promise(resolve => {
|
|
26
26
|
const release = source.addListener(forKey => {
|
|
27
27
|
if (forKey == key)
|
|
@@ -61,106 +61,12 @@ function mayRetry(fn) {
|
|
|
61
61
|
return compute();
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
const Oops$
|
|
65
|
-
|
|
66
|
-
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
|
|
67
|
-
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
|
|
68
|
-
FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
69
|
-
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
70
|
-
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`
|
|
64
|
+
const Oops$b = issues({
|
|
65
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
71
66
|
});
|
|
72
67
|
const INFO = new WeakMap();
|
|
73
68
|
const KEYS = new WeakMap();
|
|
74
69
|
const ORDER = new WeakMap();
|
|
75
|
-
function get(arg0, arg1, arg2) {
|
|
76
|
-
return apply(function get(key) {
|
|
77
|
-
const { subject } = this;
|
|
78
|
-
const computeRequired = arg1 === true || arg2 === true;
|
|
79
|
-
const factoryRequired = arg1 !== false && arg2 !== false;
|
|
80
|
-
let getter;
|
|
81
|
-
// Easy mistake, using a peer, will always be unresolved.
|
|
82
|
-
if (typeof arg0 == "symbol")
|
|
83
|
-
throw Oops$a.PeerNotAllowed(subject, key);
|
|
84
|
-
if (typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
|
|
85
|
-
throw Oops$a.BadSource(subject, key, arg0);
|
|
86
|
-
this.state.set(key, undefined);
|
|
87
|
-
const init = () => {
|
|
88
|
-
let source = this;
|
|
89
|
-
let setter;
|
|
90
|
-
if (typeof arg0 == "function") {
|
|
91
|
-
const result = mayRetry(() => arg0.call(subject, key, subject));
|
|
92
|
-
if (typeof result == "function")
|
|
93
|
-
setter = result;
|
|
94
|
-
else {
|
|
95
|
-
getter = factoryMode(this, result, key, factoryRequired);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
else if (arg0 instanceof Promise) {
|
|
100
|
-
getter = factoryMode(this, arg0, key, factoryRequired);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
else if (typeof arg1 == "function") {
|
|
104
|
-
// replace source controller in-case it is different
|
|
105
|
-
source = ensure(arg0);
|
|
106
|
-
setter = arg1;
|
|
107
|
-
}
|
|
108
|
-
else
|
|
109
|
-
throw new Error(`Factory argument cannot be ${arg1}`);
|
|
110
|
-
getter = computeMode(this, source, setter, key, computeRequired);
|
|
111
|
-
};
|
|
112
|
-
if (typeof arg0 == "function" && factoryRequired)
|
|
113
|
-
try {
|
|
114
|
-
init();
|
|
115
|
-
}
|
|
116
|
-
catch (err) {
|
|
117
|
-
Oops$a.ComputeFailed(subject, key).warn();
|
|
118
|
-
throw err;
|
|
119
|
-
}
|
|
120
|
-
return () => {
|
|
121
|
-
if (!getter)
|
|
122
|
-
init();
|
|
123
|
-
return getter();
|
|
124
|
-
};
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
function factoryMode(self, output, key, required) {
|
|
128
|
-
const { subject, state } = self;
|
|
129
|
-
let pending;
|
|
130
|
-
let error;
|
|
131
|
-
if (output instanceof Promise) {
|
|
132
|
-
state.set(key, undefined);
|
|
133
|
-
pending = output
|
|
134
|
-
.catch(err => error = err)
|
|
135
|
-
.then(val => {
|
|
136
|
-
state.set(key, val);
|
|
137
|
-
return val;
|
|
138
|
-
})
|
|
139
|
-
.finally(() => {
|
|
140
|
-
pending = undefined;
|
|
141
|
-
self.update(key);
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
state.set(key, output);
|
|
145
|
-
const suspend = () => {
|
|
146
|
-
if (required === false)
|
|
147
|
-
return undefined;
|
|
148
|
-
const issue = Oops$a.NotReady(subject, key);
|
|
149
|
-
Object.assign(pending, {
|
|
150
|
-
message: issue.message,
|
|
151
|
-
stack: issue.stack
|
|
152
|
-
});
|
|
153
|
-
throw pending;
|
|
154
|
-
};
|
|
155
|
-
return () => {
|
|
156
|
-
if (error)
|
|
157
|
-
throw error;
|
|
158
|
-
if (pending)
|
|
159
|
-
return suspend();
|
|
160
|
-
if (state.has(key))
|
|
161
|
-
return state.get(key);
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
70
|
function computeMode(self, source, setter, key, required) {
|
|
165
71
|
const { subject, state } = self;
|
|
166
72
|
let sub;
|
|
@@ -172,7 +78,7 @@ function computeMode(self, source, setter, key, required) {
|
|
|
172
78
|
return setter.call(sub.proxy, sub.proxy);
|
|
173
79
|
}
|
|
174
80
|
catch (err) {
|
|
175
|
-
Oops$
|
|
81
|
+
Oops$b.Failed(subject, key, initial).warn();
|
|
176
82
|
throw err;
|
|
177
83
|
}
|
|
178
84
|
};
|
|
@@ -241,7 +147,7 @@ function flush(control) {
|
|
|
241
147
|
KEYS.delete(control);
|
|
242
148
|
}
|
|
243
149
|
|
|
244
|
-
const Oops$
|
|
150
|
+
const Oops$a = issues({
|
|
245
151
|
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
246
152
|
});
|
|
247
153
|
const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
@@ -254,7 +160,7 @@ function createEffect(callback) {
|
|
|
254
160
|
if (unSet instanceof Promise)
|
|
255
161
|
unSet = undefined;
|
|
256
162
|
if (unSet && typeof unSet !== "function")
|
|
257
|
-
throw Oops$
|
|
163
|
+
throw Oops$a.BadCallback();
|
|
258
164
|
};
|
|
259
165
|
}
|
|
260
166
|
function createValueEffect(callback) {
|
|
@@ -270,11 +176,11 @@ function createValueEffect(callback) {
|
|
|
270
176
|
if (typeof out == "function")
|
|
271
177
|
unSet = out;
|
|
272
178
|
else
|
|
273
|
-
throw Oops$
|
|
179
|
+
throw Oops$a.BadCallback();
|
|
274
180
|
};
|
|
275
181
|
}
|
|
276
182
|
|
|
277
|
-
const Oops$
|
|
183
|
+
const Oops$9 = issues({
|
|
278
184
|
Timeout: (keys, timeout) => `No update for [${keys}] within ${timeout}.`,
|
|
279
185
|
StrictUpdate: () => `Strict update() did not find pending updates.`,
|
|
280
186
|
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
@@ -357,7 +263,7 @@ class Model {
|
|
|
357
263
|
const invoke = (key) => {
|
|
358
264
|
if (!key) {
|
|
359
265
|
clear();
|
|
360
|
-
reject(Oops$
|
|
266
|
+
reject(Oops$9.Timeout(select, typeof argument == "number"
|
|
361
267
|
? `${argument}ms`
|
|
362
268
|
: `lifetime of ${this}`));
|
|
363
269
|
}
|
|
@@ -444,11 +350,11 @@ class Model {
|
|
|
444
350
|
arg = undefined;
|
|
445
351
|
}
|
|
446
352
|
if (!frame.size && arg === true)
|
|
447
|
-
return Promise.reject(Oops$
|
|
353
|
+
return Promise.reject(Oops$9.StrictUpdate());
|
|
448
354
|
return {
|
|
449
355
|
then: (callback) => {
|
|
450
356
|
if (!callback)
|
|
451
|
-
throw Oops$
|
|
357
|
+
throw Oops$9.NoChaining();
|
|
452
358
|
if (frame.size || arg !== false)
|
|
453
359
|
waiting.add(() => {
|
|
454
360
|
callback(getUpdate(this));
|
|
@@ -777,7 +683,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
777
683
|
});
|
|
778
684
|
}
|
|
779
685
|
|
|
780
|
-
const Oops$
|
|
686
|
+
const Oops$8 = issues({
|
|
781
687
|
DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
|
|
782
688
|
});
|
|
783
689
|
function act(task) {
|
|
@@ -785,7 +691,7 @@ function act(task) {
|
|
|
785
691
|
let pending = false;
|
|
786
692
|
const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
787
693
|
if (pending)
|
|
788
|
-
return Promise.reject(Oops$
|
|
694
|
+
return Promise.reject(Oops$8.DuplicatePending(key));
|
|
789
695
|
pending = true;
|
|
790
696
|
this.update(key);
|
|
791
697
|
try {
|
|
@@ -807,6 +713,106 @@ function act(task) {
|
|
|
807
713
|
});
|
|
808
714
|
}
|
|
809
715
|
|
|
716
|
+
function factoryMode(self, output, key, required) {
|
|
717
|
+
const { subject, state } = self;
|
|
718
|
+
let pending;
|
|
719
|
+
let error;
|
|
720
|
+
if (output instanceof Promise) {
|
|
721
|
+
state.set(key, undefined);
|
|
722
|
+
pending = output
|
|
723
|
+
.catch(err => error = err)
|
|
724
|
+
.then(val => {
|
|
725
|
+
state.set(key, val);
|
|
726
|
+
return val;
|
|
727
|
+
})
|
|
728
|
+
.finally(() => {
|
|
729
|
+
pending = undefined;
|
|
730
|
+
self.update(key);
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
state.set(key, output);
|
|
734
|
+
const suspend = () => {
|
|
735
|
+
if (required === false)
|
|
736
|
+
return undefined;
|
|
737
|
+
const issue = Oops$7.NotReady(subject, key);
|
|
738
|
+
Object.assign(pending, {
|
|
739
|
+
message: issue.message,
|
|
740
|
+
stack: issue.stack
|
|
741
|
+
});
|
|
742
|
+
throw pending;
|
|
743
|
+
};
|
|
744
|
+
return () => {
|
|
745
|
+
if (error)
|
|
746
|
+
throw error;
|
|
747
|
+
if (pending)
|
|
748
|
+
return suspend();
|
|
749
|
+
if (state.has(key))
|
|
750
|
+
return state.get(key);
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
const Oops$7 = issues({
|
|
755
|
+
// BadSource: (model, property, got) =>
|
|
756
|
+
// `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
|
|
757
|
+
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
|
|
758
|
+
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
759
|
+
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
760
|
+
FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
761
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
762
|
+
});
|
|
763
|
+
function get(arg0, arg1, arg2) {
|
|
764
|
+
return apply(function get(key) {
|
|
765
|
+
const { subject } = this;
|
|
766
|
+
const computeRequired = arg1 === true || arg2 === true;
|
|
767
|
+
const factoryRequired = arg1 !== false && arg2 !== false;
|
|
768
|
+
let getter;
|
|
769
|
+
// Easy mistake, using a peer, will always be unresolved.
|
|
770
|
+
if (typeof arg0 == "symbol")
|
|
771
|
+
throw Oops$7.PeerNotAllowed(subject, key);
|
|
772
|
+
// if(typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
|
|
773
|
+
// throw Oops.BadSource(subject, key, arg0);
|
|
774
|
+
this.state.set(key, undefined);
|
|
775
|
+
const init = () => {
|
|
776
|
+
let source = this;
|
|
777
|
+
let setter;
|
|
778
|
+
if (typeof arg0 == "function") {
|
|
779
|
+
const result = mayRetry(() => arg0.call(subject, key, subject));
|
|
780
|
+
if (typeof result == "function")
|
|
781
|
+
setter = result;
|
|
782
|
+
else {
|
|
783
|
+
getter = factoryMode(this, result, key, factoryRequired);
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
else if (arg0 instanceof Promise) {
|
|
788
|
+
getter = factoryMode(this, arg0, key, factoryRequired);
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
else if (typeof arg1 == "function") {
|
|
792
|
+
// replace source controller in-case it is different
|
|
793
|
+
source = ensure(arg0);
|
|
794
|
+
setter = arg1;
|
|
795
|
+
}
|
|
796
|
+
else
|
|
797
|
+
throw new Error(`Factory argument cannot be ${arg1}`);
|
|
798
|
+
getter = computeMode(this, source, setter, key, computeRequired);
|
|
799
|
+
};
|
|
800
|
+
if (typeof arg0 == "function" && factoryRequired)
|
|
801
|
+
try {
|
|
802
|
+
init();
|
|
803
|
+
}
|
|
804
|
+
catch (err) {
|
|
805
|
+
Oops$7.ComputeFailed(subject, key).warn();
|
|
806
|
+
throw err;
|
|
807
|
+
}
|
|
808
|
+
return () => {
|
|
809
|
+
if (!getter)
|
|
810
|
+
init();
|
|
811
|
+
return getter();
|
|
812
|
+
};
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
|
|
810
816
|
function ref(callback) {
|
|
811
817
|
return apply(function ref(key) {
|
|
812
818
|
const value = this.ref(key, callback && createValueEffect(callback));
|
|
@@ -993,9 +999,11 @@ function use$1(input, argument) {
|
|
|
993
999
|
let pending;
|
|
994
1000
|
let error;
|
|
995
1001
|
let get = (_local) => state.get(key);
|
|
996
|
-
if (typeof input === "function")
|
|
997
|
-
|
|
998
|
-
|
|
1002
|
+
if (typeof input === "function") {
|
|
1003
|
+
if ("prototype" in input &&
|
|
1004
|
+
input === input.prototype.constructor)
|
|
1005
|
+
input = new input();
|
|
1006
|
+
}
|
|
999
1007
|
else if (input && typeof input !== "object")
|
|
1000
1008
|
throw Oops$6.BadArgument(typeof input);
|
|
1001
1009
|
if (input instanceof Map || input instanceof Set)
|