@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expressive/mvc",
3
- "version": "1.0.0-beta.2",
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
- "hooks"
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": "rollup --config --sourcemap --watch",
28
- "prebuild": "rm -rf lib/",
29
- "publish:pre": "npm version prerelease --preid=beta",
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
- Consumer,
9
- Provider
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';
@@ -1,101 +1,228 @@
1
1
  import Model from '.';
2
- import { Async, Class, EffectCallback, InstanceOf } from './types';
3
-
4
- declare namespace Directives {
5
- /**
6
- * Creates a new child-instance of specified controller.
7
- *
8
- * @param Peer - Type of Model to create and apply to host property.
9
- * @param callback - Fired after controller is created and ready for use.
10
- */
11
- export function setChild <T extends typeof Model> (Peer: T, callback?: (i: InstanceOf<T>) => void): InstanceOf<T>
12
-
13
- /**
14
- * Fetches and assigns the controller which spawned this host.
15
- * When parent assigns an instance via `use()` directive, it
16
- * will be made available to child upon this request.
17
- *
18
- * @param Expects - Type of controller compatible with this class.
19
- * @param required - Throw if controller is created independantly.
20
- */
21
- export function setParent <T extends typeof Model> (Expects: T, required: true): InstanceOf<T>;
22
- export function setParent <T extends typeof Model> (Expects: T, required?: false): InstanceOf<T> | undefined;
23
-
24
- /**
25
- * Find and attach most applicable instance of Model via context.
26
- *
27
- * Expects a `<Provider>` of target controller to exist.
28
- * Host controller will search element-hierarchy relative to where it spawned.
29
- *
30
- * @param Type - Type of controller to attach to property.
31
- * @param required - Throw if instance of Type cannot be found.
32
- */
33
- export function setPeer <T extends Class> (Type: T, required?: boolean): InstanceOf<T>;
34
-
35
- /**
36
- * Sets property to synchronously call an effect upon update (much like a setter).
37
- *
38
- * **Note:** Use generic-type to specifiy property signature.
39
- * Value will always start off as undefined.
40
- *
41
- * @param callback - Effect-callback fired upon update of host property.
42
- */
43
- export function setEffect <T = any> (callback: EffectCallback<T>): T | undefined;
44
-
45
- /**
46
- * Sets property to synchronously call effect upon update.
47
- *
48
- * @param starting - Beginning value of host property.
49
- * @param callback - Effect-callback fired upon set of host property.
50
- */
51
- export function setEffect <T = any> (starting: T, callback: EffectCallback<T>): T;
52
-
53
- /**
54
- * Creates a ref-compatible property for use with components.
55
- * Will persist value, and updates to this are made part of controller event-stream.
56
- *
57
- * *Output is simultaneously a ref-function and ref-object, use as needed.*
58
- *
59
- * @param callback - Optional callback to synchronously fire when reference is first set or does update.
60
- */
61
- export function setReference <T = HTMLElement> (callback?: EffectCallback<T>): ((next: T) => void) & { current: T | null };
62
-
63
- /**
64
- * Sets an exotic method with managed ready-state. Property accepts an async function.
65
- *
66
- * When an act-method is invoked, its `active` property to true for duration of call.
67
- * This is emitted as an update to property, both when called and after returns (or throws).
68
- *
69
- * **Note:** Subsequent calls will immediately throw if one is still pending.
70
- *
71
- * @param action - Action to fire when resulting property is invoked.
72
- */
73
- export function setAction <T extends Async>(action: T): T & { active: boolean };
74
-
75
- /**
76
- * Implement a computed value; output will be generated by provided function.
77
- *
78
- * *Alternative to using native getters; works exactly the same!*
79
- *
80
- * @param fn - Factory function to generate value and subscribe dependancies.
81
- */
82
- export function setComputed <T, R>(fn: (this: T, on: T) => R): R;
83
-
84
- /**
85
- * Memoized value. Computes and stores a value returned by provided factory.
86
- * Equivalent to a getter, sans the automatic updates.
87
- *
88
- * @param compute - Factory for memoized value.
89
- * @param lazy - Wait until accessed to introduce value.
90
- */
91
- export function setMemo <T> (compute: () => T, lazy?: boolean): T;
92
-
93
- /**
94
- * Flag property as not to be tracked. Useful if changes often with no real-time impact.
95
- *
96
- * @param value - starting value of property.
97
- */
98
- export function setIgnored <T> (value?: T): T;
99
- }
100
-
101
- export = Directives;
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>;