@vue-modeler/model 2.1.1-beta.1 → 2.2.0-beta.2

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.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var m=Object.defineProperty;var A=(r,t,e)=>t in r?m(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var n=(r,t,e)=>A(r,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("vue");class w extends Error{constructor(t,e){super(e.cause.message),this.actionName=t,this.options=e,this.name=this.constructor.name}get cause(){return this.options.cause}throwCause(){throw this.cause}toString(){return this.options.cause.message}}class u extends Error{constructor(t,e){super(t,e),this.message=t,this.options=e,this.name=this.constructor.name}}class p extends u{constructor(t,e,o){super(`Trying to update state of ${t} from ${e} to ${o}`),this.name=this.constructor.name}}class g extends u{constructor(t,e){super(`Unexpected AbortError for the action ${t} in state ${e}`),this.name=this.constructor.name}}const y=r=>r instanceof DOMException&&r.name==="AbortError"||typeof r=="object"&&r!==null&&"message"in r&&r.message==="canceled",s=class s{constructor(t,e){n(this,"name");n(this,"_state",s.possibleState.ready);n(this,"_value",null);n(this,"_args",null);this.model=t,this.actionFunction=e;const o=e.name;if(!(o in t&&typeof t[o]=="function"))throw new u(`Model does not contain method ${o}`);if(typeof e[s.actionFlag]!="function")throw new u(`Method ${o} is not action`);this.name=o}toString(){return this.name}get possibleStates(){return Object.values(s.possibleState)}get state(){return this._state}set state(t){this._state=t,this.model.setActionState(this)}get abortController(){return this.isPending?this._value.abortController:null}get args(){return this._args||[]}get promise(){return this.isPending?this._value.promise:null}get error(){return this.isError?this._value:null}get abortReason(){return this.isAbort?this._value.abortController.signal.reason:null}get isPending(){return this.state===s.possibleState.pending}get isError(){return this.state===s.possibleState.error}get isReady(){return this.state===s.possibleState.ready}get isLock(){return this.state===s.possibleState.lock}get isAbort(){return this.state===s.possibleState.abort}is(...t){return!!t.find(e=>this.state===e)}exec(...t){if(this.is(s.possibleState.lock,s.possibleState.pending))throw new p(this.name,this.state,s.possibleState.pending);const e=[...t];let o=t.length&&t[t.length-1];o instanceof AbortController||(o=new AbortController,e.push(o)),this.state=s.possibleState.pending,this._args=t;const i=this.actionFunction[s.actionFlag].apply(this.model,e);if(!(i instanceof Promise))return this.state=s.possibleState.ready,Promise.resolve();const d=i.then(()=>{this.ready()}).catch(a=>{if(a instanceof u||a instanceof RangeError||a instanceof ReferenceError||a instanceof SyntaxError||a instanceof TypeError||a instanceof URIError||a instanceof EvalError)throw a;const S=y(a);if(S&&!this.is(s.possibleState.pending,s.possibleState.lock))throw new g(this.name,this.state);if(S&&this._value.abortController instanceof AbortController&&this._value.abortController.signal.reason===s.abortedByLock){this.state=s.possibleState.lock,this._value=null;return}if(S){this.state=s.possibleState.abort;return}this.setError(new w(this.name,{cause:a}))});return this._value={promise:d,abortController:o},d}abort(t){return this.isPending?(this._value.abortController.abort(t),this._value.promise):Promise.resolve()}lock(){return this.isPending?this.abort(s.abortedByLock):(this.state=s.possibleState.lock,this._value=null,Promise.resolve())}unlock(){if(!this.isLock)throw new p(this.name,this.state,s.possibleState.ready);return this.ready()}setError(t){if(!this.isPending)throw new p(this.name,this.state,s.possibleState.error);return this.state=s.possibleState.error,this._value=t,this}ready(){return this.state=s.possibleState.ready,this}resetError(){if(!this.error)throw new p(this.name,this.state,s.possibleState.ready);return this.ready()}};n(s,"actionFlag",Symbol("__action_original_method__")),n(s,"possibleState",{pending:"pending",error:"error",lock:"lock",ready:"ready",abort:"abort"}),n(s,"abortedByLock",Symbol("lock"));let c=s;const v=Proxy;function E(r){if(!(r instanceof b))throw new Error("ProtoModel instance is required");return new v(l.shallowReactive(r),{get(e,o,h){const i=Reflect.get(e,o,h),d=typeof i=="function";return d&&c.actionFlag in i&&typeof i[c.actionFlag]=="function"?e.action(i):d?i.bind(e):i}})}const f=class f{constructor(){n(this,"_effectScope",l.effectScope(!0));n(this,"_actions",new WeakMap);n(this,"_actionIds",new WeakMap);n(this,"_actionStates",new Map);n(this,"_actionsSize",0);n(this,"_watchStopHandlers",new Set)}static model(...t){if(this.prototype===f.prototype)throw new Error("ProtoModel is abstract class and can not be instantiated");const e=new this(...t);return f.createModel(e)}get hasPendingActions(){return!!this.getActionStatesRef(c.possibleState.pending).value}get hasActionWithError(){return!!this.getActionStatesRef(c.possibleState.error).value}watch(...t){if(t.length===0)throw new Error("watch requires at least one argument");const e=t.length===1?this._effectScope.run(()=>l.watchEffect(t[0])):this._effectScope.run(()=>l.watch(...t));if(!e)throw new Error("watchStopHandler is undefined");return this._watchStopHandlers.add(e),()=>{e(),this._watchStopHandlers.delete(e)}}computed(t,e){return this._effectScope.run(()=>l.computed(t,e))}updateBit(t,e,o){const h=o?1:0,i=~(1<<e);return t&i|h<<e}createAction(t){const e=l.shallowReactive(new c(this,t));return this._actions.set(t,e),this._actionIds.set(e,++this._actionsSize),this.setActionState(e),e}getActionStatesRef(t){const e=this._actionStates.get(t)||l.ref(0);return this._actionStates.get(t)===void 0&&this._actionStates.set(t,e),e}action(t){if(!(c.actionFlag in t&&typeof t[c.actionFlag]=="function"))throw new u("Action decorator is not applied to the method");return this._actions.get(t)||this.createAction(t)}setActionState(t){const e=this._actionIds.get(t);if(!e)throw new Error("Action not found");for(const o of t.possibleStates)o!==t.state&&(this.getActionStatesRef(o).value=this.updateBit(this.getActionStatesRef(o).value,e,!1));this.getActionStatesRef(t.state).value=this.updateBit(this.getActionStatesRef(t.state).value,e,!0)}isModelOf(t){return this instanceof t}destructor(){this._watchStopHandlers.forEach(t=>{t()}),this._watchStopHandlers=new Set,this._effectScope.stop()}};n(f,"createModel",E);let b=f;function k(r,t){if(t.static)throw new Error("Action decorator is not supported for static methods");if(t.private)throw new Error("Action decorator is not supported for private methods");const e=t.name.toString(),o={[e]:function(...h){return this.action(o[e]).exec(...h)}};return o[e][c.actionFlag]=r,o[e]}exports.ActionError=w;exports.ActionInternalError=u;exports.ActionStatusConflictError=p;exports.ActionUnexpectedAbortError=g;exports.ProtoModel=b;exports.action=k;
1
+ "use strict";var L=Object.defineProperty;var $=(r,t,e)=>t in r?L(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var i=(r,t,e)=>$(r,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("vue");class I extends Error{constructor(t,e){super(e.cause.message),this.actionName=t,this.options=e,this.name=this.constructor.name}get cause(){return this.options.cause}throwCause(){throw this.cause}toString(){return this.options.cause.message}}class u extends Error{constructor(t,e){super(t,e),this.message=t,this.options=e,this.name=this.constructor.name}}class b extends u{constructor(t,e,o){super(`Trying to update state of ${t} from ${e} to ${o}`),this.name=this.constructor.name}}class K extends u{constructor(t,e){super(`Unexpected AbortError for the action ${t} in state ${e}`),this.name=this.constructor.name}}const B=r=>r instanceof DOMException&&r.name==="AbortError"||typeof r=="object"&&r!==null&&"message"in r&&r.message==="canceled",s=class s{constructor(t,e,o,c){i(this,"name");i(this,"_state",s.possibleState.ready);i(this,"_value",null);i(this,"_args",null);this._model=t,this.actionFunction=e,this.ownerGetter=o,this.setStateCb=c;const n=e.name;if(!(n in this._model&&typeof this._model[n]=="function"))throw new u(`Model does not contain method ${n}`);if(typeof e[s.actionFlag]!="function")throw new u(`Method ${n} is not action`);this.name=n}static create(t,e,o,c){return l.shallowReactive(new s(t,e,o,c))}toString(){return this.name}get owner(){return this.ownerGetter()}get possibleStates(){return Object.values(s.possibleState)}get state(){return this._state}set state(t){const e=this._state;this._state=t,this.setStateCb&&this.setStateCb(this,e,t)}get abortController(){return this.isPending?this._value.abortController:null}get args(){return this._args||[]}get promise(){return this.isPending?this._value.promise:null}get error(){return this.isError?this._value:null}get abortReason(){return this.isAbort?this._value.abortController.signal.reason:null}get isPending(){return this.state===s.possibleState.pending}get isError(){return this.state===s.possibleState.error}get isReady(){return this.state===s.possibleState.ready}get isLock(){return this.state===s.possibleState.lock}get isAbort(){return this.state===s.possibleState.abort}is(...t){return!!t.find(e=>this.state===e)}exec(...t){if(this.is(s.possibleState.lock,s.possibleState.pending))throw new b(this.name,this.state,s.possibleState.pending);const e=[...t];let o=t.length&&t[t.length-1];o instanceof AbortController||(o=new AbortController,e.push(o)),this.state=s.possibleState.pending,this._args=t;const n=this.actionFunction[s.actionFlag].apply(this._model,e);if(!(n instanceof Promise))return this.state=s.possibleState.ready,Promise.resolve();const d=n.then(()=>{this.ready()}).catch(a=>{if(a instanceof u||a instanceof RangeError||a instanceof ReferenceError||a instanceof SyntaxError||a instanceof TypeError||a instanceof URIError||a instanceof EvalError)throw a;const y=B(a);if(y&&!this.is(s.possibleState.pending,s.possibleState.lock))throw new K(this.name,this.state);if(y&&this._value.abortController instanceof AbortController&&this._value.abortController.signal.reason===s.abortedByLock){this.state=s.possibleState.lock,this._value=null;return}if(y){this.state=s.possibleState.abort;return}this.setError(new I(this.name,{cause:a}))});return this._value={promise:d,abortController:o},d}abort(t){return this.isPending?(this._value.abortController.abort(t),this._value.promise):Promise.resolve()}lock(){return this.isPending?this.abort(s.abortedByLock):(this.state=s.possibleState.lock,this._value=null,Promise.resolve())}unlock(){if(!this.isLock)throw new b(this.name,this.state,s.possibleState.ready);return this.ready()}setError(t){if(!this.isPending)throw new b(this.name,this.state,s.possibleState.error);return this.state=s.possibleState.error,this._value=t,this}ready(){return this.state=s.possibleState.ready,this}resetError(){if(!this.error)throw new b(this.name,this.state,s.possibleState.ready);return this.ready()}};i(s,"actionFlag",Symbol("__action_original_method__")),i(s,"possibleState",{pending:"pending",error:"error",lock:"lock",ready:"ready",abort:"abort"}),i(s,"abortedByLock",Symbol("lock"));let h=s;const T=Proxy;function D(r){if(!(r instanceof g))throw new Error("ProtoModel instance is required");return new T(l.shallowReactive(r),{get(e,o,c){const n=Reflect.get(e,o,c),d=typeof n=="function";return d&&h.actionFlag in n&&typeof n[h.actionFlag]=="function"?e.action(n):d?n.bind(e):n}})}const p=Symbol("scope"),m=Symbol("model"),A=Symbol("actions"),v=Symbol("actionIds"),w=Symbol("actionStates"),E=Symbol("actionsSize"),f=Symbol("watchStopHandlers");var k,M,P,C,R,x,F;F=p,x=m,R=A,C=v,P=w,M=E,k=f;const S=class S{constructor(){i(this,F,l.effectScope(!0));i(this,x,null);i(this,R,new WeakMap);i(this,C,new WeakMap);i(this,P,new Map);i(this,M,0);i(this,k,new Set)}static model(...t){if(this.prototype===S.prototype)throw new Error("ProtoModel is abstract class and can not be instantiated");const e=new this(...t),o=S.createModel(e);return e[m]=o,o}get hasPendingActions(){return!!this.getActionStatesRef(h.possibleState.pending).value}get hasActionWithError(){return!!this.getActionStatesRef(h.possibleState.error).value}watch(...t){if(t.length===0)throw new Error("watch requires at least one argument");const e=t.length===1?this[p].run(()=>l.watchEffect(t[0])):this[p].run(()=>l.watch(...t));if(!e)throw new Error("watchStopHandler is undefined");return this[f].add(e),()=>{e(),this[f].delete(e)}}computed(t,e){return this[p].run(()=>l.computed(t,e))}updateBit(t,e,o){const c=o?1:0,n=~(1<<e);return t&n|c<<e}createAction(t){const e=()=>{if(!this[m])throw new Error("Model not set");return this[m]},o=h.create(this,t,e,this.setActionState.bind(this));return this[A].set(t,o),this[v].set(o,++this[E]),this.setActionState(o),o}getActionStatesRef(t){const e=this[w].get(t)||l.ref(0);return this[w].get(t)===void 0&&this[w].set(t,e),e}action(t){if(!(h.actionFlag in t&&typeof t[h.actionFlag]=="function"))throw new u("Action decorator is not applied to the method");return this[A].get(t)||this.createAction(t)}setActionState(t){const e=this[v].get(t);if(!e)throw new Error("Action not found");for(const o of t.possibleStates)o!==t.state&&(this.getActionStatesRef(o).value=this.updateBit(this.getActionStatesRef(o).value,e,!1));this.getActionStatesRef(t.state).value=this.updateBit(this.getActionStatesRef(t.state).value,e,!0)}isModelOf(t){return this instanceof t}destructor(){this[f].forEach(t=>{t()}),this[f]=new Set,this[p].stop()}};i(S,"createModel",D);let g=S;function O(r,t){if(t.static)throw new Error("Action decorator is not supported for static methods");if(t.private)throw new Error("Action decorator is not supported for private methods");const e=t.name.toString(),o={[e]:function(...c){return this.action(o[e]).exec(...c)}};return o[e][h.actionFlag]=r,o[e]}exports.ActionError=I;exports.ActionInternalError=u;exports.ActionStatusConflictError=b;exports.ActionUnexpectedAbortError=K;exports.ProtoModel=g;exports.action=O;
package/dist/index.d.ts CHANGED
@@ -6,9 +6,17 @@ import { Ref } from 'vue';
6
6
  import { ShallowReactive } from 'vue';
7
7
  import { WatchStopHandle } from 'vue';
8
8
 
9
- declare class Action<Args extends any[] = unknown[]> {
10
- protected model: ProtoModel;
9
+ /**
10
+ * We should to use here `<T extends ProtoModel>` because
11
+ * we need some methods from `ProtoModel` class which are protected in context of `Model<T>`.
12
+ * For example, `setActionState` method.
13
+ * @see `ProtoModel.setActionState`
14
+ */
15
+ declare class Action<T extends object, Args extends any[] = unknown[], Owner extends object = Model<T>> implements ActionLike<Owner, Args> {
16
+ protected _model: T;
11
17
  protected actionFunction: OriginalMethodWrapper<Args>;
18
+ protected ownerGetter: () => Owner;
19
+ protected setStateCb?: ((action: SrActionLike<Owner, Args>, oldState: ActionStateName, newState: ActionStateName) => void) | undefined;
12
20
  static readonly actionFlag: unique symbol;
13
21
  static readonly possibleState: {
14
22
  readonly pending: "pending";
@@ -22,9 +30,10 @@ declare class Action<Args extends any[] = unknown[]> {
22
30
  protected _state: ActionStateName;
23
31
  protected _value: ActionValue;
24
32
  protected _args: Args | null;
25
- constructor(model: ProtoModel, // TODO: thing about this arg, it may be potential problem
26
- actionFunction: OriginalMethodWrapper<Args>);
33
+ constructor(_model: T, actionFunction: OriginalMethodWrapper<Args>, ownerGetter: () => Owner, setStateCb?: ((action: SrActionLike<Owner, Args>, oldState: ActionStateName, newState: ActionStateName) => void) | undefined);
34
+ static create<T extends ProtoModel, Args extends unknown[] = unknown[], Owner extends object = Model<T>>(model: T, actionFunction: OriginalMethodWrapper<Args>, ownerGetter: () => Owner, setStateCb?: (action: SrActionLike<Owner, Args>, oldState: ActionStateName, newState: ActionStateName) => void): SrActionLike<Owner, Args>;
27
35
  toString(): string;
36
+ get owner(): Owner;
28
37
  get possibleStates(): ActionStateName[];
29
38
  get state(): ActionStateName;
30
39
  protected set state(newState: ActionStateName);
@@ -73,6 +82,8 @@ export declare class ActionError extends Error {
73
82
  toString(): string;
74
83
  }
75
84
 
85
+ declare const actionIdsKey: unique symbol;
86
+
76
87
  /**
77
88
  * IMPORTANT: this class is an error in the correct terminology "errors vs exceptions".
78
89
  *
@@ -91,15 +102,47 @@ export declare class ActionInternalError extends Error {
91
102
  } | undefined);
92
103
  }
93
104
 
105
+ /**
106
+ * Public API interface for Action instances.
107
+ * Describes only the public contract without implementation details.
108
+ */
109
+ declare interface ActionLike<Owner extends object, Args extends any[] = unknown[]> {
110
+ readonly name: string;
111
+ readonly owner: Owner;
112
+ readonly possibleStates: ActionStateName[];
113
+ readonly state: ActionStateName;
114
+ readonly abortController: null | AbortController;
115
+ readonly args: Args | never[];
116
+ readonly promise: null | Promise<void>;
117
+ readonly error: null | ActionError;
118
+ readonly abortReason: unknown;
119
+ readonly isPending: boolean;
120
+ readonly isError: boolean;
121
+ readonly isReady: boolean;
122
+ readonly isLock: boolean;
123
+ readonly isAbort: boolean;
124
+ is(...args: ActionStateName[]): boolean;
125
+ exec(...args: Args): Promise<void>;
126
+ abort(reason?: unknown): Promise<void>;
127
+ lock(): Promise<void>;
128
+ unlock(): this;
129
+ resetError(): this;
130
+ toString(): string;
131
+ }
132
+
94
133
  declare interface ActionPendingValue {
95
134
  promise: Promise<void>;
96
135
  abortController: AbortController;
97
136
  }
98
137
 
99
- export declare type ActionPublic = Omit<Action, 'call'>;
138
+ declare const actionsKey: unique symbol;
139
+
140
+ declare const actionsSizeKey: unique symbol;
100
141
 
101
142
  export declare type ActionStateName = keyof typeof Action.possibleState;
102
143
 
144
+ declare const actionStatesKey: unique symbol;
145
+
103
146
  export declare class ActionStatusConflictError extends ActionInternalError {
104
147
  constructor(actionName: string, currentState: ActionStateName, newState: ActionStateName);
105
148
  }
@@ -137,19 +180,21 @@ declare type ActionValue = ActionPendingValue | ActionError | null;
137
180
  */
138
181
  declare function createModel<Target extends ProtoModel>(protoModel: Target): Model<Target>;
139
182
 
140
- export declare type Model<T> = {
141
- [K in keyof T]: T[K] extends ((...args: infer Args) => Promise<void>) ? Action<Args> : K extends ProtectedMethodInModel ? never : T[K];
142
- };
183
+ export declare type Model<T extends object = object> = ShallowReactive<{
184
+ [K in keyof T]: T[K] extends ((...args: infer Args) => Promise<void>) ? SrActionLike<T, Args> : K extends ProtectedMethodInModel ? never : T[K];
185
+ }>;
143
186
 
144
187
  export declare type ModelAdapterProxyConstructor = new <Target extends ProtoModel>(target: Target, handler: ProxyHandler<Target>) => Model<Target>;
145
188
 
146
189
  export declare type ModelConstructor<T extends new (...args: unknown[]) => unknown> = T extends new (...args: unknown[]) => infer R ? R extends ProtoModel ? T : never : never;
147
190
 
148
- declare type ModelConstructor_2 = new (...args: any[]) => ProtoModel;
191
+ declare type ModelConstructor_2<T extends ProtoModel> = new (...args: any[]) => T;
192
+
193
+ declare const modelKey: unique symbol;
149
194
 
150
195
  export declare type OriginalMethod = (...args: any[]) => Promise<void>;
151
196
 
152
- export declare interface OriginalMethodWrapper<Args extends unknown[] = unknown[]> {
197
+ export declare interface OriginalMethodWrapper<Args extends any[] = unknown[]> {
153
198
  (...args: Args): Promise<void>;
154
199
  [Action.actionFlag]: OriginalMethod;
155
200
  }
@@ -157,12 +202,13 @@ export declare interface OriginalMethodWrapper<Args extends unknown[] = unknown[
157
202
  export declare type ProtectedMethodInModel = 'action' | 'setActionState';
158
203
 
159
204
  export declare abstract class ProtoModel {
160
- protected _effectScope: EffectScope;
161
- protected _actions: WeakMap<OriginalMethodWrapper<unknown[]>, ShallowReactive<ActionPublic>>;
162
- protected _actionIds: WeakMap<ShallowReactive<ActionPublic>, number>;
163
- protected _actionStates: Map<"error" | "abort" | "lock" | "pending" | "ready", Ref<number>>;
164
- protected _actionsSize: number;
165
- protected _watchStopHandlers: Set<WatchStopHandle>;
205
+ protected [scopeKey]: EffectScope;
206
+ protected [modelKey]: Model<this> | null;
207
+ protected [actionsKey]: WeakMap<OriginalMethodWrapper<unknown[]>, SrActionLike<Model<this>>>;
208
+ protected [actionIdsKey]: WeakMap<SrActionLike<Model<this>>, number>;
209
+ protected [actionStatesKey]: Map<"pending" | "error" | "lock" | "ready" | "abort", Ref<number>>;
210
+ protected [actionsSizeKey]: number;
211
+ protected [watchStopHandlersKey]: Set<WatchStopHandle>;
166
212
  protected static createModel: typeof createModel;
167
213
  /**
168
214
  * Creates a model instance.
@@ -233,7 +279,7 @@ export declare abstract class ProtoModel {
233
279
  protected watch(...args: unknown[]): WatchStopHandle;
234
280
  protected computed<T>(getter: ComputedGetter<T>, debugOptions?: DebuggerOptions): ComputedRef<T>;
235
281
  protected updateBit(number: number, bitPosition: number, bitValue: boolean): number;
236
- protected createAction(actionFunction: OriginalMethodWrapper): ShallowReactive<ActionPublic>;
282
+ protected createAction(actionFunction: OriginalMethodWrapper): SrActionLike<Model<this>>;
237
283
  protected getActionStatesRef(stateName: ActionStateName): Ref<number>;
238
284
  /**
239
285
  * Gets Action instance by wrapped original method or create Action instance.
@@ -278,16 +324,26 @@ export declare abstract class ProtoModel {
278
324
  * @param originalMethod - defined as OriginalMethod or OriginalMethodWrapper.
279
325
  * @returns action
280
326
  */
281
- protected action(originalMethod: OriginalMethod | OriginalMethodWrapper): ShallowReactive<ActionPublic>;
327
+ protected action(originalMethod: OriginalMethod | OriginalMethodWrapper): SrActionLike<Model<this>>;
282
328
  /**
283
329
  * It is public method in context ProtoModel,
284
330
  * but in Model<ProtoModel> context it is protected method
285
331
  *
286
332
  * @see type Model<T>
287
333
  */
288
- setActionState(action: Action): void;
289
- isModelOf(typeModel: ModelConstructor_2): boolean;
334
+ setActionState(action: SrActionLike<Model<this>>): void;
335
+ isModelOf<T extends ProtoModel>(typeModel: ModelConstructor_2<T>): boolean;
290
336
  destructor(): void;
291
337
  }
292
338
 
339
+ declare const scopeKey: unique symbol;
340
+
341
+ /**
342
+ * Reactive ActionLike type - ActionLike wrapped in ShallowReactive.
343
+ * This is the type used throughout the codebase for action instances.
344
+ */
345
+ declare type SrActionLike<Owner extends object, Args extends any[] = unknown[]> = ShallowReactive<ActionLike<Owner, Args>>;
346
+
347
+ declare const watchStopHandlersKey: unique symbol;
348
+
293
349
  export { }
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- var w = Object.defineProperty;
2
- var m = (r, t, e) => t in r ? w(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
- var n = (r, t, e) => m(r, typeof t != "symbol" ? t + "" : t, e);
4
- import { shallowReactive as S, effectScope as g, watchEffect as A, watch as y, computed as v, ref as k } from "vue";
5
- class E extends Error {
1
+ var I = Object.defineProperty;
2
+ var K = (r, t, e) => t in r ? I(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
+ var i = (r, t, e) => K(r, typeof t != "symbol" ? t + "" : t, e);
4
+ import { shallowReactive as F, effectScope as L, watchEffect as $, watch as B, computed as D, ref as T } from "vue";
5
+ class H extends Error {
6
6
  constructor(t, e) {
7
7
  super(e.cause.message), this.actionName = t, this.options = e, this.name = this.constructor.name;
8
8
  }
@@ -16,38 +16,44 @@ class E extends Error {
16
16
  return this.options.cause.message;
17
17
  }
18
18
  }
19
- class l extends Error {
19
+ class u extends Error {
20
20
  constructor(t, e) {
21
21
  super(t, e), this.message = t, this.options = e, this.name = this.constructor.name;
22
22
  }
23
23
  }
24
- class d extends l {
24
+ class b extends u {
25
25
  constructor(t, e, o) {
26
26
  super(`Trying to update state of ${t} from ${e} to ${o}`), this.name = this.constructor.name;
27
27
  }
28
28
  }
29
- class M extends l {
29
+ class O extends u {
30
30
  constructor(t, e) {
31
31
  super(`Unexpected AbortError for the action ${t} in state ${e}`), this.name = this.constructor.name;
32
32
  }
33
33
  }
34
- const P = (r) => r instanceof DOMException && r.name === "AbortError" || typeof r == "object" && r !== null && "message" in r && r.message === "canceled", s = class s {
35
- constructor(t, e) {
36
- n(this, "name");
37
- n(this, "_state", s.possibleState.ready);
38
- n(this, "_value", null);
39
- n(this, "_args", null);
40
- this.model = t, this.actionFunction = e;
41
- const o = e.name;
42
- if (!(o in t && typeof t[o] == "function"))
43
- throw new l(`Model does not contain method ${o}`);
34
+ const j = (r) => r instanceof DOMException && r.name === "AbortError" || typeof r == "object" && r !== null && "message" in r && r.message === "canceled", s = class s {
35
+ constructor(t, e, o, c) {
36
+ i(this, "name");
37
+ i(this, "_state", s.possibleState.ready);
38
+ i(this, "_value", null);
39
+ i(this, "_args", null);
40
+ this._model = t, this.actionFunction = e, this.ownerGetter = o, this.setStateCb = c;
41
+ const n = e.name;
42
+ if (!(n in this._model && typeof this._model[n] == "function"))
43
+ throw new u(`Model does not contain method ${n}`);
44
44
  if (typeof e[s.actionFlag] != "function")
45
- throw new l(`Method ${o} is not action`);
46
- this.name = o;
45
+ throw new u(`Method ${n} is not action`);
46
+ this.name = n;
47
+ }
48
+ static create(t, e, o, c) {
49
+ return F(new s(t, e, o, c));
47
50
  }
48
51
  toString() {
49
52
  return this.name;
50
53
  }
54
+ get owner() {
55
+ return this.ownerGetter();
56
+ }
51
57
  get possibleStates() {
52
58
  return Object.values(s.possibleState);
53
59
  }
@@ -55,7 +61,8 @@ const P = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
55
61
  return this._state;
56
62
  }
57
63
  set state(t) {
58
- this._state = t, this.model.setActionState(this);
64
+ const e = this._state;
65
+ this._state = t, this.setStateCb && this.setStateCb(this, e, t);
59
66
  }
60
67
  get abortController() {
61
68
  return this.isPending ? this._value.abortController : null;
@@ -96,7 +103,7 @@ const P = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
96
103
  */
97
104
  exec(...t) {
98
105
  if (this.is(s.possibleState.lock, s.possibleState.pending))
99
- throw new d(
106
+ throw new b(
100
107
  this.name,
101
108
  this.state,
102
109
  s.possibleState.pending
@@ -104,31 +111,31 @@ const P = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
104
111
  const e = [...t];
105
112
  let o = t.length && t[t.length - 1];
106
113
  o instanceof AbortController || (o = new AbortController(), e.push(o)), this.state = s.possibleState.pending, this._args = t;
107
- const i = this.actionFunction[s.actionFlag].apply(this.model, e);
108
- if (!(i instanceof Promise))
114
+ const n = this.actionFunction[s.actionFlag].apply(this._model, e);
115
+ if (!(n instanceof Promise))
109
116
  return this.state = s.possibleState.ready, Promise.resolve();
110
- const u = i.then(() => {
117
+ const l = n.then(() => {
111
118
  this.ready();
112
119
  }).catch((a) => {
113
- if (a instanceof l || a instanceof RangeError || a instanceof ReferenceError || a instanceof SyntaxError || a instanceof TypeError || a instanceof URIError || a instanceof EvalError)
120
+ if (a instanceof u || a instanceof RangeError || a instanceof ReferenceError || a instanceof SyntaxError || a instanceof TypeError || a instanceof URIError || a instanceof EvalError)
114
121
  throw a;
115
- const f = P(a);
116
- if (f && !this.is(s.possibleState.pending, s.possibleState.lock))
117
- throw new M(this.name, this.state);
118
- if (f && this._value.abortController instanceof AbortController && this._value.abortController.signal.reason === s.abortedByLock) {
122
+ const w = j(a);
123
+ if (w && !this.is(s.possibleState.pending, s.possibleState.lock))
124
+ throw new O(this.name, this.state);
125
+ if (w && this._value.abortController instanceof AbortController && this._value.abortController.signal.reason === s.abortedByLock) {
119
126
  this.state = s.possibleState.lock, this._value = null;
120
127
  return;
121
128
  }
122
- if (f) {
129
+ if (w) {
123
130
  this.state = s.possibleState.abort;
124
131
  return;
125
132
  }
126
- this.setError(new E(this.name, { cause: a }));
133
+ this.setError(new H(this.name, { cause: a }));
127
134
  });
128
135
  return this._value = {
129
- promise: u,
136
+ promise: l,
130
137
  abortController: o
131
- }, u;
138
+ }, l;
132
139
  }
133
140
  // Returns same promise as exec method
134
141
  // but in reject state
@@ -141,7 +148,7 @@ const P = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
141
148
  }
142
149
  unlock() {
143
150
  if (!this.isLock)
144
- throw new d(
151
+ throw new b(
145
152
  this.name,
146
153
  this.state,
147
154
  s.possibleState.ready
@@ -150,7 +157,7 @@ const P = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
150
157
  }
151
158
  setError(t) {
152
159
  if (!this.isPending)
153
- throw new d(
160
+ throw new b(
154
161
  this.name,
155
162
  this.state,
156
163
  s.possibleState.error
@@ -162,7 +169,7 @@ const P = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
162
169
  }
163
170
  resetError() {
164
171
  if (!this.error)
165
- throw new d(
172
+ throw new b(
166
173
  this.name,
167
174
  this.state,
168
175
  s.possibleState.ready
@@ -170,40 +177,44 @@ const P = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
170
177
  return this.ready();
171
178
  }
172
179
  };
173
- n(s, "actionFlag", Symbol("__action_original_method__")), n(s, "possibleState", {
180
+ i(s, "actionFlag", Symbol("__action_original_method__")), i(s, "possibleState", {
174
181
  pending: "pending",
175
182
  error: "error",
176
183
  lock: "lock",
177
184
  ready: "ready",
178
185
  abort: "abort"
179
- }), n(s, "abortedByLock", Symbol("lock"));
180
- let c = s;
181
- const _ = Proxy;
182
- function R(r) {
183
- if (!(r instanceof b))
186
+ }), i(s, "abortedByLock", Symbol("lock"));
187
+ let h = s;
188
+ const z = Proxy;
189
+ function G(r) {
190
+ if (!(r instanceof A))
184
191
  throw new Error("ProtoModel instance is required");
185
- return new _(
186
- S(r),
192
+ return new z(
193
+ F(r),
187
194
  {
188
- get(e, o, h) {
189
- const i = Reflect.get(e, o, h), u = typeof i == "function";
190
- return u && c.actionFlag in i && typeof i[c.actionFlag] == "function" ? e.action(i) : u ? i.bind(e) : i;
195
+ get(e, o, c) {
196
+ const n = Reflect.get(e, o, c), l = typeof n == "function";
197
+ return l && h.actionFlag in n && typeof n[h.actionFlag] == "function" ? e.action(n) : l ? n.bind(e) : n;
191
198
  }
192
199
  }
193
200
  );
194
201
  }
195
- const p = class p {
202
+ const d = Symbol("scope"), m = Symbol("model"), g = Symbol("actions"), y = Symbol("actionIds"), S = Symbol("actionStates"), v = Symbol("actionsSize"), p = Symbol("watchStopHandlers");
203
+ var k, E, M, C, P, R, x;
204
+ x = d, R = m, P = g, C = y, M = S, E = v, k = p;
205
+ const f = class f {
196
206
  constructor() {
197
207
  // each model has its own effect scope to avoid memory leaks
198
- n(this, "_effectScope", g(!0));
208
+ i(this, x, L(!0));
209
+ i(this, R, null);
199
210
  // we use WeakMap to store actions as keys to avoid memory leaks
200
- n(this, "_actions", /* @__PURE__ */ new WeakMap());
201
- n(this, "_actionIds", /* @__PURE__ */ new WeakMap());
202
- n(this, "_actionStates", /* @__PURE__ */ new Map());
211
+ i(this, P, /* @__PURE__ */ new WeakMap());
212
+ i(this, C, /* @__PURE__ */ new WeakMap());
213
+ i(this, M, /* @__PURE__ */ new Map());
203
214
  // WeakMap doesn't have a size property, so we need to store the size of the map
204
- n(this, "_actionsSize", 0);
215
+ i(this, E, 0);
205
216
  // watchers are stored in a set to avoid memory leaks
206
- n(this, "_watchStopHandlers", /* @__PURE__ */ new Set());
217
+ i(this, k, /* @__PURE__ */ new Set());
207
218
  }
208
219
  /**
209
220
  * Creates a model instance.
@@ -213,16 +224,16 @@ const p = class p {
213
224
  * @see src/create-model.ts
214
225
  */
215
226
  static model(...t) {
216
- if (this.prototype === p.prototype)
227
+ if (this.prototype === f.prototype)
217
228
  throw new Error("ProtoModel is abstract class and can not be instantiated");
218
- const e = new this(...t);
219
- return p.createModel(e);
229
+ const e = new this(...t), o = f.createModel(e);
230
+ return e[m] = o, o;
220
231
  }
221
232
  get hasPendingActions() {
222
- return !!this.getActionStatesRef(c.possibleState.pending).value;
233
+ return !!this.getActionStatesRef(h.possibleState.pending).value;
223
234
  }
224
235
  get hasActionWithError() {
225
- return !!this.getActionStatesRef(c.possibleState.error).value;
236
+ return !!this.getActionStatesRef(h.possibleState.error).value;
226
237
  }
227
238
  /**
228
239
  * Registers watcher in the model effect scope.
@@ -283,28 +294,37 @@ const p = class p {
283
294
  watch(...t) {
284
295
  if (t.length === 0)
285
296
  throw new Error("watch requires at least one argument");
286
- const e = t.length === 1 ? this._effectScope.run(() => A(t[0])) : this._effectScope.run(() => y(...t));
297
+ const e = t.length === 1 ? this[d].run(() => $(t[0])) : this[d].run(() => B(...t));
287
298
  if (!e)
288
299
  throw new Error("watchStopHandler is undefined");
289
- return this._watchStopHandlers.add(e), () => {
290
- e(), this._watchStopHandlers.delete(e);
300
+ return this[p].add(e), () => {
301
+ e(), this[p].delete(e);
291
302
  };
292
303
  }
293
304
  computed(t, e) {
294
- return this._effectScope.run(() => v(t, e));
305
+ return this[d].run(() => D(t, e));
295
306
  }
296
307
  // @see https://github.com/trekhleb/javascript-algorithms/blob/master/src/algorithms/math/bits/updateBit.js
297
308
  updateBit(t, e, o) {
298
- const h = o ? 1 : 0, i = ~(1 << e);
299
- return t & i | h << e;
309
+ const c = o ? 1 : 0, n = ~(1 << e);
310
+ return t & n | c << e;
300
311
  }
301
312
  createAction(t) {
302
- const e = S(new c(this, t));
303
- return this._actions.set(t, e), this._actionIds.set(e, ++this._actionsSize), this.setActionState(e), e;
313
+ const e = () => {
314
+ if (!this[m])
315
+ throw new Error("Model not set");
316
+ return this[m];
317
+ }, o = h.create(
318
+ this,
319
+ t,
320
+ e,
321
+ this.setActionState.bind(this)
322
+ );
323
+ return this[g].set(t, o), this[y].set(o, ++this[v]), this.setActionState(o), o;
304
324
  }
305
325
  getActionStatesRef(t) {
306
- const e = this._actionStates.get(t) || k(0);
307
- return this._actionStates.get(t) === void 0 && this._actionStates.set(t, e), e;
326
+ const e = this[S].get(t) || T(0);
327
+ return this[S].get(t) === void 0 && this[S].set(t, e), e;
308
328
  }
309
329
  /**
310
330
  * Gets Action instance by wrapped original method or create Action instance.
@@ -350,9 +370,9 @@ const p = class p {
350
370
  * @returns action
351
371
  */
352
372
  action(t) {
353
- if (!(c.actionFlag in t && typeof t[c.actionFlag] == "function"))
354
- throw new l("Action decorator is not applied to the method");
355
- return this._actions.get(t) || this.createAction(t);
373
+ if (!(h.actionFlag in t && typeof t[h.actionFlag] == "function"))
374
+ throw new u("Action decorator is not applied to the method");
375
+ return this[g].get(t) || this.createAction(t);
356
376
  }
357
377
  /**
358
378
  * It is public method in context ProtoModel,
@@ -361,7 +381,7 @@ const p = class p {
361
381
  * @see type Model<T>
362
382
  */
363
383
  setActionState(t) {
364
- const e = this._actionIds.get(t);
384
+ const e = this[y].get(t);
365
385
  if (!e)
366
386
  throw new Error("Action not found");
367
387
  for (const o of t.possibleStates)
@@ -372,14 +392,14 @@ const p = class p {
372
392
  return this instanceof t;
373
393
  }
374
394
  destructor() {
375
- this._watchStopHandlers.forEach((t) => {
395
+ this[p].forEach((t) => {
376
396
  t();
377
- }), this._watchStopHandlers = /* @__PURE__ */ new Set(), this._effectScope.stop();
397
+ }), this[p] = /* @__PURE__ */ new Set(), this[d].stop();
378
398
  }
379
399
  };
380
- n(p, "createModel", R);
381
- let b = p;
382
- function H(r, t) {
400
+ i(f, "createModel", G);
401
+ let A = f;
402
+ function V(r, t) {
383
403
  if (t.static)
384
404
  throw new Error("Action decorator is not supported for static methods");
385
405
  if (t.private)
@@ -388,17 +408,17 @@ function H(r, t) {
388
408
  // Action constructor checks that model has method with the same name.
389
409
  // We can`t define anonymous function and change name because Function.name is readonly property.
390
410
  // So we need to create stub object to save original method name
391
- [e]: function(...h) {
392
- return this.action(o[e]).exec(...h);
411
+ [e]: function(...c) {
412
+ return this.action(o[e]).exec(...c);
393
413
  }
394
414
  };
395
- return o[e][c.actionFlag] = r, o[e];
415
+ return o[e][h.actionFlag] = r, o[e];
396
416
  }
397
417
  export {
398
- E as ActionError,
399
- l as ActionInternalError,
400
- d as ActionStatusConflictError,
401
- M as ActionUnexpectedAbortError,
402
- b as ProtoModel,
403
- H as action
418
+ H as ActionError,
419
+ u as ActionInternalError,
420
+ b as ActionStatusConflictError,
421
+ O as ActionUnexpectedAbortError,
422
+ A as ProtoModel,
423
+ V as action
404
424
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@vue-modeler/model",
4
- "version": "2.1.1-beta.1",
4
+ "version": "2.2.0-beta.2",
5
5
  "description": "A state management library based on models for Vue.js",
6
6
  "author": "abratko",
7
7
  "license": "MIT",
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "scripts": {
47
47
  "build": "tsc && vite build",
48
- "test": "vitest",
48
+ "test": "tsc --noEmit && vitest",
49
49
  "coverage": "vitest run --coverage",
50
50
  "semantic-release": "semantic-release"
51
51
  },