@vue-modeler/model 2.2.0-beta.7 → 2.2.5-beta.1

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/README.md CHANGED
@@ -1,4 +1,6 @@
1
- # Introduction
1
+ # vue-modeler/model
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@vue-modeler/model.svg)](https://www.npmjs.com/package/@vue-modeler/model) [![codecov](https://codecov.io/gh/vue-modeler/model/branch/main/graph/badge.svg?token=BFQI22MBZ1)](https://codecov.io/gh/vue-modeler/model)
2
4
 
3
5
  ## What is @vue-modeler/model
4
6
 
@@ -10,7 +12,7 @@ A state management library based on models for [Vue.js](https://vuejs.org/). The
10
12
 
11
13
  - **No global state store**. No store means no problems. State is encapsulated within the model and is reactive. Outside the model, it's only accessible for reading and observation.
12
14
  - **Extremely simple API**: A model prototype is a standard class, actions are defined as standard methods with decorators. Create a model by calling a factory method — nothing more needed. Reactive properties and behavior are defined using the standard Vue API.
13
- - **Supports shared models**. A built-in model container ensures that a model remains in memory while being used. Unused models are automatically removed from the container.
15
+ - **Supports shared models**. Models can be shared across components. You can manage model instances using dependency injection or your own container pattern.
14
16
  - **Follows DRY principle**. Actions have their own state. There's no need to write additional code to track action states. Focus instead on designing architecture and business logic.
15
17
  - **Embraces OOP**. Model prototypes are classes, supporting inheritance, encapsulation, polymorphism, and destructors.
16
18
  - **Complies with SOLID principles**. Encourages clean coding practices like composition of models, dependency injection via constructors, separation of interfaces, single responsibility, etc.
@@ -55,14 +57,14 @@ This library promises to simplify state management in [Vue.js](https://vuejs.org
55
57
 
56
58
  ## Installation
57
59
 
58
- First, [install @vue-modeler/dc](https://github.com/vue-modeler/dc?tab=readme-ov-file#installation)
59
-
60
- Then install @vue-modeler/model:
60
+ Install @vue-modeler/model:
61
61
 
62
62
  ```bash
63
63
  npm add @vue-modeler/model
64
64
  ```
65
65
 
66
+ It is recommended to use it together with the dependency container [@vue-modeler/dc](https://github.com/vue-modeler/dc). For installation instructions and provider setup, see the [@vue-modeler/dc documentation](https://github.com/vue-modeler/dc?tab=readme-ov-file#installation).
67
+
66
68
  ## Usage Examples
67
69
 
68
70
  ### 1. Define Proto model
@@ -105,7 +107,7 @@ class User extends ProtoModel {
105
107
  ) {
106
108
  super()
107
109
 
108
- this.action(this.init).exec()
110
+ this.init()
109
111
  }
110
112
 
111
113
  // Actions (async methods with @action decorator)
@@ -148,17 +150,30 @@ export const patchUser = async (dto: PatchDto): Promise<void> => {
148
150
  }
149
151
  ```
150
152
 
151
- ### 3. Compose all together and create model provider
153
+ ### 3. Create model provider
152
154
 
153
- ```typescript
154
- import { model } from '@vue-modeler/model'
155
+ Using `@vue-modeler/dc` (recommended):
156
+
157
+ ```typescript
158
+ import { provider } from '@vue-modeler/dc'
159
+ import { User } from './user-model'
160
+ import { fetchUser, patchUser } from './api'
155
161
 
156
- export const useUser = model(() => new User({
157
- fetchUser,
158
- patch: patchUser
162
+ export const useUser = provider(() => User.model({
163
+ fetchUser,
164
+ patch: patchUser
159
165
  }))
160
166
  ```
161
167
 
168
+ Or without dependency container:
169
+
170
+ ```typescript
171
+ export const useUser = () => User.model({
172
+ fetchUser,
173
+ patch: patchUser
174
+ })
175
+ ```
176
+
162
177
  ### 4. Using Models in Vue Components
163
178
 
164
179
  ```html
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var L=Object.defineProperty;var B=(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)=>B(r,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=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 d extends Error{constructor(t,e){super(t,e),this.message=t,this.options=e,this.name=this.constructor.name}}class b extends d{constructor(t,e,o){super(`Trying to update state of ${t} from ${e} to ${o}`),this.name=this.constructor.name}}class $ extends d{constructor(t,e){super(`Unexpected AbortError for the action ${t} in state ${e}`),this.name=this.constructor.name}}const T=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,h){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,this._validateArgs=h;const n=e.name;if(!(n in this._model&&typeof this._model[n]=="function"))throw new d(`Model does not contain method ${n}`);if(typeof e[s.actionFlag]!="function")throw new d(`Method ${n} is not action`);this.name=n}static create(t,e,o,c,h){return u.shallowReactive(new s(t,e,o,c,h))}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,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)}validate(...t){return this._validateArgs(this,...t)}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 h=this.actionFunction[s.actionFlag].apply(this._model,e);if(!(h instanceof Promise))return this.state=s.possibleState.ready,Promise.resolve();const n=h.then(()=>{this.ready()}).catch(a=>{if(a instanceof d||a instanceof RangeError||a instanceof ReferenceError||a instanceof SyntaxError||a instanceof TypeError||a instanceof URIError||a instanceof EvalError)throw a;const w=T(a);if(w&&!this.is(s.possibleState.pending,s.possibleState.lock))throw new $(this.name,this.state);if(w&&this._value.abortController instanceof AbortController&&this._value.abortController.signal.reason===s.abortedByLock){this.state=s.possibleState.lock,this._value=null;return}if(w){this.state=s.possibleState.abort;return}this.setError(new I(this.name,{cause:a}))});return this._value={promise:n,abortController:o},n}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 l=s;const p=Symbol("scope"),S=Symbol("model"),A=Symbol("actions"),y=Symbol("actionIds"),g=Symbol("actionStates"),E=Symbol("actionsSize"),f=Symbol("watchStopHandlers"),D=Proxy;var k,M,P,C,R,x,F;F=p,x=S,R=A,C=y,P=g,M=E,k=f;const m=class m{constructor(){i(this,F,u.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 createModel(t){if(!(t instanceof m))throw new Error("ProtoModel instance is required");const e=new D(u.shallowReactive(t),{get(o,c,h){const n=Reflect.get(o,c,h),a=typeof n=="function";return a&&l.actionFlag in n&&typeof n[l.actionFlag]=="function"?o.action(n):a?n.bind(o):n}});return t[S]=e,e}static model(...t){if(this.prototype===m.prototype)throw new Error("ProtoModel is abstract class and can not be instantiated");const e=new this(...t);return m.createModel(e)}get hasPendingActions(){return!!this.getActionStatesRef(l.possibleState.pending).value}get hasActionWithError(){return!!this.getActionStatesRef(l.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(()=>u.watchEffect(t[0])):this[p].run(()=>u.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(()=>u.computed(t,e))}updateBit(t,e,o){const c=o?1:0,h=~(1<<e);return t&h|c<<e}createAction(t){const e=()=>{if(!this[S])throw new Error("Model not set");return this[S]},o=l.create(this,t,e,this.setActionState.bind(this),this.validateArgs.bind(this));return this[A].set(t,o),this[y].set(o,++this[E]),this.setActionState(o),o}getActionStatesRef(t){const e=this[g].get(t)||u.ref(0);return this[g].get(t)===void 0&&this[g].set(t,e),e}action(t){if(!(l.actionFlag in t&&typeof t[l.actionFlag]=="function"))throw new d("Action decorator is not applied to the method");return this[A].get(t)||this.createAction(t)}setActionState(t){const e=this[y].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)}validateArgs(t,...e){const o=`validateArgs is not implemented for action ${t.name} in the model`;return[new Error(o)]}isModelOf(t){return this instanceof t}destructor(){this[f].forEach(t=>{t()}),this[f]=new Set,this[p].stop()}};let v=m;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");let e;try{e=t.name.toString()}catch(c){const n=`Invalid context. Can\`t get name of the method: ${c instanceof Error?c.message:"unknown error"}`;throw new Error(n)}const o={[e]:function(...c){return this.action(o[e]).exec(...c)}};return o[e][l.actionFlag]=r,o[e]}exports.Action=l;exports.ActionError=I;exports.ActionInternalError=d;exports.ActionStatusConflictError=b;exports.ActionUnexpectedAbortError=$;exports.ProtoModel=v;exports.action=O;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("vue");class v 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 l extends Error{constructor(t,e){super(t,e),this.message=t,this.options=e,this.name=this.constructor.name}}class p extends l{constructor(t,e,r){super(`Trying to update state of ${t} from ${e} to ${r}`),this.name=this.constructor.name}}class A extends l{constructor(t,e){super(`Unexpected AbortError for the action ${t} in state ${e}`),this.name=this.constructor.name}}const k=a=>a instanceof DOMException&&a.name==="AbortError"||typeof a=="object"&&a!==null&&"message"in a&&a.message==="canceled";class s{constructor(t,e,r,i,c){this._model=t,this.actionFunction=e,this.ownerGetter=r,this.setStateCb=i,this._validateArgs=c;const o=e.name;if(!(o in this._model&&typeof this._model[o]=="function"))throw new l(`Model does not contain method ${o}`);if(typeof e[s.actionFlag]!="function")throw new l(`Method ${o} is not action`);this.name=o}static actionFlag=Symbol("__action_original_method__");static possibleState={pending:"pending",error:"error",lock:"lock",ready:"ready",abort:"abort"};static abortedByLock=Symbol("lock");name;_state=s.possibleState.ready;_value=null;_args=null;static create(t,e,r,i,c){return h.shallowReactive(new s(t,e,r,i,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,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)}validate(...t){return this._validateArgs(this,...t)}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 r=t.length&&t[t.length-1];r instanceof AbortController||(r=new AbortController,e.push(r)),this.state=s.possibleState.pending,this._args=t;const c=this.actionFunction[s.actionFlag].apply(this._model,e);if(!(c instanceof Promise))return this.state=s.possibleState.ready,Promise.resolve();const o=c.then(()=>{this.ready()}).catch(n=>{if(n instanceof l||n instanceof RangeError||n instanceof ReferenceError||n instanceof SyntaxError||n instanceof TypeError||n instanceof URIError||n instanceof EvalError)throw n;const S=k(n);if(S&&!this.is(s.possibleState.pending,s.possibleState.lock))throw new A(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 v(this.name,{cause:n}))});return this._value={promise:o,abortController:r},o}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()}}const u=Symbol("scope"),b=Symbol("model"),g=Symbol("actions"),w=Symbol("actionIds"),m=Symbol("actionStates"),y=Symbol("actionsSize"),d=Symbol("watchStopHandlers"),M=Proxy;class f{[u]=h.effectScope(!0);[b]=null;[g]=new WeakMap;[w]=new WeakMap;[m]=new Map;[y]=0;[d]=new Set;static createModel(t){if(!(t instanceof f))throw new TypeError("ProtoModel instance is required");const e=new M(h.shallowReactive(t),{get(r,i,c){const o=Reflect.get(r,i,c),n=typeof o=="function";return n&&s.actionFlag in o&&typeof o[s.actionFlag]=="function"?r.action(o):n?o.bind(r):o}});return t[b]=e,e}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(s.possibleState.pending).value}get hasActionWithError(){return!!this.getActionStatesRef(s.possibleState.error).value}watch(...t){if(t.length===0)throw new Error("watch requires at least one argument");const e=t.length===1?this[u].run(()=>h.watchEffect(t[0])):this[u].run(()=>h.watch(...t));if(!e)throw new Error("watchStopHandler is undefined");return this[d].add(e),()=>{e(),this[d].delete(e)}}computed(t,e){return this[u].run(()=>h.computed(t,e))}updateBit(t,e,r){const i=r?1:0,c=~(1<<e);return t&c|i<<e}createAction(t){const e=()=>{if(!this[b])throw new Error("Model not set");return this[b]},r=s.create(this,t,e,this.setActionState.bind(this),this.validateArgs.bind(this));return this[g].set(t,r),this[w].set(r,++this[y]),this.setActionState(r),r}getActionStatesRef(t){const e=this[m].get(t)||h.ref(0);return this[m].get(t)===void 0&&this[m].set(t,e),e}action(t){if(!(s.actionFlag in t&&typeof t[s.actionFlag]=="function"))throw new l("Action decorator is not applied to the method");return this[g].get(t)||this.createAction(t)}setActionState(t){const e=this[w].get(t);if(!e)throw new Error("Action not found");for(const r of t.possibleStates)r!==t.state&&(this.getActionStatesRef(r).value=this.updateBit(this.getActionStatesRef(r).value,e,!1));this.getActionStatesRef(t.state).value=this.updateBit(this.getActionStatesRef(t.state).value,e,!0)}validateArgs(t,...e){const r=`validateArgs is not implemented for action ${t.name} in the model`;return[new Error(r)]}isModelOf(t){return this instanceof t}destructor(){this[d].forEach(t=>{t()}),this[d]=new Set,this[u].stop()}}function P(a,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");let e;try{e=t.name.toString()}catch(i){const o=`Invalid context. Can\`t get name of the method: ${i instanceof Error?i.message:"unknown error"}`;throw new Error(o)}const r={[e]:function(...i){return this.action(r[e]).exec(...i)}};return r[e][s.actionFlag]=a,r[e]}exports.Action=s;exports.ActionError=v;exports.ActionInternalError=l;exports.ActionStatusConflictError=p;exports.ActionUnexpectedAbortError=A;exports.ProtoModel=f;exports.action=P;
package/dist/index.js CHANGED
@@ -1,8 +1,5 @@
1
- var $ = Object.defineProperty;
2
- var K = (r, t, e) => t in r ? $(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 B, watch as D, computed as T, ref as H } from "vue";
5
- class O extends Error {
1
+ import { shallowReactive as y, effectScope as A, watchEffect as E, watch as k, computed as M, ref as C } from "vue";
2
+ class P extends Error {
6
3
  constructor(t, e) {
7
4
  super(e.cause.message), this.actionName = t, this.options = e, this.name = this.constructor.name;
8
5
  }
@@ -16,42 +13,52 @@ class O extends Error {
16
13
  return this.options.cause.message;
17
14
  }
18
15
  }
19
- class u extends Error {
16
+ class h extends Error {
20
17
  constructor(t, e) {
21
18
  super(t, e), this.message = t, this.options = e, this.name = this.constructor.name;
22
19
  }
23
20
  }
24
- class b extends u {
25
- constructor(t, e, o) {
26
- super(`Trying to update state of ${t} from ${e} to ${o}`), this.name = this.constructor.name;
21
+ class d extends h {
22
+ constructor(t, e, r) {
23
+ super(`Trying to update state of ${t} from ${e} to ${r}`), this.name = this.constructor.name;
27
24
  }
28
25
  }
29
- class j extends u {
26
+ class R extends h {
30
27
  constructor(t, e) {
31
28
  super(`Unexpected AbortError for the action ${t} in state ${e}`), this.name = this.constructor.name;
32
29
  }
33
30
  }
34
- const z = (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, h) {
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, this._validateArgs = h;
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}`);
31
+ const x = (a) => a instanceof DOMException && a.name === "AbortError" || typeof a == "object" && a !== null && "message" in a && a.message === "canceled";
32
+ class s {
33
+ constructor(t, e, r, i, c) {
34
+ this._model = t, this.actionFunction = e, this.ownerGetter = r, this.setStateCb = i, this._validateArgs = c;
35
+ const o = e.name;
36
+ if (!(o in this._model && typeof this._model[o] == "function"))
37
+ throw new h(`Model does not contain method ${o}`);
44
38
  if (typeof e[s.actionFlag] != "function")
45
- throw new u(`Method ${n} is not action`);
46
- this.name = n;
47
- }
48
- static create(t, e, o, c, h) {
49
- return F(new s(
39
+ throw new h(`Method ${o} is not action`);
40
+ this.name = o;
41
+ }
42
+ static actionFlag = /* @__PURE__ */ Symbol("__action_original_method__");
43
+ static possibleState = {
44
+ pending: "pending",
45
+ error: "error",
46
+ lock: "lock",
47
+ ready: "ready",
48
+ abort: "abort"
49
+ };
50
+ static abortedByLock = /* @__PURE__ */ Symbol("lock");
51
+ name;
52
+ _state = s.possibleState.ready;
53
+ _value = null;
54
+ _args = null;
55
+ static create(t, e, r, i, c) {
56
+ return y(new s(
50
57
  t,
51
58
  e,
52
- o,
53
- c,
54
- h
59
+ r,
60
+ i,
61
+ c
55
62
  ));
56
63
  }
57
64
  toString() {
@@ -112,39 +119,39 @@ const z = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
112
119
  */
113
120
  exec(...t) {
114
121
  if (this.is(s.possibleState.lock, s.possibleState.pending))
115
- throw new b(
122
+ throw new d(
116
123
  this.name,
117
124
  this.state,
118
125
  s.possibleState.pending
119
126
  );
120
127
  const e = [...t];
121
- let o = t.length && t[t.length - 1];
122
- o instanceof AbortController || (o = new AbortController(), e.push(o)), this.state = s.possibleState.pending, this._args = t;
123
- const h = this.actionFunction[s.actionFlag].apply(this._model, e);
124
- if (!(h instanceof Promise))
128
+ let r = t.length && t[t.length - 1];
129
+ r instanceof AbortController || (r = new AbortController(), e.push(r)), this.state = s.possibleState.pending, this._args = t;
130
+ const c = this.actionFunction[s.actionFlag].apply(this._model, e);
131
+ if (!(c instanceof Promise))
125
132
  return this.state = s.possibleState.ready, Promise.resolve();
126
- const n = h.then(() => {
133
+ const o = c.then(() => {
127
134
  this.ready();
128
- }).catch((a) => {
129
- if (a instanceof u || a instanceof RangeError || a instanceof ReferenceError || a instanceof SyntaxError || a instanceof TypeError || a instanceof URIError || a instanceof EvalError)
130
- throw a;
131
- const S = z(a);
132
- if (S && !this.is(s.possibleState.pending, s.possibleState.lock))
133
- throw new j(this.name, this.state);
134
- if (S && this._value.abortController instanceof AbortController && this._value.abortController.signal.reason === s.abortedByLock) {
135
+ }).catch((n) => {
136
+ if (n instanceof h || n instanceof RangeError || n instanceof ReferenceError || n instanceof SyntaxError || n instanceof TypeError || n instanceof URIError || n instanceof EvalError)
137
+ throw n;
138
+ const m = x(n);
139
+ if (m && !this.is(s.possibleState.pending, s.possibleState.lock))
140
+ throw new R(this.name, this.state);
141
+ if (m && this._value.abortController instanceof AbortController && this._value.abortController.signal.reason === s.abortedByLock) {
135
142
  this.state = s.possibleState.lock, this._value = null;
136
143
  return;
137
144
  }
138
- if (S) {
145
+ if (m) {
139
146
  this.state = s.possibleState.abort;
140
147
  return;
141
148
  }
142
- this.setError(new O(this.name, { cause: a }));
149
+ this.setError(new P(this.name, { cause: n }));
143
150
  });
144
151
  return this._value = {
145
- promise: n,
146
- abortController: o
147
- }, n;
152
+ promise: o,
153
+ abortController: r
154
+ }, o;
148
155
  }
149
156
  // Returns same promise as exec method
150
157
  // but in reject state
@@ -157,7 +164,7 @@ const z = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
157
164
  }
158
165
  unlock() {
159
166
  if (!this.isLock)
160
- throw new b(
167
+ throw new d(
161
168
  this.name,
162
169
  this.state,
163
170
  s.possibleState.ready
@@ -166,7 +173,7 @@ const z = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
166
173
  }
167
174
  setError(t) {
168
175
  if (!this.isPending)
169
- throw new b(
176
+ throw new d(
170
177
  this.name,
171
178
  this.state,
172
179
  s.possibleState.error
@@ -178,39 +185,27 @@ const z = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
178
185
  }
179
186
  resetError() {
180
187
  if (!this.error)
181
- throw new b(
188
+ throw new d(
182
189
  this.name,
183
190
  this.state,
184
191
  s.possibleState.ready
185
192
  );
186
193
  return this.ready();
187
194
  }
188
- };
189
- i(s, "actionFlag", Symbol("__action_original_method__")), i(s, "possibleState", {
190
- pending: "pending",
191
- error: "error",
192
- lock: "lock",
193
- ready: "ready",
194
- abort: "abort"
195
- }), i(s, "abortedByLock", Symbol("lock"));
196
- let l = s;
197
- const d = Symbol("scope"), m = Symbol("model"), w = Symbol("actions"), y = Symbol("actionIds"), g = Symbol("actionStates"), A = Symbol("actionsSize"), p = Symbol("watchStopHandlers"), G = Proxy;
198
- var E, k, M, P, C, R, x;
199
- x = d, R = m, C = w, P = y, M = g, k = A, E = p;
200
- const f = class f {
201
- constructor() {
202
- // each model has its own effect scope to avoid memory leaks
203
- i(this, x, L(!0));
204
- i(this, R, null);
205
- // we use WeakMap to store actions as keys to avoid memory leaks
206
- i(this, C, /* @__PURE__ */ new WeakMap());
207
- i(this, P, /* @__PURE__ */ new WeakMap());
208
- i(this, M, /* @__PURE__ */ new Map());
209
- // WeakMap doesn't have a size property, so we need to store the size of the map
210
- i(this, k, 0);
211
- // watchers are stored in a set to avoid memory leaks
212
- i(this, E, /* @__PURE__ */ new Set());
213
- }
195
+ }
196
+ const l = /* @__PURE__ */ Symbol("scope"), p = /* @__PURE__ */ Symbol("model"), g = /* @__PURE__ */ Symbol("actions"), S = /* @__PURE__ */ Symbol("actionIds"), f = /* @__PURE__ */ Symbol("actionStates"), w = /* @__PURE__ */ Symbol("actionsSize"), u = /* @__PURE__ */ Symbol("watchStopHandlers"), F = Proxy;
197
+ class b {
198
+ // each model has its own effect scope to avoid memory leaks
199
+ [l] = A(!0);
200
+ [p] = null;
201
+ // we use WeakMap to store actions as keys to avoid memory leaks
202
+ [g] = /* @__PURE__ */ new WeakMap();
203
+ [S] = /* @__PURE__ */ new WeakMap();
204
+ [f] = /* @__PURE__ */ new Map();
205
+ // WeakMap doesn't have a size property, so we need to store the size of the map
206
+ [w] = 0;
207
+ // watchers are stored in a set to avoid memory leaks
208
+ [u] = /* @__PURE__ */ new Set();
214
209
  /**
215
210
  * Wraps ProtoModel instance with proxy to handle get traps for actions
216
211
  * and to return Action instance instead of original method.
@@ -236,18 +231,18 @@ const f = class f {
236
231
  * @returns model instance wrapped with proxy.
237
232
  */
238
233
  static createModel(t) {
239
- if (!(t instanceof f))
240
- throw new Error("ProtoModel instance is required");
241
- const e = new G(
242
- F(t),
234
+ if (!(t instanceof b))
235
+ throw new TypeError("ProtoModel instance is required");
236
+ const e = new F(
237
+ y(t),
243
238
  {
244
- get(o, c, h) {
245
- const n = Reflect.get(o, c, h), a = typeof n == "function";
246
- return a && l.actionFlag in n && typeof n[l.actionFlag] == "function" ? o.action(n) : a ? n.bind(o) : n;
239
+ get(r, i, c) {
240
+ const o = Reflect.get(r, i, c), n = typeof o == "function";
241
+ return n && s.actionFlag in o && typeof o[s.actionFlag] == "function" ? r.action(o) : n ? o.bind(r) : o;
247
242
  }
248
243
  }
249
244
  );
250
- return t[m] = e, e;
245
+ return t[p] = e, e;
251
246
  }
252
247
  /**
253
248
  * Creates a model instance.
@@ -256,16 +251,16 @@ const f = class f {
256
251
  * @returns model instance.
257
252
  */
258
253
  static model(...t) {
259
- if (this.prototype === f.prototype)
254
+ if (this.prototype === b.prototype)
260
255
  throw new Error("ProtoModel is abstract class and can not be instantiated");
261
256
  const e = new this(...t);
262
- return f.createModel(e);
257
+ return b.createModel(e);
263
258
  }
264
259
  get hasPendingActions() {
265
- return !!this.getActionStatesRef(l.possibleState.pending).value;
260
+ return !!this.getActionStatesRef(s.possibleState.pending).value;
266
261
  }
267
262
  get hasActionWithError() {
268
- return !!this.getActionStatesRef(l.possibleState.error).value;
263
+ return !!this.getActionStatesRef(s.possibleState.error).value;
269
264
  }
270
265
  /**
271
266
  * Registers watcher in the model effect scope.
@@ -326,38 +321,38 @@ const f = class f {
326
321
  watch(...t) {
327
322
  if (t.length === 0)
328
323
  throw new Error("watch requires at least one argument");
329
- const e = t.length === 1 ? this[d].run(() => B(t[0])) : this[d].run(() => D(...t));
324
+ const e = t.length === 1 ? this[l].run(() => E(t[0])) : this[l].run(() => k(...t));
330
325
  if (!e)
331
326
  throw new Error("watchStopHandler is undefined");
332
- return this[p].add(e), () => {
333
- e(), this[p].delete(e);
327
+ return this[u].add(e), () => {
328
+ e(), this[u].delete(e);
334
329
  };
335
330
  }
336
331
  computed(t, e) {
337
- return this[d].run(() => T(t, e));
332
+ return this[l].run(() => M(t, e));
338
333
  }
339
334
  // @see https://github.com/trekhleb/javascript-algorithms/blob/master/src/algorithms/math/bits/updateBit.js
340
- updateBit(t, e, o) {
341
- const c = o ? 1 : 0, h = ~(1 << e);
342
- return t & h | c << e;
335
+ updateBit(t, e, r) {
336
+ const i = r ? 1 : 0, c = ~(1 << e);
337
+ return t & c | i << e;
343
338
  }
344
339
  createAction(t) {
345
340
  const e = () => {
346
- if (!this[m])
341
+ if (!this[p])
347
342
  throw new Error("Model not set");
348
- return this[m];
349
- }, o = l.create(
343
+ return this[p];
344
+ }, r = s.create(
350
345
  this,
351
346
  t,
352
347
  e,
353
348
  this.setActionState.bind(this),
354
349
  this.validateArgs.bind(this)
355
350
  );
356
- return this[w].set(t, o), this[y].set(o, ++this[A]), this.setActionState(o), o;
351
+ return this[g].set(t, r), this[S].set(r, ++this[w]), this.setActionState(r), r;
357
352
  }
358
353
  getActionStatesRef(t) {
359
- const e = this[g].get(t) || H(0);
360
- return this[g].get(t) === void 0 && this[g].set(t, e), e;
354
+ const e = this[f].get(t) || C(0);
355
+ return this[f].get(t) === void 0 && this[f].set(t, e), e;
361
356
  }
362
357
  /**
363
358
  * Gets Action instance by wrapped original method or create Action instance.
@@ -403,9 +398,9 @@ const f = class f {
403
398
  * @returns action
404
399
  */
405
400
  action(t) {
406
- if (!(l.actionFlag in t && typeof t[l.actionFlag] == "function"))
407
- throw new u("Action decorator is not applied to the method");
408
- return this[w].get(t) || this.createAction(t);
401
+ if (!(s.actionFlag in t && typeof t[s.actionFlag] == "function"))
402
+ throw new h("Action decorator is not applied to the method");
403
+ return this[g].get(t) || this.createAction(t);
409
404
  }
410
405
  /**
411
406
  * It is public method in context ProtoModel,
@@ -414,29 +409,28 @@ const f = class f {
414
409
  * @see type Model<T>
415
410
  */
416
411
  setActionState(t) {
417
- const e = this[y].get(t);
412
+ const e = this[S].get(t);
418
413
  if (!e)
419
414
  throw new Error("Action not found");
420
- for (const o of t.possibleStates)
421
- o !== t.state && (this.getActionStatesRef(o).value = this.updateBit(this.getActionStatesRef(o).value, e, !1));
415
+ for (const r of t.possibleStates)
416
+ r !== t.state && (this.getActionStatesRef(r).value = this.updateBit(this.getActionStatesRef(r).value, e, !1));
422
417
  this.getActionStatesRef(t.state).value = this.updateBit(this.getActionStatesRef(t.state).value, e, !0);
423
418
  }
424
419
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
425
420
  validateArgs(t, ...e) {
426
- const o = `validateArgs is not implemented for action ${t.name} in the model`;
427
- return [new Error(o)];
421
+ const r = `validateArgs is not implemented for action ${t.name} in the model`;
422
+ return [new Error(r)];
428
423
  }
429
424
  isModelOf(t) {
430
425
  return this instanceof t;
431
426
  }
432
427
  destructor() {
433
- this[p].forEach((t) => {
428
+ this[u].forEach((t) => {
434
429
  t();
435
- }), this[p] = /* @__PURE__ */ new Set(), this[d].stop();
430
+ }), this[u] = /* @__PURE__ */ new Set(), this[l].stop();
436
431
  }
437
- };
438
- let v = f;
439
- function N(r, t) {
432
+ }
433
+ function K(a, t) {
440
434
  if (t.static)
441
435
  throw new Error("Action decorator is not supported for static methods");
442
436
  if (t.private)
@@ -444,26 +438,26 @@ function N(r, t) {
444
438
  let e;
445
439
  try {
446
440
  e = t.name.toString();
447
- } catch (c) {
448
- const n = `Invalid context. Can\`t get name of the method: ${c instanceof Error ? c.message : "unknown error"}`;
449
- throw new Error(n);
441
+ } catch (i) {
442
+ const o = `Invalid context. Can\`t get name of the method: ${i instanceof Error ? i.message : "unknown error"}`;
443
+ throw new Error(o);
450
444
  }
451
- const o = {
445
+ const r = {
452
446
  // Action constructor checks that model has method with the same name.
453
447
  // We can`t define anonymous function and change name because Function.name is readonly property.
454
448
  // So we need to create stub object to save original method name
455
- [e]: function(...c) {
456
- return this.action(o[e]).exec(...c);
449
+ [e]: function(...i) {
450
+ return this.action(r[e]).exec(...i);
457
451
  }
458
452
  };
459
- return o[e][l.actionFlag] = r, o[e];
453
+ return r[e][s.actionFlag] = a, r[e];
460
454
  }
461
455
  export {
462
- l as Action,
463
- O as ActionError,
464
- u as ActionInternalError,
465
- b as ActionStatusConflictError,
466
- j as ActionUnexpectedAbortError,
467
- v as ProtoModel,
468
- N as action
456
+ s as Action,
457
+ P as ActionError,
458
+ h as ActionInternalError,
459
+ d as ActionStatusConflictError,
460
+ R as ActionUnexpectedAbortError,
461
+ b as ProtoModel,
462
+ K as action
469
463
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@vue-modeler/model",
4
- "version": "2.2.0-beta.7",
4
+ "version": "2.2.5-beta.1",
5
5
  "description": "A state management library based on models for Vue.js",
6
6
  "author": "abratko",
7
7
  "license": "MIT",
@@ -21,30 +21,31 @@
21
21
  "access": "public"
22
22
  },
23
23
  "devDependencies": {
24
- "@eslint/js": "^9.23.0",
24
+ "@eslint/js": "^9.39.2",
25
25
  "@semantic-release/changelog": "^6.0.3",
26
26
  "@semantic-release/git": "^10.0.1",
27
- "@types/eslint__js": "^8.42.3",
28
- "@types/node": "^22.14.0",
29
- "@vitest/coverage-v8": "2.1.3",
30
- "@vue/test-utils": "^1.3.6",
27
+ "@types/node": "^25.0.3",
28
+ "@vitest/coverage-v8": "4.0.16",
29
+ "@vue/test-utils": "^2.4.6",
31
30
  "conventional-changelog-conventionalcommits": "^9.1.0",
32
- "eslint": "^9.23.0",
33
- "eslint-scope": "^8.3.0",
34
- "eslint-visitor-keys": "^4.2.0",
35
- "jsdom": "^25.0.1",
36
- "semantic-release": "^24.2.3",
37
- "typescript": "^5.8.2",
38
- "typescript-eslint": "^8.29.0",
39
- "vite": "^5.4.16",
40
- "vite-plugin-dts": "^4.5.3",
41
- "vitest": "^2.1.9"
31
+ "eslint": "^9.39.2",
32
+ "eslint-scope": "^9.0.0",
33
+ "eslint-visitor-keys": "^5.0.0",
34
+ "jsdom": "^27.4.0",
35
+ "semantic-release": "^25.0.2",
36
+ "typescript": "^5.9.3",
37
+ "typescript-eslint": "^8.51.0",
38
+ "vite": "^7.3.0",
39
+ "vite-plugin-dts": "^4.5.4",
40
+ "vitest": "^4.0.16",
41
+ "vue": ">=2.7 <4.0.0"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "vue": ">=2.7 <4.0.0"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "tsc && vite build",
48
+ "lint": "eslint .",
48
49
  "test": "tsc --noEmit && vitest",
49
50
  "coverage": "vitest run --coverage",
50
51
  "semantic-release": "semantic-release"