@cyysummer/projector 0.0.9 → 0.0.10

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.9
2
+ * @cyysummer/projector v0.0.10
3
3
  * (c) 2021-PRESENT Chris Liu
4
4
  * @license MIT
5
5
  **/
6
- import w from"on-change";import{cloneDeep as m,set as x}from"lodash-es";import{withEvents as v}from"@cyysummer/core";var f=class extends v(){constructor(t){super();this._paused=!1;this._shadow=m(t)}receive(t,r){if(this._paused)return;x(this._shadow,t,r);let o=[{path:t,value:r}];this.emit("record",{next:this._shadow,patches:o}),this._ensureProjector(),this._projector?.project(this._shadow,...o)}sendTo(t){typeof t=="function"?this._projectorFactory=t:this._projector=t}pause(){this._paused=!0}resume(){this._paused=!1}_ensureProjector(){!this._projector&&this._projectorFactory&&(this._projector=this._projectorFactory())}};import{get as p,keys as l}from"lodash-es";var S=n=>{},d=class{at(e){return(t,r)=>{let o=i(r);return t.execute(e,o)}}atWith(e,t){return(o,c)=>{let a=i(c),u=t(a);return o.execute(e,u)}}arrayAt(e,t){return(r,o)=>{let c=o.path?p(o.source,o.path):o.value;if(c&&Array.isArray(c)&&c.length>0){let a={keys:typeof c[0]=="object"?l(c[0]):[],resolveHeader:(u,s)=>String(u),...t};return r.executeArray(e,c,a)}}}arrayAtWith(e,t,r){return(o,c)=>{let a=c.path?p(c.source,c.path):c.value;if(a&&Array.isArray(a)&&a.length>0){let u=a.map(t),s={keys:typeof a[0]=="object"?l(a[0]):[],resolveHeader:(T,j)=>String(T),...r};return o.executeArray(e,u,s)}}}loop(e){return async(t,r)=>{let o=i(r);if(Array.isArray(o)){let c=o;for(let a=0;a<c.length;a++){let u=c[a],T=e(u,a)(t,{value:u});T instanceof Promise&&await T}}else throw new Error(`Effect: Value at path '${r.path}' is not an array.`)}}sourceWith(e,t){return(r,o)=>{let c=t(o.source);return r.execute(e,c)}}raw(e,t){return(r,o)=>r.execute(e,t)}sequence(e){return async(t,r)=>{let o=i(r);for(let c of e)await c(t,{value:o})}}sequenceWith(e,t){return async(o,c)=>{let a=i(c),u=t(a);for(let s of e)await s(o,{value:u})}}when(e,t,r=S){return(o,c)=>{let a=i(c);return(e(a)?t:r)(o,{value:a})}}whenFromSource(e,t,r=S){return(o,c)=>(e(c.source)?t:r)(o,c)}},i=n=>n.source&&n.path?p(n.source,n.path):n.value;var h=class{constructor(e){this._schema=e;if(!e)throw new Error("Projector: Schema is required.")}project(e,...t){for(let r of t)this._dispatch(e,r)}_dispatch(e,t){let{path:r,value:o}=t,c=this._resolveEffect(r);c&&(this._ensureScheduler(),this._scheduler.enqueue({path:r.join("."),effect:c,ctx:{source:e,path:r,value:o}}))}_ensureScheduler(){if(!this._scheduler)throw new Error("Projector: no scheduler.")}_resolveEffect(e){let t=this._schema;for(let r of e){if(!t)return null;t=t[r]}return typeof t=="function"?t:null}},g=class extends h{constructor(e,t){super(e),this._scheduler=t}},E=class extends h{scheduleWith(e){return typeof e=="function"?this._schedulerFactory=e:this._scheduler=e,this}_ensureScheduler(){if(!this._scheduler&&this._schedulerFactory&&(this._scheduler=this._schedulerFactory()),!this._scheduler)throw new Error("Projector: no scheduler.")}};import{debounce as b}from"lodash-es";var y=class{constructor(e){this._strategy=e;this._queue=new Map}enqueue(e){return this._queue.set(e.path,e),this}flush(){return this.checkStrategy(),log.trace("Scheduler.flush()",[...this._queue.keys()]),this.flushCore()}withStrategy(e){return typeof e=="function"?this._strategyFactory=e:this._strategy=e,this}checkStrategy(){if(!this._strategy&&this._strategyFactory&&(this._strategy=this._strategyFactory()),!this._strategy)throw new Error("Scheduler: target is not set")}async run(e){for(let t of e){let{effect:r,ctx:o}=t,c=r(this._strategy,o);c instanceof Promise&&await c}}},I=class extends y{constructor(t,r=500){super(t);this.timeout=r;this.flushCore=b(async()=>{let t=[...this._queue.values()];this._queue.clear(),this.run(t)},this.timeout)}},_=class extends y{async flushCore(){this._strategy.reset(),this.run([...this._queue.values()])}};function O(n){let e=new f(n);return[w(n,(r,o)=>e.receive(r,o),{pathAsArray:!0}),e]}export{E as DynamicProjector,d as EffectFactory,I as LazyScheduler,g as Projector,h as ProjectorBase,f as Recorder,y as Scheduler,_ as TotalScheduler,O as track};
6
+ import L from"on-change";import{cloneDeep as x,set as w}from"lodash-es";import{withEvents as v}from"@cyysummer/core";var i=class extends v(){constructor(t){super();this._paused=!1;this._shadow=x(t)}receive(t,r){if(this._paused)return;w(this._shadow,t,r);let o=[{path:t,value:r}];this.emit("record",{next:this._shadow,patches:o}),this._ensureProjector(),this._projector?.project(this._shadow,...o)}sendTo(t){typeof t=="function"?this._projectorFactory=t:this._projector=t}pause(){this._paused=!0}resume(){this._paused=!1}_ensureProjector(){!this._projector&&this._projectorFactory&&(this._projector=this._projectorFactory())}};import F from"on-change";var l=class{constructor(e,t){this._schema=e;this._scheduler=t;if(!e)throw new Error("Projector: Schema is required.")}project(e,...t){for(let r of t)this._dispatch(e,r)}_dispatch(e,t){let{path:r,value:o}=t,c=this._resolveEffect(r);c&&(this._ensureScheduler(),this._scheduler.enqueue({path:r.join("."),effect:c,ctx:{source:e,path:r,value:o}}))}_ensureScheduler(){if(!this._scheduler)throw new Error("Projector: no scheduler.")}_resolveEffect(e){let t=this._schema;for(let r of e){if(!t)return null;t=t[r]}return typeof t=="function"?t:null}},f=class extends l{constructor(e,t){super(e,t)}},y=class extends l{withScheduler(e){return typeof e=="function"?this._schedulerFactory=e:this._scheduler=e,this}_ensureScheduler(){if(!this._scheduler&&this._schedulerFactory&&(this._scheduler=this._schedulerFactory()),!this._scheduler)throw new Error("Projector: no scheduler.")}};import{debounce as b}from"lodash-es";var d=class{constructor(e){this._strategy=e;this._queue=new Map}enqueue(e){return this._queue.set(e.path,e),this}flush(){return this.checkStrategy(),log.trace("Scheduler.flush()",[...this._queue.keys()]),this.flushCore()}withStrategy(e){return typeof e=="function"?this._strategyFactory=e:this._strategy=e,this}checkStrategy(){if(!this._strategy&&this._strategyFactory&&(this._strategy=this._strategyFactory()),!this._strategy)throw new Error("Scheduler: no strategy.")}async run(e){for(let t of e){let{effect:r,ctx:o}=t,c=r(this._strategy,o);c instanceof Promise&&await c}}},p=class extends d{constructor(t,r=500){super(t);this.wait=r;this.flushCore=b(async()=>{let t=[...this._queue.values()];this._queue.clear(),this.run(t)},this.wait)}},S=class extends d{async flushCore(){this._strategy.reset(),this.run([...this._queue.values()])}};import{debounce as j}from"lodash-es";var _=class{constructor(e,t){this._initial=e;this._schema=t;this._flushWait=0}buildDynamic(){this.track();let e=new y(this._schema);return this._scheduler&&e.withScheduler(this._scheduler),this._recorder.sendTo(e),{tracked:this._tracked,recorder:this._recorder,projector:e,scheduler:this._scheduler}}buildStatic(){if(!this._scheduler)throw new Error("Builder: no scheduler was provided. Call `withLazyScheduler()` or `withTotalScheduler()` to provide.");if(!this._strategy&&!this._strategyFactory)throw new Error("Builder: no strategy was provided. Call `withStrategy()` to provide.");if(!this._onFlush)throw new Error("Builder: no flush handler was provided. Call `onFlush()` to provide.");let e=async()=>{await this._scheduler.flush(),this._onFlush()};this.track(),this._scheduler.withStrategy(this._strategy??this._strategyFactory);let t=new f(this._schema,this._scheduler);return this._recorder.sendTo(t),this._recorder.on("record",this._flushWait?j(e,this._flushWait):e),{tracked:this._tracked,recorder:this._recorder,scheduler:this._scheduler}}onFlush(e,t=500){return this._onFlush=e,this._flushWait=t,this}withLazyScheduler(e=500){return this._scheduler=new p(void 0,e),this}withTotalScheduler(){return this._scheduler=new S,this}withStrategy(e){return typeof e=="function"?this._strategyFactory=e:this._strategy=e,this}track(){this._recorder&&this._tracked||(this._recorder=new i(this._initial),this._tracked=F(this._initial,(e,t)=>this._recorder.receive(e,t),{pathAsArray:!0}))}};import{get as g,keys as E}from"lodash-es";var m=u=>{},I=class{at(e){return(t,r)=>{let o=h(r);return t.execute(e,o)}}atWith(e,t){return(o,c)=>{let a=h(c),s=t(a);return o.execute(e,s)}}arrayAt(e,t){return(r,o)=>{let c=o.path?g(o.source,o.path):o.value;if(c&&Array.isArray(c)&&c.length>0){let a={keys:typeof c[0]=="object"?E(c[0]):[],resolveHeader:(s,n)=>String(s),...t};return r.executeArray(e,c,a)}}}arrayAtWith(e,t,r){return(o,c)=>{let a=c.path?g(c.source,c.path):c.value;if(a&&Array.isArray(a)&&a.length>0){let s=a.map(t),n={keys:typeof a[0]=="object"?E(a[0]):[],resolveHeader:(T,P)=>String(T),...r};return o.executeArray(e,s,n)}}}loop(e){return async(t,r)=>{let o=h(r);if(Array.isArray(o)){let c=o;for(let a=0;a<c.length;a++){let s=c[a],T=e(s,a)(t,{value:s});T instanceof Promise&&await T}}else throw new Error(`Effect: Value at path '${r.path}' is not an array.`)}}sourceWith(e,t){return(r,o)=>{let c=t(o.source);return r.execute(e,c)}}raw(e,t){return(r,o)=>r.execute(e,t)}sequence(e){return async(t,r)=>{let o=h(r);for(let c of e)await c(t,{value:o})}}sequenceWith(e,t){return async(o,c)=>{let a=h(c),s=t(a);for(let n of e)await n(o,{value:s})}}when(e,t,r=m){return(o,c)=>{let a=h(c);return(e(a)?t:r)(o,{value:a})}}whenFromSource(e,t,r=m){return(o,c)=>(e(c.source)?t:r)(o,c)}},h=u=>u.source&&u.path?g(u.source,u.path):u.value;function G(u){let e=new i(u);return[L(u,(r,o)=>e.receive(r,o),{pathAsArray:!0}),e]}export{_ as Builder,y as DynamicProjector,I as EffectFactory,p as LazyScheduler,f as Projector,l as ProjectorBase,i as Recorder,d as Scheduler,S as TotalScheduler,G 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.9",
3
+ "version": "0.0.10",
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
@@ -59,7 +59,7 @@ type ArrayEffectOptions = {
59
59
  /**
60
60
  * Strategy defines actual execution methods for projecting values to target.
61
61
  */
62
- interface ITargetExecutionStrategy<TTarget, TLocation = any> {
62
+ interface ITargetExecutionStrategy<TTarget, TLocation> {
63
63
  execute<T extends any>(location: TLocation, value: T): MaybePromise<void>;
64
64
  executeArray<T extends any>(location: TLocation, rows: T[], options: ArrayEffectOptions): MaybePromise<void>;
65
65
  reset(): void;
@@ -72,8 +72,8 @@ interface IProjector<TSource> {
72
72
  interface IScheduler<TTarget> {
73
73
  enqueue(effect: IScheduleItem): void;
74
74
  flush(): MaybePromise<void>;
75
- withStrategy(target: ITargetExecutionStrategy<TTarget, unknown>): IScheduler<TTarget>;
76
- withStrategy(target: Func<ITargetExecutionStrategy<TTarget, unknown>>): IScheduler<TTarget>;
75
+ withStrategy(strategy: ITargetExecutionStrategy<TTarget, any>): IScheduler<TTarget>;
76
+ withStrategy(factory: Func<ITargetExecutionStrategy<TTarget, any>>): IScheduler<TTarget>;
77
77
  }
78
78
 
79
79
  interface IScheduleItem<TSource, TValue> {
@@ -125,6 +125,55 @@ declare class Recorder<TSource extends object> extends Recorder_base {
125
125
  private _ensureProjector;
126
126
  }
127
127
 
128
+ declare abstract class ProjectorBase<TSource> implements IProjector<TSource> {
129
+ protected _schema: Schema<TSource>;
130
+ protected _scheduler?: IScheduler<any> | undefined;
131
+ constructor(_schema: Schema<TSource>, _scheduler?: IScheduler<any> | undefined);
132
+ project(next: TSource, ...patches: Patch[]): void;
133
+ protected _dispatch(next: TSource, patch: Patch): void;
134
+ protected _ensureScheduler(): void;
135
+ protected _resolveEffect(path: (string | symbol)[]): Effect<TSource, any> | null;
136
+ }
137
+ declare class Projector<TSource> extends ProjectorBase<TSource> {
138
+ constructor(_schema: Schema<TSource>, _scheduler: IScheduler<any>);
139
+ }
140
+ declare class DynamicProjector<TSource> extends ProjectorBase<TSource> {
141
+ private _schedulerFactory?;
142
+ withScheduler(scheduler: IScheduler<any>): IProjector<TSource>;
143
+ withScheduler(factory: Func<IScheduler<any>>): IProjector<TSource>;
144
+ protected _ensureScheduler(): void;
145
+ }
146
+
147
+ declare class Builder<TSource extends object, TTarget, TLocation> {
148
+ private _initial;
149
+ private _schema;
150
+ private _flushWait;
151
+ private _onFlush?;
152
+ private _recorder?;
153
+ private _scheduler?;
154
+ private _strategy?;
155
+ private _strategyFactory?;
156
+ private _tracked?;
157
+ constructor(_initial: TSource, _schema: Schema<TSource>);
158
+ buildDynamic(): {
159
+ tracked: TSource;
160
+ recorder: Recorder<TSource>;
161
+ projector: DynamicProjector<TSource>;
162
+ scheduler: IScheduler<TTarget> | undefined;
163
+ };
164
+ buildStatic(): {
165
+ tracked: TSource;
166
+ recorder: Recorder<TSource>;
167
+ scheduler: IScheduler<TTarget>;
168
+ };
169
+ onFlush(callback: Action, wait?: number): Builder<TSource, TTarget, TLocation>;
170
+ withLazyScheduler(wait?: number): Builder<TSource, TTarget, TLocation>;
171
+ withTotalScheduler(): Builder<TSource, TTarget, TLocation>;
172
+ withStrategy(strategy: ITargetExecutionStrategy<TTarget, TLocation>): Builder<TSource, TTarget, TLocation>;
173
+ withStrategy(factory: Func<ITargetExecutionStrategy<TTarget, TLocation>>): Builder<TSource, TTarget, TLocation>;
174
+ private track;
175
+ }
176
+
128
177
  /**
129
178
  * Build effects for a target.
130
179
  * @template TSource The type of the source object.
@@ -209,25 +258,6 @@ declare class EffectFactory<TSource extends object, TLocation = any> {
209
258
  whenFromSource<T>(condition: Predicate<TSource>, ifTrue: Effect<TSource, any>, ifFalse?: Effect<TSource, any>): Effect<TSource, T>;
210
259
  }
211
260
 
212
- declare abstract class ProjectorBase<TSource> implements IProjector<TSource> {
213
- protected _schema: Schema<TSource>;
214
- protected _scheduler?: IScheduler<any>;
215
- constructor(_schema: Schema<TSource>);
216
- project(next: TSource, ...patches: Patch[]): void;
217
- protected _dispatch(next: TSource, patch: Patch): void;
218
- protected _ensureScheduler(): void;
219
- protected _resolveEffect(path: (string | symbol)[]): Effect<TSource, any> | null;
220
- }
221
- declare class Projector<TSource> extends ProjectorBase<TSource> {
222
- constructor(_schema: Schema<TSource>, _scheduler: IScheduler<any>);
223
- }
224
- declare class DynamicProjector<TSource> extends ProjectorBase<TSource> {
225
- private _schedulerFactory?;
226
- scheduleWith(scheduler: IScheduler<any>): IProjector<TSource>;
227
- scheduleWith(schedulerFactory: Func<IScheduler<any>>): IProjector<TSource>;
228
- protected _ensureScheduler(): void;
229
- }
230
-
231
261
  /**
232
262
  * Scheduler abstract class, used to schedule projector effects.
233
263
  */
@@ -239,7 +269,7 @@ declare abstract class Scheduler<TTarget> implements IScheduler<TTarget> {
239
269
  enqueue(item: IScheduleItem<any, any>): IScheduler<TTarget>;
240
270
  flush(): MaybePromise<void>;
241
271
  withStrategy(strategy: ITargetExecutionStrategy<TTarget, any>): IScheduler<TTarget>;
242
- withStrategy(strategy: Func<ITargetExecutionStrategy<TTarget, any>>): IScheduler<TTarget>;
272
+ withStrategy(factory: Func<ITargetExecutionStrategy<TTarget, any>>): IScheduler<TTarget>;
243
273
  protected checkStrategy(): void;
244
274
  protected abstract flushCore(): MaybePromise<void>;
245
275
  protected run(list: IScheduleItem<any, any>[]): Promise<void>;
@@ -247,7 +277,7 @@ declare abstract class Scheduler<TTarget> implements IScheduler<TTarget> {
247
277
  /**
248
278
  * A scheduler that **delays and batches** effect executions using debounce.
249
279
  *
250
- * Effects are collected in a queue and only executed after the specified `timeout`
280
+ * Effects are collected in a queue and only executed after the specified `wait`
251
281
  * has passed without any new effects being enqueued. This helps reduce redundant
252
282
  * executions (e.g. during rapid successive state updates) and is especially useful
253
283
  * when projecting to expensive targets like UI rendering, DOM updates, or network requests.
@@ -257,8 +287,8 @@ declare abstract class Scheduler<TTarget> implements IScheduler<TTarget> {
257
287
  * effects in batch.
258
288
  */
259
289
  declare class LazyScheduler<TTarget> extends Scheduler<TTarget> {
260
- protected timeout: number;
261
- constructor(strategy?: ITargetExecutionStrategy<TTarget, any>, timeout?: number);
290
+ protected wait: number;
291
+ constructor(strategy?: ITargetExecutionStrategy<TTarget, any>, wait?: number);
262
292
  protected readonly flushCore: lodash_es.DebouncedFunc<() => Promise<void>>;
263
293
  }
264
294
  /**
@@ -275,4 +305,4 @@ declare class TotalScheduler<TTarget> extends Scheduler<TTarget> {
275
305
  */
276
306
  declare function track<TSource extends object>(initial: TSource): [TSource, Recorder<TSource>];
277
307
 
278
- export { DynamicProjector, EffectFactory, LazyScheduler, Projector, ProjectorBase, Recorder, Scheduler, TotalScheduler, track };
308
+ export { Builder, DynamicProjector, EffectFactory, LazyScheduler, Projector, ProjectorBase, Recorder, Scheduler, TotalScheduler, track };
package/types/types.d.ts CHANGED
@@ -57,7 +57,7 @@ export type ArrayEffectOptions = {
57
57
  /**
58
58
  * Strategy defines actual execution methods for projecting values to target.
59
59
  */
60
- export interface ITargetExecutionStrategy<TTarget, TLocation = any> {
60
+ export interface ITargetExecutionStrategy<TTarget, TLocation> {
61
61
  execute<T extends any>(location: TLocation, value: T): MaybePromise<void>;
62
62
  executeArray<T extends any>(location: TLocation, rows: T[], options: ArrayEffectOptions): MaybePromise<void>;
63
63
  reset(): void;
@@ -70,8 +70,8 @@ export interface IProjector<TSource> {
70
70
  export interface IScheduler<TTarget> {
71
71
  enqueue(effect: IScheduleItem): void;
72
72
  flush(): MaybePromise<void>;
73
- withStrategy(target: ITargetExecutionStrategy<TTarget, unknown>): IScheduler<TTarget>;
74
- withStrategy(target: Func<ITargetExecutionStrategy<TTarget, unknown>>): IScheduler<TTarget>;
73
+ withStrategy(strategy: ITargetExecutionStrategy<TTarget, any>): IScheduler<TTarget>;
74
+ withStrategy(factory: Func<ITargetExecutionStrategy<TTarget, any>>): IScheduler<TTarget>;
75
75
  }
76
76
 
77
77
  export interface IScheduleItem<TSource, TValue> {