@cyysummer/projector 0.0.3 → 0.0.5
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/dist/index.js +3 -2
- package/package.json +2 -2
- package/types/lib.d.ts +61 -15
- package/types/types.d.ts +15 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @cyysummer/projector v0.0.
|
|
2
|
+
* @cyysummer/projector v0.0.5
|
|
3
3
|
* (c) 2021-PRESENT Chris Liu
|
|
4
4
|
* @license MIT
|
|
5
5
|
**/
|
|
6
|
-
import
|
|
6
|
+
import E from"on-change";import{set as g}from"lodash-es";import{withEvents as I}from"@cyysummer/core";var i=class extends I(){constructor(e){super();this._paused=!1;this._shadow=structuredClone(e)}receive(e,r){if(this._paused)return;g(this._shadow,e,r);let c=[{path:e,value:r}];this.emit("record",{next:this._shadow,patches:c}),this._ensureProjector(),this._projector?.project(this._shadow,...c)}sendTo(e){typeof e=="function"?this._projectorFactory=e:this._projector=e}pause(){this._paused=!0}resume(){this._paused=!1}_ensureProjector(){!this._projector&&this._projectorFactory&&(this._projector=this._projectorFactory())}};import{get as d}from"lodash-es";var l=u=>{},p=class{constructor(t){this._strategy=t}chain(t){return async(e,r)=>{let c=n(r);for(let o of t)await o(e,{value:c})}}chainWith(t,e){return async(c,o)=>{let s=n(o),a=e(s);for(let f of t)await f(c,{value:a})}}create(t){return(e,r)=>{let c=n(r);return this._strategy.execute(e,t,c)}}createIf(t,e,r=l){return(c,o)=>{let s=n(o);return(t(s)?e:r)(c,{value:s})}}createIfRoot(t,e,r=l){return(c,o)=>(t(o.source)?e:r)(c,o)}createRoot(t,e){return(r,c)=>{let o=e(c.source);return this._strategy.execute(r,t,o)}}createForArray(t){return(e,r)=>{let c=r.path?d(r.source,r.path):r.value;if(c&&Array.isArray(c)&&c.length>0){let o=Object.keys(c[0]);return this._strategy.executeArray(e,t,o,c)}}}createForRaw(t,e){return(r,c)=>this._strategy.execute(r,t,e)}createWith(t,e){return(c,o)=>{let s=n(o),a=e(s);return this._strategy.execute(c,t,a)}}};function n(u){return u.source&&u.path?d(u.source,u.path):u.value}var h=class{constructor(t){this._schema=t;if(!t)throw new Error("Projector: Schema is required.")}project(t,...e){for(let r of e)this._dispatch(t,r)}_dispatch(t,e){let{path:r,value:c}=e,o=this._resolveEffect(r);o&&(this._ensureScheduler(),this._scheduler.enqueue({path:r.join("."),effect:o,ctx:{source:t,path:r,value:c}}))}_ensureScheduler(){if(!this._scheduler)throw new Error("Projector: no scheduler.")}_resolveEffect(t){let e=this._schema;for(let r of t){if(!e)return null;e=e[r]}return typeof e=="function"?e:null}},S=class extends h{constructor(t,e){super(t),this._scheduler=e}},y=class extends h{scheduleWith(t){return typeof t=="function"?this._schedulerFactory=t:this._scheduler=t,this}_ensureScheduler(){if(!this._scheduler&&this._schedulerFactory&&(this._scheduler=this._schedulerFactory()),!this._scheduler)throw new Error("Projector: no scheduler.")}};var T=class{constructor(t){this._target=t}withTarget(t){return typeof t=="function"?this._targetFactory=t:this._target=t,this}checkTarget(){if(!this._target&&this._targetFactory&&(this._target=this._targetFactory()),!this._target)throw new Error("Scheduler: target is not set")}},_=class extends T{constructor(){super(...arguments);this._queue=new Map}enqueue(e){return this._queue.set(e.path,e),this}async flush(){this.checkTarget(),log.trace("BufferedScheduler: flushing");let e=[...this._queue.values()];this._queue.clear();for(let r of e){let{effect:c,ctx:o}=r,s=c(this._target,o);s instanceof Promise&&await s}}};function C(u){let t=new i(u);return[E(u,t.receive.bind(t),{pathAsArray:!0}),t]}export{_ as BufferedScheduler,y as DynamicProjector,p as EffectBuilder,S as Projector,h as ProjectorBase,i as Recorder,T as Scheduler,C as track};
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyysummer/projector",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "A powerful state projection library for creating anything.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Chris Liu",
|
|
7
7
|
"files": [
|
|
8
|
-
"dist
|
|
8
|
+
"dist/*.js",
|
|
9
9
|
"types/**"
|
|
10
10
|
],
|
|
11
11
|
"type": "module",
|
package/types/lib.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Schema defines how to project changes from a source object to a target object.
|
|
3
|
+
*/
|
|
1
4
|
// prettier-ignore
|
|
2
5
|
type Schema<TSource, T = any> = TSource extends object ?
|
|
3
6
|
Partial<{
|
|
@@ -12,9 +15,15 @@ type Schema<TSource, T = any> = TSource extends object ?
|
|
|
12
15
|
// Else map T to effect.
|
|
13
16
|
: Effect<TSource, T>;
|
|
14
17
|
|
|
18
|
+
/**
|
|
19
|
+
* An effect defines how to project a value from source to target.
|
|
20
|
+
*/
|
|
15
21
|
// todo: Solve this `any`
|
|
16
22
|
type Effect<TSource, TValue> = (target: any, ctx: IEffectContext<TSource, TValue>) => MaybePromise<void>;
|
|
17
23
|
|
|
24
|
+
/**
|
|
25
|
+
* The context for an effect. It contains information about changes.
|
|
26
|
+
*/
|
|
18
27
|
interface IEffectContext<TSource, TValue> {
|
|
19
28
|
/**
|
|
20
29
|
* The source object.
|
|
@@ -32,9 +41,12 @@ interface IEffectContext<TSource, TValue> {
|
|
|
32
41
|
value: TValue;
|
|
33
42
|
}
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Strategy defines actual execution methods for projecting values to target.
|
|
46
|
+
*/
|
|
47
|
+
interface ITargetExecutionStrategy<TTarget, TLocation = any> {
|
|
48
|
+
execute<T>(target: TTarget, at: TLocation, value: T): MaybePromise<void>;
|
|
49
|
+
executeArray<T>(target: TTarget, at: TLocation, keys: Partial<keyof T>[], rows: T[]): MaybePromise<void>;
|
|
38
50
|
}
|
|
39
51
|
|
|
40
52
|
interface IProjector<TSource> {
|
|
@@ -71,11 +83,30 @@ declare const Recorder_base: Constructor<object> & (new (...args: any[]) => obje
|
|
|
71
83
|
*/
|
|
72
84
|
declare class Recorder<TSource extends object> extends Recorder_base {
|
|
73
85
|
private _paused;
|
|
86
|
+
private _projector?;
|
|
87
|
+
private _projectorFactory?;
|
|
74
88
|
private _shadow;
|
|
75
89
|
constructor(initial: TSource);
|
|
76
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Receive changes from the tracked object.
|
|
92
|
+
* @param path
|
|
93
|
+
* @param value
|
|
94
|
+
* @returns
|
|
95
|
+
*/
|
|
96
|
+
receive(path: any[], value: any): void;
|
|
97
|
+
/**
|
|
98
|
+
* Send changes to a projector.
|
|
99
|
+
* @param projector
|
|
100
|
+
*/
|
|
101
|
+
sendTo(projector: IProjector<TSource>): void;
|
|
102
|
+
/**
|
|
103
|
+
* Send changes to a projector.
|
|
104
|
+
* @param factory
|
|
105
|
+
*/
|
|
106
|
+
sendTo(factory: Func<IProjector<TSource>>): void;
|
|
77
107
|
pause(): void;
|
|
78
108
|
resume(): void;
|
|
109
|
+
private _ensureProjector;
|
|
79
110
|
}
|
|
80
111
|
|
|
81
112
|
/**
|
|
@@ -83,7 +114,7 @@ declare class Recorder<TSource extends object> extends Recorder_base {
|
|
|
83
114
|
*/
|
|
84
115
|
declare class EffectBuilder<TTarget, TSource extends object> {
|
|
85
116
|
private _strategy;
|
|
86
|
-
constructor(_strategy:
|
|
117
|
+
constructor(_strategy: ITargetExecutionStrategy<TTarget>);
|
|
87
118
|
/**
|
|
88
119
|
* Call multiple effects in sequence.
|
|
89
120
|
* @param effects Effects to call.
|
|
@@ -148,22 +179,32 @@ declare class EffectBuilder<TTarget, TSource extends object> {
|
|
|
148
179
|
createWith<T, R>(at: string, customizer: Func1<T, R>): Effect<TSource, R>;
|
|
149
180
|
}
|
|
150
181
|
|
|
151
|
-
declare class
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
constructor(_schema: Schema<TSource
|
|
182
|
+
declare abstract class ProjectorBase<TSource> implements IProjector<TSource> {
|
|
183
|
+
protected _schema: Schema<TSource>;
|
|
184
|
+
protected _scheduler?: IScheduler<any>;
|
|
185
|
+
constructor(_schema: Schema<TSource>);
|
|
155
186
|
project(next: TSource, ...patches: Patch[]): void;
|
|
156
|
-
|
|
157
|
-
|
|
187
|
+
protected _dispatch(next: TSource, patch: Patch): void;
|
|
188
|
+
protected _ensureScheduler(): void;
|
|
189
|
+
protected _resolveEffect(path: (string | symbol)[]): Effect<TSource, any> | null;
|
|
190
|
+
}
|
|
191
|
+
declare class Projector<TSource> extends ProjectorBase<TSource> {
|
|
192
|
+
constructor(_schema: Schema<TSource>, _scheduler: IScheduler<any>);
|
|
193
|
+
}
|
|
194
|
+
declare class DynamicProjector<TSource> extends ProjectorBase<TSource> {
|
|
195
|
+
private _schedulerFactory?;
|
|
196
|
+
scheduleWith(scheduler: IScheduler<any>): IProjector<TSource>;
|
|
197
|
+
scheduleWith(schedulerFactory: Func<IScheduler<any>>): IProjector<TSource>;
|
|
198
|
+
protected _ensureScheduler(): void;
|
|
158
199
|
}
|
|
159
200
|
|
|
160
201
|
/**
|
|
161
202
|
* Scheduler abstract class, used to schedule projector effects.
|
|
162
203
|
*/
|
|
163
204
|
declare abstract class Scheduler<TTarget> implements IScheduler<TTarget> {
|
|
164
|
-
protected _target
|
|
165
|
-
protected _targetFactory
|
|
166
|
-
constructor(_target?: TTarget |
|
|
205
|
+
protected _target?: TTarget | undefined;
|
|
206
|
+
protected _targetFactory?: Func<TTarget>;
|
|
207
|
+
constructor(_target?: TTarget | undefined);
|
|
167
208
|
abstract enqueue(item: IScheduleItem<TTarget, any>): IScheduler<TTarget>;
|
|
168
209
|
abstract flush(): MaybePromise<void>;
|
|
169
210
|
withTarget(target: TTarget): IScheduler<TTarget>;
|
|
@@ -179,6 +220,11 @@ declare class BufferedScheduler<TTarget> extends Scheduler<TTarget> {
|
|
|
179
220
|
flush(): Promise<void>;
|
|
180
221
|
}
|
|
181
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Track changes to an object.
|
|
225
|
+
* @param initial Source object to track. This must the raw object, not reactive-enabled object.
|
|
226
|
+
* @returns A tuple of the tracked object and a recorder.
|
|
227
|
+
*/
|
|
182
228
|
declare function track<TSource extends object>(initial: TSource): [TSource, Recorder<TSource>];
|
|
183
229
|
|
|
184
|
-
export { BufferedScheduler, EffectBuilder, Projector, Recorder, Scheduler, track };
|
|
230
|
+
export { BufferedScheduler, DynamicProjector, EffectBuilder, Projector, ProjectorBase, Recorder, Scheduler, track };
|
package/types/types.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Schema defines how to project changes from a source object to a target object.
|
|
3
|
+
*/
|
|
1
4
|
// prettier-ignore
|
|
2
5
|
export type Schema<TSource, T = any> = TSource extends object ?
|
|
3
6
|
Partial<{
|
|
@@ -12,9 +15,15 @@ export type Schema<TSource, T = any> = TSource extends object ?
|
|
|
12
15
|
// Else map T to effect.
|
|
13
16
|
: Effect<TSource, T>;
|
|
14
17
|
|
|
18
|
+
/**
|
|
19
|
+
* An effect defines how to project a value from source to target.
|
|
20
|
+
*/
|
|
15
21
|
// todo: Solve this `any`
|
|
16
22
|
export type Effect<TSource, TValue> = (target: any, ctx: IEffectContext<TSource, TValue>) => MaybePromise<void>;
|
|
17
23
|
|
|
24
|
+
/**
|
|
25
|
+
* The context for an effect. It contains information about changes.
|
|
26
|
+
*/
|
|
18
27
|
export interface IEffectContext<TSource, TValue> {
|
|
19
28
|
/**
|
|
20
29
|
* The source object.
|
|
@@ -32,9 +41,12 @@ export interface IEffectContext<TSource, TValue> {
|
|
|
32
41
|
value: TValue;
|
|
33
42
|
}
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Strategy defines actual execution methods for projecting values to target.
|
|
46
|
+
*/
|
|
47
|
+
export interface ITargetExecutionStrategy<TTarget, TLocation = any> {
|
|
48
|
+
execute<T>(target: TTarget, at: TLocation, value: T): MaybePromise<void>;
|
|
49
|
+
executeArray<T>(target: TTarget, at: TLocation, keys: Partial<keyof T>[], rows: T[]): MaybePromise<void>;
|
|
38
50
|
}
|
|
39
51
|
|
|
40
52
|
export interface IProjector<TSource> {
|