@expressive/mvc 1.0.0-beta.2 → 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/README.md +86 -78
- package/lib/index.js +980 -829
- package/package.json +14 -9
- package/types/context.d.ts +57 -0
- package/types/index.d.ts +3 -20
- package/types/instructions.d.ts +227 -100
- package/types/model.d.ts +193 -34
- package/types/selector.ts +18 -0
- package/types/types.d.ts +7 -1
- package/types/controller.d.ts +0 -56
- package/types/react.d.ts +0 -46
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expressive/mvc",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.23",
|
|
4
4
|
"description": "Use classes to define state in React!",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Gabe Klein",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"react",
|
|
17
|
-
"
|
|
17
|
+
"mvc"
|
|
18
18
|
],
|
|
19
19
|
"main": "lib/index.js",
|
|
20
20
|
"types": "types/index.d.ts",
|
|
@@ -24,13 +24,9 @@
|
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "rollup --config",
|
|
27
|
-
"watch": "
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"preversion": "jest",
|
|
31
|
-
"postversion": "npm run build; npm publish",
|
|
32
|
-
"postpublish": "git push; git push --tags; rm -rf lib",
|
|
33
|
-
"test": "jest --watchAll"
|
|
27
|
+
"watch": "jest --watchAll",
|
|
28
|
+
"test": "jest --collectCoverage",
|
|
29
|
+
"prebuild": "rm -rf lib/"
|
|
34
30
|
},
|
|
35
31
|
"peerDependencies": {
|
|
36
32
|
"react": ">=17.0.2"
|
|
@@ -47,8 +43,17 @@
|
|
|
47
43
|
"react-test-renderer": "^17.0.2",
|
|
48
44
|
"rollup": "^2.52.2",
|
|
49
45
|
"rollup-plugin-typescript2": "^0.30.0",
|
|
46
|
+
"semantic-release": "^18.0.1",
|
|
50
47
|
"ts-jest": "^27.0.3",
|
|
51
48
|
"tslib": "^2.3.0",
|
|
52
49
|
"typescript": "typescript@>=3.8 <5.0"
|
|
50
|
+
},
|
|
51
|
+
"release": {
|
|
52
|
+
"branches": [
|
|
53
|
+
{
|
|
54
|
+
"name": "beta",
|
|
55
|
+
"prerelease": true
|
|
56
|
+
}
|
|
57
|
+
]
|
|
53
58
|
}
|
|
54
59
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Consumer, ReactElement, ReactNode } from "react";
|
|
2
|
+
import { Model } from "./model"
|
|
3
|
+
import { Class } from "./types";
|
|
4
|
+
|
|
5
|
+
export namespace Provider {
|
|
6
|
+
type Item = Model | typeof Model;
|
|
7
|
+
type Collection<T extends Item> = T[] | { [key: string]: T };
|
|
8
|
+
type Existent<E> = E extends Class ? InstanceType<E> : E extends Model ? E : never;
|
|
9
|
+
|
|
10
|
+
type NormalProps<E, I = Existent<E>> =
|
|
11
|
+
& { of: E, children: ReactNode | ((instance: I) => ReactNode) }
|
|
12
|
+
& Model.Data<I>;
|
|
13
|
+
|
|
14
|
+
// FIX: This fails to exclude properties with same key but different type.
|
|
15
|
+
type MultipleProps<T extends Item> =
|
|
16
|
+
& { of: Collection<T>, children?: ReactNode | (() => ReactNode) }
|
|
17
|
+
& Model.Data<Existent<T>>;
|
|
18
|
+
|
|
19
|
+
type Props<T extends Item> = MultipleProps<T> | NormalProps<T>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function Provider<T extends Provider.Item>(props: Provider.Props<T>): ReactElement<typeof props>;
|
|
23
|
+
|
|
24
|
+
export namespace Consumer {
|
|
25
|
+
type HasProps<E extends Class> = {
|
|
26
|
+
/** Type of controller to fetch from context. */
|
|
27
|
+
of: E;
|
|
28
|
+
/**
|
|
29
|
+
* Getter function. Is called on every natural render of this component.
|
|
30
|
+
* Will throw if usable instance cannot be found in context.
|
|
31
|
+
*/
|
|
32
|
+
has: (value: InstanceType<E>) => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type GetProps<E extends Class> = {
|
|
36
|
+
/** Type of controller to fetch from context. */
|
|
37
|
+
of: E;
|
|
38
|
+
/** Getter function. Is called on every natural render of this component. */
|
|
39
|
+
get: (value: InstanceType<E> | undefined) => void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type RenderProps<E extends Class> = {
|
|
43
|
+
/** Type of controller to fetch from context. */
|
|
44
|
+
of: E;
|
|
45
|
+
/**
|
|
46
|
+
* Render function, will receive instance of desired controller.
|
|
47
|
+
*
|
|
48
|
+
* Similar to `tap()`, updates to properties accessed in
|
|
49
|
+
* this function will cause a refresh when they change.
|
|
50
|
+
*/
|
|
51
|
+
children: (value: InstanceType<E>) => ReactElement<any, any> | null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
type Props<T extends Class> = HasProps<T> | GetProps<T> | RenderProps<T>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function Consumer<T extends Class>(props: Consumer.Props<T>): null;
|
package/types/index.d.ts
CHANGED
|
@@ -4,23 +4,6 @@ export {
|
|
|
4
4
|
Singleton
|
|
5
5
|
} from './model';
|
|
6
6
|
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from './react';
|
|
11
|
-
|
|
12
|
-
export {
|
|
13
|
-
setChild as use,
|
|
14
|
-
setParent as parent,
|
|
15
|
-
setPeer as tap,
|
|
16
|
-
setEffect as on,
|
|
17
|
-
setReference as ref,
|
|
18
|
-
setAction as act,
|
|
19
|
-
setComputed as from,
|
|
20
|
-
setMemo as memo,
|
|
21
|
-
setIgnored as lazy
|
|
22
|
-
} from "./instructions";
|
|
23
|
-
|
|
24
|
-
export {
|
|
25
|
-
Selector
|
|
26
|
-
} from './selector'
|
|
7
|
+
export * from './context';
|
|
8
|
+
export * from './instructions';
|
|
9
|
+
export * from './selector';
|
package/types/instructions.d.ts
CHANGED
|
@@ -1,101 +1,228 @@
|
|
|
1
1
|
import Model from '.';
|
|
2
|
-
import { Async, Class,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
export
|
|
2
|
+
import { Async, Class, InstanceOf, InterceptCallback } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Run instruction as controller sets itself up.
|
|
6
|
+
* This will specialize the behavior of a given property.
|
|
7
|
+
**/
|
|
8
|
+
export function apply <T = any> (instruction: Model.Instruction<T>, name?: string): T;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new child-instance of specified controller.
|
|
12
|
+
*
|
|
13
|
+
* @param Peer - Type of Model to create and apply to host property.
|
|
14
|
+
* @param callback - Fired after controller is created and ready for use.
|
|
15
|
+
*/
|
|
16
|
+
export function use <T extends Class> (Peer: T, callback: (i?: InstanceOf<T>) => void): InstanceOf<T> | undefined;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new child-instance of specified controller.
|
|
20
|
+
*
|
|
21
|
+
* @param Peer - Type of Model to create and apply to host property.
|
|
22
|
+
* @param required - Property should be non-nullable, will throw if value is set to undefined.
|
|
23
|
+
*/
|
|
24
|
+
export function use <T extends Class> (Peer: T, required: false): InstanceOf<T> | undefined;
|
|
25
|
+
export function use <T extends Class> (Peer: T, required?: true): InstanceOf<T>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new child-instance of specified controller.
|
|
29
|
+
*
|
|
30
|
+
* @param factory - Generate model for use.
|
|
31
|
+
* @param callback - Fired after controller is created and ready for use.
|
|
32
|
+
*/
|
|
33
|
+
export function use <T extends Model | undefined> (factory: () => T, callback?: (i: T) => void): T;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Create a child-instance relationship with provided model.
|
|
37
|
+
*
|
|
38
|
+
* Note: If `peer` is not already initialized before parent is
|
|
39
|
+
* (created with `new` as opposed to create method), that model will
|
|
40
|
+
* attach this via `parent()` instruction. It will not howerver, if
|
|
41
|
+
* already active.
|
|
42
|
+
*
|
|
43
|
+
* @param factory - Instance of model to attach.
|
|
44
|
+
* @param callback - Fired after controller is attached.
|
|
45
|
+
*/
|
|
46
|
+
export function use <T extends Model> (peer: T, callback?: (i: T) => void): T;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Create a placeholder for specified Model type.
|
|
50
|
+
*/
|
|
51
|
+
export function use <T extends Model> (): T | undefined;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Generate a child controller from specified object. Object's values are be trackable, as would be for a full-model.
|
|
55
|
+
*
|
|
56
|
+
* Note: Child will *not* be same object as one provided.
|
|
57
|
+
*/
|
|
58
|
+
export function use <T extends {}> (object: T): T;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generic instruction used by `use()` and `tap()` for recursive subscription.
|
|
62
|
+
*
|
|
63
|
+
* @param from - Instruction body is run upon parent create. Return function to fetch current value of field.
|
|
64
|
+
*/
|
|
65
|
+
export function child <T extends Model> (from: (this: Model.Controller, key: string) => () => T | undefined): T;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Fetches and assigns the controller which spawned this host.
|
|
69
|
+
* When parent assigns an instance via `use()` directive, it
|
|
70
|
+
* will be made available to child upon this request.
|
|
71
|
+
*
|
|
72
|
+
* @param Expects - Type of controller compatible with this class.
|
|
73
|
+
* @param required - Throw if controller is created independantly.
|
|
74
|
+
*/
|
|
75
|
+
export function parent <T extends typeof Model> (Expects: T, required: true): InstanceOf<T>;
|
|
76
|
+
export function parent <T extends typeof Model> (Expects: T, required?: false): InstanceOf<T> | undefined;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Find and attach most applicable instance of Model via context.
|
|
80
|
+
*
|
|
81
|
+
* Host controller will search element-hierarchy relative to where it spawned.
|
|
82
|
+
*
|
|
83
|
+
* @param Type - Type of model to find from context
|
|
84
|
+
* @param callback -
|
|
85
|
+
* - Invoked after context is scanned, is passed result - either found or undefined.
|
|
86
|
+
* - If argument is inadequate, but required, your implemention should simply throw.
|
|
87
|
+
* - If inadequate and not required, conditionally return false.
|
|
88
|
+
*/
|
|
89
|
+
export function tap <T extends typeof Model> (Type: T, callback?: (instance?: InstanceOf<T>) => void | true): InstanceOf<T>;
|
|
90
|
+
export function tap <T extends typeof Model> (Type: T, callback?: (instance?: InstanceOf<T>) => void | false): InstanceOf<T> | undefined;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Find and attach most applicable instance of Model via context.
|
|
94
|
+
*
|
|
95
|
+
* Expects a `<Provider>` of target controller to exist.
|
|
96
|
+
* Host controller will search element-hierarchy relative to where it spawned.
|
|
97
|
+
*
|
|
98
|
+
* @param Type - Type of controller to attach to property.
|
|
99
|
+
* @param required - Throw if instance of Type cannot be found.
|
|
100
|
+
*/
|
|
101
|
+
export function tap <T extends Class> (Type: T, required?: boolean): InstanceOf<T>;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Cause property to synchronously run effect upon update.
|
|
105
|
+
*
|
|
106
|
+
* Callback may return an effect callback, Promise (ignored), or a boolean.
|
|
107
|
+
*
|
|
108
|
+
* If a boolean is returned explicitly, new value will be dropped. Useful to override.
|
|
109
|
+
*
|
|
110
|
+
* - `false` will prevent update.
|
|
111
|
+
* - `true` will emit update (unchanged).
|
|
112
|
+
*
|
|
113
|
+
* @param initialValue - Beginning value of host property.
|
|
114
|
+
* @param onUpdate - Effect-callback fired upon set of host property.
|
|
115
|
+
*/
|
|
116
|
+
export function on <T = any> (initialValue: undefined, onUpdate: InterceptCallback<T>): T | undefined;
|
|
117
|
+
export function on <T = any> (initialValue: T, onUpdate: InterceptCallback<T>): T;
|
|
118
|
+
|
|
119
|
+
/** Object with references to all managed values of `T`. */
|
|
120
|
+
export type Refs <T extends Model> = { [P in Model.Fields<T>]: Model.Ref<T[P]> };
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Creates an object with references to all managed values.
|
|
124
|
+
* Each property will set value in state when invoked.
|
|
125
|
+
*
|
|
126
|
+
* *Properties are simultaneously a ref-function and ref-object, use as needed.*
|
|
127
|
+
*
|
|
128
|
+
* @param target - Source model from which to reference values.
|
|
129
|
+
*/
|
|
130
|
+
export function ref <T extends Model> (target: T): Refs<T>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Creates a ref-compatible property.
|
|
134
|
+
* Will persist value, and updates to this are made part of controller event-stream.
|
|
135
|
+
*
|
|
136
|
+
* *Output is simultaneously a ref-function and ref-object, use as needed.*
|
|
137
|
+
*
|
|
138
|
+
* @param callback - Optional callback to synchronously fire when reference is first set or does update.
|
|
139
|
+
*/
|
|
140
|
+
export function ref <T = HTMLElement> (callback?: InterceptCallback<T>): Model.Ref<T>;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Sets an exotic method with managed ready-state. Property accepts an async function.
|
|
144
|
+
*
|
|
145
|
+
* When an act-method is invoked, its `active` property to true for duration of call.
|
|
146
|
+
* This is emitted as an update to property, both when called and after returns (or throws).
|
|
147
|
+
*
|
|
148
|
+
* **Note:** Subsequent calls will immediately throw if one is still pending.
|
|
149
|
+
*
|
|
150
|
+
* @param action - Action to fire when resulting property is invoked.
|
|
151
|
+
*/
|
|
152
|
+
export function act <T extends Async> (action: T): T & { active: boolean };
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Implement a computed value; output is returned by function from provided factory.
|
|
156
|
+
*
|
|
157
|
+
* @param compute - Factory function to generate a getter to subscribe dependancies.
|
|
158
|
+
*/
|
|
159
|
+
export function from <R> (compute: (property: string) => (this: any, state: any) => R): R;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Implement a computed value; output will be generated by provided function.
|
|
163
|
+
*
|
|
164
|
+
* @param source - Source Model to find and subscribe to, for input.
|
|
165
|
+
*
|
|
166
|
+
* @param compute - Compute function. Bound to a subscriber-proxy of source, returns output value.
|
|
167
|
+
* Will update automatically as input values change.
|
|
168
|
+
*/
|
|
169
|
+
export function from <T extends Class, R> (source: T, compute: (this: InstanceOf<T>, on: InstanceOf<T>) => R): R;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Implement a computed value; output will be generated by provided function.
|
|
173
|
+
*
|
|
174
|
+
* @param source - Source model from which computed value will be a subscriber.
|
|
175
|
+
*
|
|
176
|
+
* @param compute - Compute function. Bound to a subscriber-proxy of source, returns output value.
|
|
177
|
+
* Will update automatically as input values change.
|
|
178
|
+
*/
|
|
179
|
+
export function from <T, R> (source: T, compute: (this: T, on: T) => R): R;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Memoized value. Computes and stores a value returned by provided factory.
|
|
183
|
+
* Equivalent to a getter, sans the automatic updates.
|
|
184
|
+
*
|
|
185
|
+
* @param compute - Factory for memoized value.
|
|
186
|
+
* @param lazy - Wait until accessed to introduce value.
|
|
187
|
+
*/
|
|
188
|
+
export function memo <T> (compute: () => T, lazy?: boolean): T;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Flag property as not to be tracked. Useful if changes often with no real-time impact.
|
|
192
|
+
*
|
|
193
|
+
* @param value - starting value of property.
|
|
194
|
+
*/
|
|
195
|
+
export function lazy <T> (value?: T): T;
|
|
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
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Suspend during the execution of given function to obtain value.
|
|
205
|
+
*
|
|
206
|
+
* @param waitFor - Async function to suspend for.
|
|
207
|
+
*/
|
|
208
|
+
export function pending (waitFor: () => Promise<void>): undefined;
|
|
209
|
+
export function pending <T> (waitFor: () => Promise<T>): T;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Suspend for a computed value, returned by syncronous function.
|
|
213
|
+
*
|
|
214
|
+
* If accessed while computing to undefined, will throw a promise. Function is subscribed
|
|
215
|
+
* and will re-evaluate anytime used properties change. Once function returns any value,
|
|
216
|
+
* outstanding promises resolve and are not thrown on subsequent access of this property.
|
|
217
|
+
*
|
|
218
|
+
* Similar to `from`, compute function will only run when inputs change and not upon access.
|
|
219
|
+
*
|
|
220
|
+
* This behavior is recursive. If return value _becomes_ undefined, property
|
|
221
|
+
* access will throw Promises again, awaiting its next value.
|
|
222
|
+
*
|
|
223
|
+
* @param source - Source object, from which computed value will be a subscriber.
|
|
224
|
+
*
|
|
225
|
+
* @param compute - Compute function returns output value. Bound to a subscriber of source.
|
|
226
|
+
* Will re-run automatically as input values change.
|
|
227
|
+
*/
|
|
228
|
+
export function pending <T, R> (source: T, compute: (this: T, on: T) => R): Exclude<R, undefined>;
|