@cyysummer/projector 0.0.6 → 0.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @cyysummer/projector v0.0.6
2
+ * @cyysummer/projector v0.0.8
3
3
  * (c) 2021-PRESENT Chris Liu
4
4
  * @license MIT
5
5
  **/
6
- import m 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}create(t){return(e,r)=>{let c=a(r);return this._strategy.execute(e,t,c)}}createWith(t,e){return(c,o)=>{let s=a(o),n=e(s);return this._strategy.execute(c,t,n)}}forEach(t){return(e,r)=>{}}fromArray(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)}}}fromSource(t,e){return(r,c)=>{let o=e(c.source);return this._strategy.execute(r,t,o)}}fromValue(t,e){return(r,c)=>this._strategy.execute(r,t,e)}sequence(t){return async(e,r)=>{let c=a(r);for(let o of t)await o(e,{value:c})}}sequenceWith(t,e){return async(c,o)=>{let s=a(o),n=e(s);for(let h of t)await h(c,{value:n})}}when(t,e,r=l){return(c,o)=>{let s=a(o);return(t(s)?e:r)(c,{value:s})}}whenFromSource(t,e,r=l){return(c,o)=>(t(o.source)?e:r)(c,o)}};function a(u){return u.source&&u.path?d(u.source,u.path):u.value}var T=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 T{constructor(t,e){super(t),this._scheduler=e}},y=class extends T{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 f=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 f{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 R(u){let t=new i(u);return[m(u,t.receive.bind(t),{pathAsArray:!0}),t]}export{_ as BufferedScheduler,y as DynamicProjector,p as EffectFactory,S as Projector,T as ProjectorBase,i as Recorder,f as Scheduler,R as track};
6
+ import b from"on-change";import{set as m}from"lodash-es";import{withEvents as I}from"@cyysummer/core";var T=class extends I(){constructor(e){super();this._paused=!1;this._shadow=structuredClone(e)}receive(e,r){if(this._paused)return;m(this._shadow,e,r);let o=[{path:e,value:r}];this.emit("record",{next:this._shadow,patches:o}),this._ensureProjector(),this._projector?.project(this._shadow,...o)}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 l,keys as d}from"lodash-es";var y=s=>{},S=class{constructor(t){this._strategy=t}at(t){return(e,r)=>{let o=i(r);return this._strategy.execute(e,t,o)}}atWith(t,e){return(o,c)=>{let u=i(c),a=e(u);return this._strategy.execute(o,t,a)}}arrayAt(t,e){return(r,o)=>{let c=o.path?l(o.source,o.path):o.value;if(c&&Array.isArray(c)&&c.length>0){let u={keys:typeof c[0]=="object"?d(c[0]):[],resolveHeader:(a,n)=>String(a),...e};return this._strategy.executeArray(r,t,c,u)}}}arrayAtWith(t,e,r){return(o,c)=>{let u=c.path?l(c.source,c.path):c.value;if(u&&Array.isArray(u)&&u.length>0){let a=u.map(e),n={keys:typeof u[0]=="object"?d(u[0]):[],resolveHeader:(f,v)=>String(f),...r};return this._strategy.executeArray(o,t,a,n)}}}loop(t){return async(e,r)=>{let o=i(r);if(Array.isArray(o)){let c=o;for(let u=0;u<c.length;u++){let a=c[u],f=t(a,u)(e,{value:a});f instanceof Promise&&await f}}else throw new Error(`Effect: Value at path '${r.path}' is not an array.`)}}sourceWith(t,e){return(r,o)=>{let c=e(o.source);return this._strategy.execute(r,t,c)}}raw(t,e){return(r,o)=>this._strategy.execute(r,t,e)}sequence(t){return async(e,r)=>{let o=i(r);for(let c of t)await c(e,{value:o})}}sequenceWith(t,e){return async(o,c)=>{let u=i(c),a=e(u);for(let n of t)await n(o,{value:a})}}when(t,e,r=y){return(o,c)=>{let u=i(c);return(t(u)?e:r)(o,{value:u})}}whenFromSource(t,e,r=y){return(o,c)=>(t(c.source)?e:r)(o,c)}},i=s=>s.source&&s.path?l(s.source,s.path):s.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:o}=e,c=this._resolveEffect(r);c&&(this._ensureScheduler(),this._scheduler.enqueue({path:r.join("."),effect:c,ctx:{source:t,path:r,value:o}}))}_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}},_=class extends h{constructor(t,e){super(t),this._scheduler=e}},g=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 p=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")}},E=class extends p{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",[...this._queue.keys()]);let e=[...this._queue.values()];this._queue.clear();for(let r of e){let{effect:o,ctx:c}=r,u=o(this._target,c);u instanceof Promise&&await u}}};function k(s){let t=new T(s);return[b(s,t.receive.bind(t),{pathAsArray:!0}),t]}export{E as BufferedScheduler,g as DynamicProjector,S as EffectFactory,_ as Projector,h as ProjectorBase,T as Recorder,p as Scheduler,k as track};
7
7
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyysummer/projector",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "A powerful state projection library for creating anything.",
5
5
  "license": "MIT",
6
6
  "author": "Chris Liu",
package/types/lib.d.ts CHANGED
@@ -2,18 +2,16 @@
2
2
  * A Schema defines how to project changes from a source object to a target object.
3
3
  */
4
4
  // prettier-ignore
5
- type Schema<TSource, T = any> = TSource extends object ?
6
- Partial<{
7
- // If the property is an array, map whole array to effect.
8
- // Else map property to schema.
9
- [K in keyof T]:
10
- T[K] extends Array<infer U> ?
11
- Effect<TSource, U>
12
- // If TSource is an object, map each property to schema, or write effect for the property.
13
- : Schema<TSource, T[K]> | Effect<TSource, T[K]>;
14
- }>
15
- // Else map T to effect.
16
- : Effect<TSource, T>;
5
+ type Schema<TSource, T = TSource> = {
6
+ // If the property is an array, map to effect.
7
+ [K in keyof T]?: T[K] extends Array<infer U>
8
+ ? Effect<TSource, U[]>
9
+ // Else, if the property is an object, map to schema or effect.
10
+ : T[K] extends object
11
+ ? Schema<TSource, T[K]> | Effect<TSource, T[K]>
12
+ // Else, leaf property, map to effect.
13
+ : Effect<TSource, T[K]>;
14
+ };
17
15
 
18
16
  /**
19
17
  * An effect defines how to project a value from source to target.
@@ -41,12 +39,27 @@ interface IEffectContext<TSource, TValue> {
41
39
  value: TValue;
42
40
  }
43
41
 
42
+ /**
43
+ * Options for execute array effect.
44
+ */
45
+ type ArrayEffectOptions = {
46
+ /**
47
+ * The keys of the objects in the array. Use this only when element of array is object.
48
+ */
49
+ keys: (string | symbol)[];
50
+
51
+ /**
52
+ * Function to generate header for each column.
53
+ */
54
+ resolveHeader: (key: string | symbol, index?: number) => string;
55
+ }
56
+
44
57
  /**
45
58
  * Strategy defines actual execution methods for projecting values to target.
46
59
  */
47
60
  interface ITargetExecutionStrategy<TTarget, TLocation = any> {
48
- execute<T>(target: TTarget, location: TLocation, value: T): MaybePromise<void>;
49
- executeArray<T>(target: TTarget, location: TLocation, keys: Partial<keyof T>[], rows: T[]): MaybePromise<void>;
61
+ execute<T extends any>(target: TTarget, location: TLocation, value: T): MaybePromise<void>;
62
+ executeArray<T extends any>(target: TTarget, location: TLocation, rows: T[], options: ArrayEffectOptions): MaybePromise<void>;
50
63
  }
51
64
 
52
65
  interface IProjector<TSource> {
@@ -116,39 +129,52 @@ declare class EffectFactory<TTarget, TSource extends object, TLocation = any> {
116
129
  protected _strategy: ITargetExecutionStrategy<TTarget, TLocation>;
117
130
  constructor(_strategy: ITargetExecutionStrategy<TTarget, TLocation>);
118
131
  /**
119
- * Create an effect that will applied at the specified location.
132
+ * Create an effect that will be applied at the specified location.
133
+ * @param location The location in `TTarget` where the effect is executed.
134
+ * @returns
135
+ */
136
+ at<T>(location: TLocation): Effect<TSource, T>;
137
+ /**
138
+ * Create an effect that will be applied at the specified location. Use `mapper` to transform the value.
120
139
  * @param location The location in `TTarget` where the effect is executed.
140
+ * @param mapper Function to transform the value.
121
141
  * @returns
122
142
  */
123
- create<T>(location: TLocation): Effect<TSource, T>;
143
+ atWith<T, R>(location: TLocation, mapper: Func1<T, R>): Effect<TSource, R>;
124
144
  /**
125
- * Create an effect that will applied at the specified location. Use `mapper` to transform the source object.
145
+ * Create an effect that will be applied at the specified location for array data.
126
146
  * @param location The location in `TTarget` where the effect is executed.
127
- * @param mapper Function to transform the source object.
128
147
  * @returns
129
148
  */
130
- createWith<T, R>(location: TLocation, mapper: Func1<T, R>): Effect<TSource, R>;
131
- forEach<T extends Array<U>, U extends object = any>(location: Func1<number, TLocation>): Effect<TSource, any>;
149
+ arrayAt<T, U = UnwrapArray<T>>(location: TLocation, options?: Partial<ArrayEffectOptions>): Effect<TSource, T>;
132
150
  /**
133
- * Create an effect that will applied at the specified location for array data.
151
+ * Create an effect that will be applied at the specified location for array data.
134
152
  * @param location The location in `TTarget` where the effect is executed.
153
+ * @param mapper Function to transform the element of the array.
154
+ * @returns
155
+ */
156
+ arrayAtWith<T, U = UnwrapArray<T>, R = any>(location: TLocation, mapper: Func1<U, R>, options?: Partial<ArrayEffectOptions>): Effect<TSource, T>;
157
+ /**
158
+ *
159
+ * @param each
135
160
  * @returns
161
+ * @experimental
136
162
  */
137
- fromArray<T extends Array<U>, U extends object = any>(location: TLocation): Effect<TSource, T>;
163
+ loop<T, U = T extends Array<infer K> ? K : never>(each: Func2<U, number, Effect<TSource, U>>): Effect<TSource, T>;
138
164
  /**
139
- * Create an effect that will applied at the specified location. Use `mapper` to transform the source object.
165
+ * Create an effect that will be applied at the specified location for `TSource` object. Use `mapper` to transform the `TSource` object.
140
166
  * @param location The location in `TTarget` where the effect is executed.
141
- * @param mapper Function to transform the source object.
167
+ * @param mapper Function to transform the `TSource` object.
142
168
  * @returns
143
169
  */
144
- fromSource<T>(location: TLocation, mapper: Func1<TSource, string>): Effect<TSource, T>;
170
+ sourceWith<T>(location: TLocation, mapper: Func1<TSource, string>): Effect<TSource, T>;
145
171
  /**
146
- * Create an effect that will applied at the specified location for raw value. This effect will not read from source object.
172
+ * Create an effect that will be applied at the specified location for raw value. This effect will not read from `TSource` object.
147
173
  * @param location The location in `TTarget` where the effect is executed.
148
- * @param value The value to use.
174
+ * @param rawValue The value to use.
149
175
  * @returns
150
176
  */
151
- fromValue<T>(location: TLocation, value: T): Effect<TSource, T>;
177
+ raw<T>(location: TLocation, rawValue: T): Effect<TSource, T>;
152
178
  /**
153
179
  * Call multiple effects in sequence.
154
180
  * @param effects Effects to call.
@@ -156,23 +182,23 @@ declare class EffectFactory<TTarget, TSource extends object, TLocation = any> {
156
182
  */
157
183
  sequence<T>(effects: Effect<TSource, T>[]): Effect<TSource, T>;
158
184
  /**
159
- * Call multiple effects in sequence. Use `mapper` to transform the original value.
185
+ * Call multiple effects in sequence. Use `mapper` to transform the value.
160
186
  * @param effects Effects to call.
161
- * @param mapper Function to transform the original value.
187
+ * @param mapper Function to transform the value.
162
188
  * @returns
163
189
  */
164
190
  sequenceWith<T, R>(effects: Effect<TSource, R>[], mapper: Func1<T, R>): Effect<TSource, R>;
165
191
  /**
166
192
  * Execute effect based on condition. The condition is based on the value of the current property path.
167
- * @param condition Condition delegate that takes the original value of the property and returns true or false.
193
+ * @param condition Condition delegate that takes the value of the property and returns true or false.
168
194
  * @param ifTrue When condition is true, this effect is executed.
169
195
  * @param ifFalse When condition is false, this effect is executed.
170
196
  * @returns
171
197
  */
172
198
  when<T>(condition: Predicate<T>, ifTrue: Effect<TSource, any>, ifFalse?: Effect<TSource, any>): Effect<TSource, T>;
173
199
  /**
174
- * Execute effect based on condition. The condition is based on the source object.
175
- * @param condition Condition delegate that takes the source object and returns true or false.
200
+ * Execute effect based on condition. The condition is based on the `TSource` object.
201
+ * @param condition Condition delegate that takes the `TSource` object and returns true or false.
176
202
  * @param ifTrue When condition is true, this effect is executed.
177
203
  * @param ifFalse When condition is false, this effect is executed.
178
204
  * @returns
package/types/types.d.ts CHANGED
@@ -2,18 +2,16 @@
2
2
  * A Schema defines how to project changes from a source object to a target object.
3
3
  */
4
4
  // prettier-ignore
5
- export type Schema<TSource, T = any> = TSource extends object ?
6
- Partial<{
7
- // If the property is an array, map whole array to effect.
8
- // Else map property to schema.
9
- [K in keyof T]:
10
- T[K] extends Array<infer U> ?
11
- Effect<TSource, U>
12
- // If TSource is an object, map each property to schema, or write effect for the property.
13
- : Schema<TSource, T[K]> | Effect<TSource, T[K]>;
14
- }>
15
- // Else map T to effect.
16
- : Effect<TSource, T>;
5
+ export type Schema<TSource, T = TSource> = {
6
+ // If the property is an array, map to effect.
7
+ [K in keyof T]?: T[K] extends Array<infer U>
8
+ ? Effect<TSource, U[]>
9
+ // Else, if the property is an object, map to schema or effect.
10
+ : T[K] extends object
11
+ ? Schema<TSource, T[K]> | Effect<TSource, T[K]>
12
+ // Else, leaf property, map to effect.
13
+ : Effect<TSource, T[K]>;
14
+ };
17
15
 
18
16
  /**
19
17
  * An effect defines how to project a value from source to target.
@@ -41,12 +39,27 @@ export interface IEffectContext<TSource, TValue> {
41
39
  value: TValue;
42
40
  }
43
41
 
42
+ /**
43
+ * Options for execute array effect.
44
+ */
45
+ export type ArrayEffectOptions = {
46
+ /**
47
+ * The keys of the objects in the array. Use this only when element of array is object.
48
+ */
49
+ keys: (string | symbol)[];
50
+
51
+ /**
52
+ * Function to generate header for each column.
53
+ */
54
+ resolveHeader: (key: string | symbol, index?: number) => string;
55
+ }
56
+
44
57
  /**
45
58
  * Strategy defines actual execution methods for projecting values to target.
46
59
  */
47
60
  export interface ITargetExecutionStrategy<TTarget, TLocation = any> {
48
- execute<T>(target: TTarget, location: TLocation, value: T): MaybePromise<void>;
49
- executeArray<T>(target: TTarget, location: TLocation, keys: Partial<keyof T>[], rows: T[]): MaybePromise<void>;
61
+ execute<T extends any>(target: TTarget, location: TLocation, value: T): MaybePromise<void>;
62
+ executeArray<T extends any>(target: TTarget, location: TLocation, rows: T[], options: ArrayEffectOptions): MaybePromise<void>;
50
63
  }
51
64
 
52
65
  export interface IProjector<TSource> {