@vue-modeler/model 1.0.7 → 2.0.1-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/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var m=Object.defineProperty;var A=(s,t,e)=>t in s?m(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var i=(s,t,e)=>A(s,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("vue");var _=Object.defineProperty,E=(s,t,e)=>t in s?_(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e,p=(s,t,e)=>E(s,typeof t!="symbol"?t+"":t,e);function I(){var s;const t=(s=h.getCurrentInstance())==null?void 0:s.proxy;if(!t)throw new Error("Current instance is undefined");if(!t.$vueModelerDc)throw new Error("Dependency container undefined. Check plugin setup");return t.$vueModelerDc}function g(s,t={persistentInstance:!1}){const e=Symbol("provider"),o=()=>{const a=I(),n=a.get(e)||a.add(e,s);return t.persistentInstance||(n.subscribeOnParentScopeDispose(h.onScopeDispose),h.onScopeDispose(()=>{n.parentScopeCount>0||a.delete(e)})),n.instance};return o.__isProvider__=!0,Object.defineProperty(o,"asKey",{value:e,writable:!1}),o}class P{constructor(){p(this,"isServer",!0),p(this,"stateKey","__SSR_STATE__"),p(this,"serializers",new Set),p(this,"stateFromServer",{}),this.isServer=typeof window>"u",this.initStateFromServer()}initStateFromServer(){if(this.isServer||!globalThis.__INITIAL_STATE__)return;const t=typeof globalThis.__INITIAL_STATE__=="string"?JSON.parse(globalThis.__INITIAL_STATE__):globalThis.__INITIAL_STATE__;typeof t[this.stateKey]=="object"&&(this.stateFromServer=t[this.stateKey])}extractState(t){return this.stateFromServer[t]}addSerializer(t){return this.isServer&&this.serializers.add(t),t}removeSerializer(t){return this.isServer?this.serializers.delete(t):!1}serialize(){const t={};for(const e of this.serializers){const o=e();o.value!==void 0&&(t[o.extractionKey]=o.value)}return t}injectState(t){this.isServer&&(t[this.stateKey]=this.serialize())}}g(()=>new P);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 d extends u{constructor(t,e,o){super(`Trying to update state of ${t} from ${e} to ${o}`),this.name=this.constructor.name}}class v extends u{constructor(t,e){super(`Unexpected AbortError for the action ${t} in state ${e}`),this.name=this.constructor.name}}const T=s=>s instanceof DOMException&&s.name==="AbortError"||typeof s=="object"&&s!==null&&"message"in s&&s.message==="canceled",r=class r{constructor(t,e){i(this,"name");i(this,"_state",r.possibleState.ready);i(this,"_value",null);i(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[r.actionFlag]!="function")throw new u(`Method ${o} is not action`);this.name=o}toString(){return this.name}get possibleStates(){return Object.values(r.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===r.possibleState.pending}get isError(){return this.state===r.possibleState.error}get isReady(){return this.state===r.possibleState.ready}get isLock(){return this.state===r.possibleState.lock}get isAbort(){return this.state===r.possibleState.abort}is(...t){return!!t.find(e=>this.state===e)}exec(...t){if(this.is(r.possibleState.lock,r.possibleState.pending))throw new d(this.name,this.state,r.possibleState.pending);const e=[...t];let o=t.length&&t[t.length-1];o instanceof AbortController||(o=new AbortController,e.push(o)),this.state=r.possibleState.pending,this._args=t;const n=this.actionFunction[r.actionFlag].apply(this.model,e);if(!(n instanceof Promise))return this.state=r.possibleState.ready,Promise.resolve(n);const f=n.then(()=>{this.ready()}).catch(c=>{if(c instanceof u||c instanceof RangeError||c instanceof ReferenceError||c instanceof SyntaxError||c instanceof TypeError||c instanceof URIError||c instanceof EvalError)throw c;const S=T(c);if(S&&!this.is(r.possibleState.pending,r.possibleState.lock))throw new v(this.name,this.state);if(S&&this._value.abortController instanceof AbortController&&this._value.abortController.signal.reason===r.abortedByLock){this.state=r.possibleState.lock,this._value=null;return}if(S){this.state=r.possibleState.abort;return}this.setError(new w(this.name,{cause:c}))});return this._value={promise:f,abortController:o},f}abort(t){return this.isPending?(this._value.abortController.abort(t),this._value.promise):Promise.resolve()}lock(){return this.isPending?this.abort(r.abortedByLock):(this.state=r.possibleState.lock,this._value=null,Promise.resolve())}unlock(){if(!this.isLock)throw new d(this.name,this.state,r.possibleState.ready);return this.ready()}setError(t){if(!this.isPending)throw new d(this.name,this.state,r.possibleState.error);return this.state=r.possibleState.error,this._value=t,this}ready(){return this.state=r.possibleState.ready,this}resetError(){if(!this.error)throw new d(this.name,this.state,r.possibleState.ready);return this.ready()}};i(r,"actionFlag",Symbol("__action_original_method__")),i(r,"possibleState",{pending:"pending",error:"error",lock:"lock",ready:"ready",abort:"abort"}),i(r,"abortedByLock",Symbol("lock"));let l=r;class b{constructor(){i(this,"_effectScope",h.effectScope(!0));i(this,"_actions",new WeakMap);i(this,"_actionIds",new WeakMap);i(this,"_actionStates",new Map);i(this,"_actionsSize",0);i(this,"_unwatchers",new Set)}get hasPendingActions(){return!!this.getActionStatesRef(l.possibleState.pending).value}get hasActionWithError(){return!!this.getActionStatesRef(l.possibleState.error).value}watch(...t){const e=this._effectScope.run(()=>h.watch(...t));if(!e)throw new Error("watchStopHandler is undefined");return this._unwatchers.add(e),e}computed(t,e){return this._effectScope.run(()=>h.computed(t,e))}updateBit(t,e,o){const a=o?1:0,n=~(1<<e);return t&n|a<<e}createAction(t){const e=h.shallowReactive(new l(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)||h.ref(0);return this._actionStates.get(t)===void 0&&this._actionStates.set(t,e),e}action(t){if(!(l.actionFlag in t&&typeof t[l.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._unwatchers.forEach(t=>{t()}),this._unwatchers=new Set,this._effectScope.stop()}}const k=Proxy;function y(s){if(!(s instanceof b))throw new Error("ProtoModel instance is required");return new k(h.shallowReactive(s),{get(e,o,a){const n=Reflect.get(e,o,a),f=typeof n=="function";return f&&l.actionFlag in n&&typeof n[l.actionFlag]=="function"?e.action(n):f?n.bind(e):n}})}function M(s,t){return g(()=>y(s()),t)}const C=(s,t,e)=>{if(typeof t!="string")throw new Error("Action name is not a string");if(typeof e.value!="function")throw new Error("Property value is not a function");if(!(s instanceof b))throw new Error("Target is not instance of ProtoModel");const o=e.value,a={[t]:function(...n){return this.action(a[t]).exec(...n)}};a[t][l.actionFlag]=o,e.value=a[t]};exports.ActionError=w;exports.ActionInternalError=u;exports.ActionStatusConflictError=d;exports.ActionUnexpectedAbortError=v;exports.ProtoModel=b;exports.action=C;exports.createModel=y;exports.model=M;
1
+ "use strict";var g=Object.defineProperty;var m=(r,t,e)=>t in r?g(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var n=(r,t,e)=>m(r,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("vue");class S 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 w extends u{constructor(t,e){super(`Unexpected AbortError for the action ${t} in state ${e}`),this.name=this.constructor.name}}const A=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 b=A(a);if(b&&!this.is(s.possibleState.pending,s.possibleState.lock))throw new w(this.name,this.state);if(b&&this._value.abortController instanceof AbortController&&this._value.abortController.signal.reason===s.abortedByLock){this.state=s.possibleState.lock,this._value=null;return}if(b){this.state=s.possibleState.abort;return}this.setError(new S(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 y=Proxy;function v(r){if(!(r instanceof f))throw new Error("ProtoModel instance is required");return new y(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}})}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 v(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}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()}}function E(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=S;exports.ActionInternalError=u;exports.ActionStatusConflictError=p;exports.ActionUnexpectedAbortError=w;exports.ProtoModel=f;exports.action=E;
package/dist/index.d.ts CHANGED
@@ -2,8 +2,6 @@ import { ComputedGetter } from 'vue';
2
2
  import { ComputedRef } from 'vue';
3
3
  import { DebuggerOptions } from 'vue';
4
4
  import { EffectScope } from 'vue';
5
- import { Provider } from '@vue-modeler/dc';
6
- import { ProviderOptions } from '@vue-modeler/dc';
7
5
  import { Ref } from 'vue';
8
6
  import { ShallowReactive } from 'vue';
9
7
  import { WatchStopHandle } from 'vue';
@@ -53,7 +51,7 @@ declare class Action<Args extends any[] = unknown[]> {
53
51
  resetError(): this;
54
52
  }
55
53
 
56
- export declare const action: MethodDecorator;
54
+ export declare function action<T extends ProtoModel, Args extends unknown[]>(originalMethod: (this: T, ...args: Args) => Promise<void>, context: ClassMethodDecoratorContext<T, (this: T, ...args: Args) => Promise<void>>): OriginalMethodWrapper<Args>;
57
55
 
58
56
  /**
59
57
  * IMPORTANT: this class looks like error,
@@ -112,24 +110,20 @@ export declare class ActionUnexpectedAbortError extends ActionInternalError {
112
110
 
113
111
  declare type ActionValue = ActionPendingValue | ActionError | null;
114
112
 
115
- export declare function createModel<Target extends ProtoModel>(protoModel: Target): Model<Target>;
116
-
117
113
  export declare type Model<T> = {
118
114
  [K in keyof T]: T[K] extends ((...args: infer Args) => Promise<void>) ? Action<Args> : K extends ProtectedMethodInModel ? never : T[K];
119
115
  };
120
116
 
121
- export declare function model<T extends ProtoModel>(modelFactory: () => T, options?: ProviderOptions): Provider<Model<T>>;
122
-
123
117
  export declare type ModelAdapterProxyConstructor = new <Target extends ProtoModel>(target: Target, handler: ProxyHandler<Target>) => Model<Target>;
124
118
 
125
119
  export declare type ModelConstructor<T extends new (...args: unknown[]) => unknown> = T extends new (...args: unknown[]) => infer R ? R extends ProtoModel ? T : never : never;
126
120
 
127
121
  declare type ModelConstructor_2 = new (...args: any[]) => ProtoModel;
128
122
 
129
- export declare type OriginalMethod<Args extends unknown[] = unknown[]> = (...args: Args) => void | Promise<void>;
123
+ export declare type OriginalMethod = (...args: any[]) => Promise<void>;
130
124
 
131
125
  export declare interface OriginalMethodWrapper<Args extends unknown[] = unknown[]> {
132
- (...args: Args): void | Promise<void>;
126
+ (...args: Args): Promise<void>;
133
127
  [Action.actionFlag]: OriginalMethod;
134
128
  }
135
129
 
@@ -139,11 +133,75 @@ export declare abstract class ProtoModel {
139
133
  protected _effectScope: EffectScope;
140
134
  protected _actions: WeakMap<OriginalMethodWrapper<unknown[]>, ShallowReactive<ActionPublic>>;
141
135
  protected _actionIds: WeakMap<ShallowReactive<ActionPublic>, number>;
142
- protected _actionStates: Map<"pending" | "error" | "lock" | "ready" | "abort", Ref<number>>;
136
+ protected _actionStates: Map<"error" | "abort" | "lock" | "pending" | "ready", Ref<number>>;
143
137
  protected _actionsSize: number;
144
- protected _unwatchers: Set<WatchStopHandle>;
138
+ protected _watchStopHandlers: Set<WatchStopHandle>;
139
+ /**
140
+ * Creates a model instance.
141
+ *
142
+ * @param args - arguments for the model constructor.
143
+ * @returns model instance.
144
+ * @see src/create-model.ts
145
+ */
146
+ static model<T extends ProtoModel, Args extends unknown[]>(this: new (...args: Args) => T, ...args: Args): Model<T>;
145
147
  get hasPendingActions(): boolean;
146
148
  get hasActionWithError(): boolean;
149
+ /**
150
+ * Registers watcher in the model effect scope.
151
+ * It uses "watch" or "watchEffect" function from Vue.
152
+ *
153
+ * It has restrictions. It can't be used with own not reactive properties.
154
+ * This is because `this` in inner context is not shallow reactive.
155
+ *
156
+ * Example with error:
157
+ *
158
+ * ```ts
159
+ * class TestModel extends ProtoModel {
160
+ * protected _someProperty: string = ''
161
+ *
162
+ * constructor () {
163
+ * super()
164
+ *
165
+ * // This watcher will not work because
166
+ * // `this` and `this.someProperty`
167
+ * // are not reactive
168
+ * this.watch(
169
+ * () => this.someProperty,
170
+ * (value: string) => {
171
+ * console.log(value)
172
+ * }
173
+ * )
174
+ * }
175
+ *
176
+ * get someProperty(): string {
177
+ * return this._someProperty
178
+ * }
179
+ * }
180
+ *
181
+ * To watch for own properties you need to define it as reactive property
182
+ * with ref or this.computed.
183
+ *
184
+ * ```ts
185
+ * class TestModel extends ProtoModel {
186
+ * protected _someProperty = ref('')
187
+ *
188
+ * constructor () {
189
+ * super()
190
+ *
191
+ * // This watcher will work because `this._someProperty` is reactive
192
+ * this.watch(
193
+ * () => this._someProperty.value,
194
+ * (value: string) => {
195
+ * console.log(value)
196
+ * }
197
+ * )
198
+ * }
199
+ * }
200
+ * ```
201
+ *
202
+ * @param args - arguments for "watch" or "watchEffect" function.
203
+ * @see src/create-model.ts
204
+ */
147
205
  protected watch(...args: unknown[]): WatchStopHandle;
148
206
  protected computed<T>(getter: ComputedGetter<T>, debugOptions?: DebuggerOptions): ComputedRef<T>;
149
207
  protected updateBit(number: number, bitPosition: number, bitValue: boolean): number;
@@ -154,6 +212,7 @@ export declare abstract class ProtoModel {
154
212
  *
155
213
  * From external context of model this method is implicitly used to get or create an action.
156
214
  * It called inside get hook proxy of action.
215
+ * @see src/create-model.ts
157
216
  *
158
217
  * ```ts
159
218
  * class TestModel extends ProtoModel {
@@ -167,9 +226,10 @@ export declare abstract class ProtoModel {
167
226
  *
168
227
  * In internal context of model this method is used to get Action instance.
169
228
  * You can`t call it as `testModel.testAction.exec()` or `testModel.testAction.isPending` etc.
170
- * because TypeScript sees it as standard method of model instance and you will get error about type.
229
+ * because TypeScript sees it as standard method of the class and you will get error about type.
171
230
  *
172
- * To get Action instance in internal context of model you need to call it as `testModel.action(testModel.testAction)`
231
+ * To get Action instance in internal context of model
232
+ * you need to call it as `testModel.action(testModel.testAction)`
173
233
  *
174
234
  * ```ts
175
235
  * class TestModel extends ProtoModel {
package/dist/index.js CHANGED
@@ -1,66 +1,8 @@
1
- var v = Object.defineProperty;
2
- var m = (s, t, e) => t in s ? v(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
3
- var n = (s, t, e) => m(s, typeof t != "symbol" ? t + "" : t, e);
4
- import { onScopeDispose as S, getCurrentInstance as y, effectScope as A, watch as _, computed as I, shallowReactive as b, ref as T } from "vue";
5
- var E = Object.defineProperty, P = (s, t, e) => t in s ? E(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e, f = (s, t, e) => P(s, typeof t != "symbol" ? t + "" : t, e);
6
- function k() {
7
- var s;
8
- const t = (s = y()) == null ? void 0 : s.proxy;
9
- if (!t)
10
- throw new Error("Current instance is undefined");
11
- if (!t.$vueModelerDc)
12
- throw new Error("Dependency container undefined. Check plugin setup");
13
- return t.$vueModelerDc;
14
- }
15
- function g(s, t = { persistentInstance: !1 }) {
16
- const e = Symbol("provider"), o = () => {
17
- const a = k(), i = a.get(e) || a.add(e, s);
18
- return t.persistentInstance || (i.subscribeOnParentScopeDispose(S), S(() => {
19
- i.parentScopeCount > 0 || a.delete(e);
20
- })), i.instance;
21
- };
22
- return o.__isProvider__ = !0, Object.defineProperty(
23
- o,
24
- "asKey",
25
- {
26
- value: e,
27
- writable: !1
28
- }
29
- ), o;
30
- }
31
- class M {
32
- constructor() {
33
- f(this, "isServer", !0), f(this, "stateKey", "__SSR_STATE__"), f(this, "serializers", /* @__PURE__ */ new Set()), f(this, "stateFromServer", {}), this.isServer = typeof window > "u", this.initStateFromServer();
34
- }
35
- initStateFromServer() {
36
- if (this.isServer || !globalThis.__INITIAL_STATE__)
37
- return;
38
- const t = typeof globalThis.__INITIAL_STATE__ == "string" ? JSON.parse(globalThis.__INITIAL_STATE__) : globalThis.__INITIAL_STATE__;
39
- typeof t[this.stateKey] == "object" && (this.stateFromServer = t[this.stateKey]);
40
- }
41
- extractState(t) {
42
- return this.stateFromServer[t];
43
- }
44
- addSerializer(t) {
45
- return this.isServer && this.serializers.add(t), t;
46
- }
47
- removeSerializer(t) {
48
- return this.isServer ? this.serializers.delete(t) : !1;
49
- }
50
- serialize() {
51
- const t = {};
52
- for (const e of this.serializers) {
53
- const o = e();
54
- o.value !== void 0 && (t[o.extractionKey] = o.value);
55
- }
56
- return t;
57
- }
58
- injectState(t) {
59
- this.isServer && (t[this.stateKey] = this.serialize());
60
- }
61
- }
62
- g(() => new M());
63
- class x extends Error {
1
+ var S = Object.defineProperty;
2
+ var w = (r, t, e) => t in r ? S(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
+ var n = (r, t, e) => w(r, typeof t != "symbol" ? t + "" : t, e);
4
+ import { shallowReactive as b, effectScope as m, watchEffect as g, watch as A, computed as y, ref as v } from "vue";
5
+ class k extends Error {
64
6
  constructor(t, e) {
65
7
  super(e.cause.message), this.actionName = t, this.options = e, this.name = this.constructor.name;
66
8
  }
@@ -74,40 +16,40 @@ class x extends Error {
74
16
  return this.options.cause.message;
75
17
  }
76
18
  }
77
- class h extends Error {
19
+ class l extends Error {
78
20
  constructor(t, e) {
79
21
  super(t, e), this.message = t, this.options = e, this.name = this.constructor.name;
80
22
  }
81
23
  }
82
- class d extends h {
24
+ class p extends l {
83
25
  constructor(t, e, o) {
84
26
  super(`Trying to update state of ${t} from ${e} to ${o}`), this.name = this.constructor.name;
85
27
  }
86
28
  }
87
- class C extends h {
29
+ class E extends l {
88
30
  constructor(t, e) {
89
31
  super(`Unexpected AbortError for the action ${t} in state ${e}`), this.name = this.constructor.name;
90
32
  }
91
33
  }
92
- const F = (s) => s instanceof DOMException && s.name === "AbortError" || typeof s == "object" && s !== null && "message" in s && s.message === "canceled", r = class r {
34
+ const P = (r) => r instanceof DOMException && r.name === "AbortError" || typeof r == "object" && r !== null && "message" in r && r.message === "canceled", s = class s {
93
35
  constructor(t, e) {
94
36
  n(this, "name");
95
- n(this, "_state", r.possibleState.ready);
37
+ n(this, "_state", s.possibleState.ready);
96
38
  n(this, "_value", null);
97
39
  n(this, "_args", null);
98
40
  this.model = t, this.actionFunction = e;
99
41
  const o = e.name;
100
42
  if (!(o in t && typeof t[o] == "function"))
101
- throw new h(`Model does not contain method ${o}`);
102
- if (typeof e[r.actionFlag] != "function")
103
- throw new h(`Method ${o} is not action`);
43
+ throw new l(`Model does not contain method ${o}`);
44
+ if (typeof e[s.actionFlag] != "function")
45
+ throw new l(`Method ${o} is not action`);
104
46
  this.name = o;
105
47
  }
106
48
  toString() {
107
49
  return this.name;
108
50
  }
109
51
  get possibleStates() {
110
- return Object.values(r.possibleState);
52
+ return Object.values(s.possibleState);
111
53
  }
112
54
  get state() {
113
55
  return this._state;
@@ -132,19 +74,19 @@ const F = (s) => s instanceof DOMException && s.name === "AbortError" || typeof
132
74
  return this.isAbort ? this._value.abortController.signal.reason : null;
133
75
  }
134
76
  get isPending() {
135
- return this.state === r.possibleState.pending;
77
+ return this.state === s.possibleState.pending;
136
78
  }
137
79
  get isError() {
138
- return this.state === r.possibleState.error;
80
+ return this.state === s.possibleState.error;
139
81
  }
140
82
  get isReady() {
141
- return this.state === r.possibleState.ready;
83
+ return this.state === s.possibleState.ready;
142
84
  }
143
85
  get isLock() {
144
- return this.state === r.possibleState.lock;
86
+ return this.state === s.possibleState.lock;
145
87
  }
146
88
  get isAbort() {
147
- return this.state === r.possibleState.abort;
89
+ return this.state === s.possibleState.abort;
148
90
  }
149
91
  is(...t) {
150
92
  return !!t.find((e) => this.state === e);
@@ -153,35 +95,35 @@ const F = (s) => s instanceof DOMException && s.name === "AbortError" || typeof
153
95
  * Put into action in PENDING state
154
96
  */
155
97
  exec(...t) {
156
- if (this.is(r.possibleState.lock, r.possibleState.pending))
157
- throw new d(
98
+ if (this.is(s.possibleState.lock, s.possibleState.pending))
99
+ throw new p(
158
100
  this.name,
159
101
  this.state,
160
- r.possibleState.pending
102
+ s.possibleState.pending
161
103
  );
162
104
  const e = [...t];
163
105
  let o = t.length && t[t.length - 1];
164
- o instanceof AbortController || (o = new AbortController(), e.push(o)), this.state = r.possibleState.pending, this._args = t;
165
- const i = this.actionFunction[r.actionFlag].apply(this.model, e);
106
+ 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);
166
108
  if (!(i instanceof Promise))
167
- return this.state = r.possibleState.ready, Promise.resolve(i);
109
+ return this.state = s.possibleState.ready, Promise.resolve();
168
110
  const u = i.then(() => {
169
111
  this.ready();
170
- }).catch((c) => {
171
- if (c instanceof h || c instanceof RangeError || c instanceof ReferenceError || c instanceof SyntaxError || c instanceof TypeError || c instanceof URIError || c instanceof EvalError)
172
- throw c;
173
- const p = F(c);
174
- if (p && !this.is(r.possibleState.pending, r.possibleState.lock))
175
- throw new C(this.name, this.state);
176
- if (p && this._value.abortController instanceof AbortController && this._value.abortController.signal.reason === r.abortedByLock) {
177
- this.state = r.possibleState.lock, this._value = null;
112
+ }).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)
114
+ throw a;
115
+ const d = P(a);
116
+ if (d && !this.is(s.possibleState.pending, s.possibleState.lock))
117
+ throw new E(this.name, this.state);
118
+ if (d && this._value.abortController instanceof AbortController && this._value.abortController.signal.reason === s.abortedByLock) {
119
+ this.state = s.possibleState.lock, this._value = null;
178
120
  return;
179
121
  }
180
- if (p) {
181
- this.state = r.possibleState.abort;
122
+ if (d) {
123
+ this.state = s.possibleState.abort;
182
124
  return;
183
125
  }
184
- this.setError(new x(this.name, { cause: c }));
126
+ this.setError(new k(this.name, { cause: a }));
185
127
  });
186
128
  return this._value = {
187
129
  promise: u,
@@ -195,51 +137,65 @@ const F = (s) => s instanceof DOMException && s.name === "AbortError" || typeof
195
137
  return this.isPending ? (this._value.abortController.abort(t), this._value.promise) : Promise.resolve();
196
138
  }
197
139
  lock() {
198
- return this.isPending ? this.abort(r.abortedByLock) : (this.state = r.possibleState.lock, this._value = null, Promise.resolve());
140
+ return this.isPending ? this.abort(s.abortedByLock) : (this.state = s.possibleState.lock, this._value = null, Promise.resolve());
199
141
  }
200
142
  unlock() {
201
143
  if (!this.isLock)
202
- throw new d(
144
+ throw new p(
203
145
  this.name,
204
146
  this.state,
205
- r.possibleState.ready
147
+ s.possibleState.ready
206
148
  );
207
149
  return this.ready();
208
150
  }
209
151
  setError(t) {
210
152
  if (!this.isPending)
211
- throw new d(
153
+ throw new p(
212
154
  this.name,
213
155
  this.state,
214
- r.possibleState.error
156
+ s.possibleState.error
215
157
  );
216
- return this.state = r.possibleState.error, this._value = t, this;
158
+ return this.state = s.possibleState.error, this._value = t, this;
217
159
  }
218
160
  ready() {
219
- return this.state = r.possibleState.ready, this;
161
+ return this.state = s.possibleState.ready, this;
220
162
  }
221
163
  resetError() {
222
164
  if (!this.error)
223
- throw new d(
165
+ throw new p(
224
166
  this.name,
225
167
  this.state,
226
- r.possibleState.ready
168
+ s.possibleState.ready
227
169
  );
228
170
  return this.ready();
229
171
  }
230
172
  };
231
- n(r, "actionFlag", Symbol("__action_original_method__")), n(r, "possibleState", {
173
+ n(s, "actionFlag", Symbol("__action_original_method__")), n(s, "possibleState", {
232
174
  pending: "pending",
233
175
  error: "error",
234
176
  lock: "lock",
235
177
  ready: "ready",
236
178
  abort: "abort"
237
- }), n(r, "abortedByLock", Symbol("lock"));
238
- let l = r;
239
- class w {
179
+ }), n(s, "abortedByLock", Symbol("lock"));
180
+ let c = s;
181
+ const _ = Proxy;
182
+ function M(r) {
183
+ if (!(r instanceof f))
184
+ throw new Error("ProtoModel instance is required");
185
+ return new _(
186
+ b(r),
187
+ {
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;
191
+ }
192
+ }
193
+ );
194
+ }
195
+ class f {
240
196
  constructor() {
241
197
  // each model has its own effect scope to avoid memory leaks
242
- n(this, "_effectScope", A(!0));
198
+ n(this, "_effectScope", m(!0));
243
199
  // we use WeakMap to store actions as keys to avoid memory leaks
244
200
  n(this, "_actions", /* @__PURE__ */ new WeakMap());
245
201
  n(this, "_actionIds", /* @__PURE__ */ new WeakMap());
@@ -247,34 +203,105 @@ class w {
247
203
  // WeakMap doesn't have a size property, so we need to store the size of the map
248
204
  n(this, "_actionsSize", 0);
249
205
  // watchers are stored in a set to avoid memory leaks
250
- n(this, "_unwatchers", /* @__PURE__ */ new Set());
206
+ n(this, "_watchStopHandlers", /* @__PURE__ */ new Set());
207
+ }
208
+ /**
209
+ * Creates a model instance.
210
+ *
211
+ * @param args - arguments for the model constructor.
212
+ * @returns model instance.
213
+ * @see src/create-model.ts
214
+ */
215
+ static model(...t) {
216
+ if (this.prototype === f.prototype)
217
+ throw new Error("ProtoModel is abstract class and can not be instantiated");
218
+ const e = new this(...t);
219
+ return M(e);
251
220
  }
252
221
  get hasPendingActions() {
253
- return !!this.getActionStatesRef(l.possibleState.pending).value;
222
+ return !!this.getActionStatesRef(c.possibleState.pending).value;
254
223
  }
255
224
  get hasActionWithError() {
256
- return !!this.getActionStatesRef(l.possibleState.error).value;
225
+ return !!this.getActionStatesRef(c.possibleState.error).value;
257
226
  }
227
+ /**
228
+ * Registers watcher in the model effect scope.
229
+ * It uses "watch" or "watchEffect" function from Vue.
230
+ *
231
+ * It has restrictions. It can't be used with own not reactive properties.
232
+ * This is because `this` in inner context is not shallow reactive.
233
+ *
234
+ * Example with error:
235
+ *
236
+ * ```ts
237
+ * class TestModel extends ProtoModel {
238
+ * protected _someProperty: string = ''
239
+ *
240
+ * constructor () {
241
+ * super()
242
+ *
243
+ * // This watcher will not work because
244
+ * // `this` and `this.someProperty`
245
+ * // are not reactive
246
+ * this.watch(
247
+ * () => this.someProperty,
248
+ * (value: string) => {
249
+ * console.log(value)
250
+ * }
251
+ * )
252
+ * }
253
+ *
254
+ * get someProperty(): string {
255
+ * return this._someProperty
256
+ * }
257
+ * }
258
+ *
259
+ * To watch for own properties you need to define it as reactive property
260
+ * with ref or this.computed.
261
+ *
262
+ * ```ts
263
+ * class TestModel extends ProtoModel {
264
+ * protected _someProperty = ref('')
265
+ *
266
+ * constructor () {
267
+ * super()
268
+ *
269
+ * // This watcher will work because `this._someProperty` is reactive
270
+ * this.watch(
271
+ * () => this._someProperty.value,
272
+ * (value: string) => {
273
+ * console.log(value)
274
+ * }
275
+ * )
276
+ * }
277
+ * }
278
+ * ```
279
+ *
280
+ * @param args - arguments for "watch" or "watchEffect" function.
281
+ * @see src/create-model.ts
282
+ */
258
283
  watch(...t) {
259
- const e = this._effectScope.run(() => _(...t));
284
+ if (t.length === 0)
285
+ throw new Error("watch requires at least one argument");
286
+ const e = t.length === 1 ? this._effectScope.run(() => g(t[0])) : this._effectScope.run(() => A(...t));
260
287
  if (!e)
261
288
  throw new Error("watchStopHandler is undefined");
262
- return this._unwatchers.add(e), e;
289
+ return this._watchStopHandlers.add(e), e;
263
290
  }
264
291
  computed(t, e) {
265
- return this._effectScope.run(() => I(t, e));
292
+ return this._effectScope.run(() => y(t, e));
266
293
  }
267
294
  // @see https://github.com/trekhleb/javascript-algorithms/blob/master/src/algorithms/math/bits/updateBit.js
268
295
  updateBit(t, e, o) {
269
- const a = o ? 1 : 0, i = ~(1 << e);
270
- return t & i | a << e;
296
+ const h = o ? 1 : 0, i = ~(1 << e);
297
+ return t & i | h << e;
271
298
  }
272
299
  createAction(t) {
273
- const e = b(new l(this, t));
300
+ const e = b(new c(this, t));
274
301
  return this._actions.set(t, e), this._actionIds.set(e, ++this._actionsSize), this.setActionState(e), e;
275
302
  }
276
303
  getActionStatesRef(t) {
277
- const e = this._actionStates.get(t) || T(0);
304
+ const e = this._actionStates.get(t) || v(0);
278
305
  return this._actionStates.get(t) === void 0 && this._actionStates.set(t, e), e;
279
306
  }
280
307
  /**
@@ -282,6 +309,7 @@ class w {
282
309
  *
283
310
  * From external context of model this method is implicitly used to get or create an action.
284
311
  * It called inside get hook proxy of action.
312
+ * @see src/create-model.ts
285
313
  *
286
314
  * ```ts
287
315
  * class TestModel extends ProtoModel {
@@ -295,9 +323,10 @@ class w {
295
323
  *
296
324
  * In internal context of model this method is used to get Action instance.
297
325
  * You can`t call it as `testModel.testAction.exec()` or `testModel.testAction.isPending` etc.
298
- * because TypeScript sees it as standard method of model instance and you will get error about type.
326
+ * because TypeScript sees it as standard method of the class and you will get error about type.
299
327
  *
300
- * To get Action instance in internal context of model you need to call it as `testModel.action(testModel.testAction)`
328
+ * To get Action instance in internal context of model
329
+ * you need to call it as `testModel.action(testModel.testAction)`
301
330
  *
302
331
  * ```ts
303
332
  * class TestModel extends ProtoModel {
@@ -319,8 +348,8 @@ class w {
319
348
  * @returns action
320
349
  */
321
350
  action(t) {
322
- if (!(l.actionFlag in t && typeof t[l.actionFlag] == "function"))
323
- throw new h("Action decorator is not applied to the method");
351
+ if (!(c.actionFlag in t && typeof t[c.actionFlag] == "function"))
352
+ throw new l("Action decorator is not applied to the method");
324
353
  return this._actions.get(t) || this.createAction(t);
325
354
  }
326
355
  /**
@@ -341,52 +370,31 @@ class w {
341
370
  return this instanceof t;
342
371
  }
343
372
  destructor() {
344
- this._unwatchers.forEach((t) => {
373
+ this._watchStopHandlers.forEach((t) => {
345
374
  t();
346
- }), this._unwatchers = /* @__PURE__ */ new Set(), this._effectScope.stop();
375
+ }), this._watchStopHandlers = /* @__PURE__ */ new Set(), this._effectScope.stop();
347
376
  }
348
377
  }
349
- const R = Proxy;
350
- function z(s) {
351
- if (!(s instanceof w))
352
- throw new Error("ProtoModel instance is required");
353
- return new R(
354
- b(s),
355
- {
356
- get(e, o, a) {
357
- const i = Reflect.get(e, o, a), u = typeof i == "function";
358
- return u && l.actionFlag in i && typeof i[l.actionFlag] == "function" ? e.action(i) : u ? i.bind(e) : i;
359
- }
360
- }
361
- );
362
- }
363
- function j(s, t) {
364
- return g(() => z(s()), t);
365
- }
366
- const B = (s, t, e) => {
367
- if (typeof t != "string")
368
- throw new Error("Action name is not a string");
369
- if (typeof e.value != "function")
370
- throw new Error("Property value is not a function");
371
- if (!(s instanceof w))
372
- throw new Error("Target is not instance of ProtoModel");
373
- const o = e.value, a = {
378
+ function I(r, t) {
379
+ if (t.static)
380
+ throw new Error("Action decorator is not supported for static methods");
381
+ if (t.private)
382
+ throw new Error("Action decorator is not supported for private methods");
383
+ const e = t.name.toString(), o = {
374
384
  // Action constructor checks that model has method with the same name.
375
385
  // We can`t define anonymous function and change name because Function.name is readonly property.
376
386
  // So we need to create stub object to save original method name
377
- [t]: function(...i) {
378
- return this.action(a[t]).exec(...i);
387
+ [e]: function(...h) {
388
+ return this.action(o[e]).exec(...h);
379
389
  }
380
390
  };
381
- a[t][l.actionFlag] = o, e.value = a[t];
382
- };
391
+ return o[e][c.actionFlag] = r, o[e];
392
+ }
383
393
  export {
384
- x as ActionError,
385
- h as ActionInternalError,
386
- d as ActionStatusConflictError,
387
- C as ActionUnexpectedAbortError,
388
- w as ProtoModel,
389
- B as action,
390
- z as createModel,
391
- j as model
394
+ k as ActionError,
395
+ l as ActionInternalError,
396
+ p as ActionStatusConflictError,
397
+ E as ActionUnexpectedAbortError,
398
+ f as ProtoModel,
399
+ I as action
392
400
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@vue-modeler/model",
4
- "version": "1.0.7",
4
+ "version": "2.0.1-beta.1",
5
5
  "description": "A state management library based on models for Vue.js",
6
6
  "author": "abratko",
7
7
  "license": "MIT",
@@ -28,6 +28,7 @@
28
28
  "@types/node": "^22.14.0",
29
29
  "@vitest/coverage-v8": "2.1.3",
30
30
  "@vue/test-utils": "^1.3.6",
31
+ "conventional-changelog-conventionalcommits": "^9.1.0",
31
32
  "eslint": "^9.23.0",
32
33
  "eslint-scope": "^8.3.0",
33
34
  "eslint-visitor-keys": "^4.2.0",
@@ -40,7 +41,6 @@
40
41
  "vitest": "^2.1.9"
41
42
  },
42
43
  "peerDependencies": {
43
- "@vue-modeler/dc": ">=2.1.0 <3.0.0-beta.999",
44
44
  "vue": ">=2.7 <4.0.0"
45
45
  },
46
46
  "scripts": {