@vue-modeler/model 2.2.0-beta.5 → 2.2.0-beta.7
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 +1 -1
- package/dist/index.d.ts +32 -32
- package/dist/index.js +115 -78
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
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;
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,8 @@ export declare class Action<T extends object, Args extends any[] = unknown[]> im
|
|
|
16
16
|
protected _model: T;
|
|
17
17
|
protected actionFunction: OriginalMethodWrapper<Args>;
|
|
18
18
|
protected ownerGetter: () => Model<T>;
|
|
19
|
-
protected setStateCb
|
|
19
|
+
protected setStateCb: (action: ActionLike<T, Args>, oldState: ActionStateName, newState: ActionStateName) => void;
|
|
20
|
+
protected _validateArgs: (action: ActionLike<T, Args>, ...args: Args) => Error[];
|
|
20
21
|
static readonly actionFlag: unique symbol;
|
|
21
22
|
static readonly possibleState: {
|
|
22
23
|
readonly pending: "pending";
|
|
@@ -30,8 +31,8 @@ export declare class Action<T extends object, Args extends any[] = unknown[]> im
|
|
|
30
31
|
protected _state: ActionStateName;
|
|
31
32
|
protected _value: ActionValue;
|
|
32
33
|
protected _args: Args | null;
|
|
33
|
-
constructor(_model: T, actionFunction: OriginalMethodWrapper<Args>, ownerGetter: () => Model<T>, setStateCb
|
|
34
|
-
static create<T extends ProtoModel, Args extends unknown[] = unknown[]>(model: T, actionFunction: OriginalMethodWrapper<Args>, ownerGetter: () => Model<T>, setStateCb
|
|
34
|
+
constructor(_model: T, actionFunction: OriginalMethodWrapper<Args>, ownerGetter: () => Model<T>, setStateCb: (action: ActionLike<T, Args>, oldState: ActionStateName, newState: ActionStateName) => void, _validateArgs: (action: ActionLike<T, Args>, ...args: Args) => Error[]);
|
|
35
|
+
static create<T extends ProtoModel, Args extends unknown[] = unknown[]>(model: T, actionFunction: OriginalMethodWrapper<Args>, ownerGetter: () => Model<T>, setStateCb: (action: ActionLike<T, Args>, oldState: ActionStateName, newState: ActionStateName) => void, validateArgs: (action: ActionLike<T, Args>, ...args: Args) => Error[]): ActionLike<T, Args>;
|
|
35
36
|
toString(): string;
|
|
36
37
|
get owner(): Model<T>;
|
|
37
38
|
get possibleStates(): ActionStateName[];
|
|
@@ -48,6 +49,7 @@ export declare class Action<T extends object, Args extends any[] = unknown[]> im
|
|
|
48
49
|
get isLock(): boolean;
|
|
49
50
|
get isAbort(): boolean;
|
|
50
51
|
is(...args: ActionStateName[]): boolean;
|
|
52
|
+
validate(...args: Args): Error[];
|
|
51
53
|
/**
|
|
52
54
|
* Put into action in PENDING state
|
|
53
55
|
*/
|
|
@@ -122,6 +124,7 @@ export declare interface ActionLike<T extends object, Args extends any[] = unkno
|
|
|
122
124
|
readonly isLock: boolean;
|
|
123
125
|
readonly isAbort: boolean;
|
|
124
126
|
is(...args: ActionStateName[]): boolean;
|
|
127
|
+
validate(...args: Args): Error[];
|
|
125
128
|
exec(...args: Args): Promise<void>;
|
|
126
129
|
abort(reason?: unknown): Promise<void>;
|
|
127
130
|
lock(): Promise<void>;
|
|
@@ -153,33 +156,6 @@ export declare class ActionUnexpectedAbortError extends ActionInternalError {
|
|
|
153
156
|
|
|
154
157
|
declare type ActionValue = ActionPendingValue | ActionError | null;
|
|
155
158
|
|
|
156
|
-
/**
|
|
157
|
-
* Wraps ProtoModel instance with proxy to handle get traps for actions
|
|
158
|
-
* and to return Action instance instead of original method.
|
|
159
|
-
*
|
|
160
|
-
* ```ts
|
|
161
|
-
* class TestModel extends ProtoModel {
|
|
162
|
-
* constructor() {
|
|
163
|
-
* super()
|
|
164
|
-
* }
|
|
165
|
-
*
|
|
166
|
-
* @action async someAction(): Promise<void> {
|
|
167
|
-
* return Promise.resolve()
|
|
168
|
-
* }
|
|
169
|
-
* }
|
|
170
|
-
*
|
|
171
|
-
* const model = createModel(new TestModel())
|
|
172
|
-
* const action = model.someAction // will return Action instance instead of original method
|
|
173
|
-
* model.someAction.exec() // will execute action
|
|
174
|
-
* model.someAction.isPending // will return true if action is pending
|
|
175
|
-
* model.someAction.error // will return error if action is errored
|
|
176
|
-
* ```
|
|
177
|
-
* @param protoModel - ProtoModel instance.
|
|
178
|
-
* @returns model instance wrapped with proxy.
|
|
179
|
-
* @see src/proto-model.ts
|
|
180
|
-
*/
|
|
181
|
-
declare function createModel<Target extends ProtoModel>(protoModel: Target): Model<Target>;
|
|
182
|
-
|
|
183
159
|
export declare type Model<T extends object = object> = ShallowReactive<{
|
|
184
160
|
[K in keyof T]: T[K] extends ((...args: infer Args) => Promise<void>) ? ActionLike<T, Args> : K extends ProtectedMethodInModel ? never : T[K];
|
|
185
161
|
}>;
|
|
@@ -209,13 +185,36 @@ export declare abstract class ProtoModel {
|
|
|
209
185
|
protected [actionStatesKey]: Map<"pending" | "error" | "lock" | "ready" | "abort", Ref<number>>;
|
|
210
186
|
protected [actionsSizeKey]: number;
|
|
211
187
|
protected [watchStopHandlersKey]: Set<WatchStopHandle>;
|
|
212
|
-
|
|
188
|
+
/**
|
|
189
|
+
* Wraps ProtoModel instance with proxy to handle get traps for actions
|
|
190
|
+
* and to return Action instance instead of original method.
|
|
191
|
+
*
|
|
192
|
+
* ```ts
|
|
193
|
+
* class TestModel extends ProtoModel {
|
|
194
|
+
* constructor() {
|
|
195
|
+
* super()
|
|
196
|
+
* }
|
|
197
|
+
*
|
|
198
|
+
* @action async someAction(): Promise<void> {
|
|
199
|
+
* return Promise.resolve()
|
|
200
|
+
* }
|
|
201
|
+
* }
|
|
202
|
+
*
|
|
203
|
+
* const model = ProtoModel.createModel(new TestModel())
|
|
204
|
+
* const action = model.someAction // will return Action instance instead of original method
|
|
205
|
+
* model.someAction.exec() // will execute action
|
|
206
|
+
* model.someAction.isPending // will return true if action is pending
|
|
207
|
+
* model.someAction.error // will return error if action is errored
|
|
208
|
+
* ```
|
|
209
|
+
* @param protoModel - ProtoModel instance.
|
|
210
|
+
* @returns model instance wrapped with proxy.
|
|
211
|
+
*/
|
|
212
|
+
static createModel<Target extends ProtoModel>(protoModel: Target): Model<Target>;
|
|
213
213
|
/**
|
|
214
214
|
* Creates a model instance.
|
|
215
215
|
*
|
|
216
216
|
* @param args - arguments for the model constructor.
|
|
217
217
|
* @returns model instance.
|
|
218
|
-
* @see src/create-model.ts
|
|
219
218
|
*/
|
|
220
219
|
static model<T extends ProtoModel, Args extends unknown[]>(this: new (...args: Args) => T, ...args: Args): Model<T>;
|
|
221
220
|
get hasPendingActions(): boolean;
|
|
@@ -332,6 +331,7 @@ export declare abstract class ProtoModel {
|
|
|
332
331
|
* @see type Model<T>
|
|
333
332
|
*/
|
|
334
333
|
setActionState(action: ActionLike<this>): void;
|
|
334
|
+
protected validateArgs(action: ActionLike<this>, ...args: unknown[]): Error[];
|
|
335
335
|
isModelOf<T extends ProtoModel>(typeModel: ModelConstructor_2<T>): boolean;
|
|
336
336
|
destructor(): void;
|
|
337
337
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var i = (r, t, e) =>
|
|
4
|
-
import { shallowReactive as F, effectScope as
|
|
5
|
-
class
|
|
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 {
|
|
6
6
|
constructor(t, e) {
|
|
7
7
|
super(e.cause.message), this.actionName = t, this.options = e, this.name = this.constructor.name;
|
|
8
8
|
}
|
|
@@ -26,18 +26,18 @@ class b extends u {
|
|
|
26
26
|
super(`Trying to update state of ${t} from ${e} to ${o}`), this.name = this.constructor.name;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
class
|
|
29
|
+
class j 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
|
|
35
|
-
constructor(t, e, o,
|
|
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
36
|
i(this, "name");
|
|
37
37
|
i(this, "_state", s.possibleState.ready);
|
|
38
38
|
i(this, "_value", null);
|
|
39
39
|
i(this, "_args", null);
|
|
40
|
-
this._model = t, this.actionFunction = e, this.ownerGetter = o, this.setStateCb =
|
|
40
|
+
this._model = t, this.actionFunction = e, this.ownerGetter = o, this.setStateCb = c, this._validateArgs = h;
|
|
41
41
|
const n = e.name;
|
|
42
42
|
if (!(n in this._model && typeof this._model[n] == "function"))
|
|
43
43
|
throw new u(`Model does not contain method ${n}`);
|
|
@@ -45,8 +45,14 @@ const j = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
|
|
|
45
45
|
throw new u(`Method ${n} is not action`);
|
|
46
46
|
this.name = n;
|
|
47
47
|
}
|
|
48
|
-
static create(t, e, o,
|
|
49
|
-
return F(new s(
|
|
48
|
+
static create(t, e, o, c, h) {
|
|
49
|
+
return F(new s(
|
|
50
|
+
t,
|
|
51
|
+
e,
|
|
52
|
+
o,
|
|
53
|
+
c,
|
|
54
|
+
h
|
|
55
|
+
));
|
|
50
56
|
}
|
|
51
57
|
toString() {
|
|
52
58
|
return this.name;
|
|
@@ -62,7 +68,7 @@ const j = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
|
|
|
62
68
|
}
|
|
63
69
|
set state(t) {
|
|
64
70
|
const e = this._state;
|
|
65
|
-
this._state = t, this.setStateCb
|
|
71
|
+
this._state = t, this.setStateCb(this, e, t);
|
|
66
72
|
}
|
|
67
73
|
get abortController() {
|
|
68
74
|
return this.isPending ? this._value.abortController : null;
|
|
@@ -98,6 +104,9 @@ const j = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
|
|
|
98
104
|
is(...t) {
|
|
99
105
|
return !!t.find((e) => this.state === e);
|
|
100
106
|
}
|
|
107
|
+
validate(...t) {
|
|
108
|
+
return this._validateArgs(this, ...t);
|
|
109
|
+
}
|
|
101
110
|
/**
|
|
102
111
|
* Put into action in PENDING state
|
|
103
112
|
*/
|
|
@@ -111,31 +120,31 @@ const j = (r) => r instanceof DOMException && r.name === "AbortError" || typeof
|
|
|
111
120
|
const e = [...t];
|
|
112
121
|
let o = t.length && t[t.length - 1];
|
|
113
122
|
o instanceof AbortController || (o = new AbortController(), e.push(o)), this.state = s.possibleState.pending, this._args = t;
|
|
114
|
-
const
|
|
115
|
-
if (!(
|
|
123
|
+
const h = this.actionFunction[s.actionFlag].apply(this._model, e);
|
|
124
|
+
if (!(h instanceof Promise))
|
|
116
125
|
return this.state = s.possibleState.ready, Promise.resolve();
|
|
117
|
-
const
|
|
126
|
+
const n = h.then(() => {
|
|
118
127
|
this.ready();
|
|
119
|
-
}).catch((
|
|
120
|
-
if (
|
|
121
|
-
throw
|
|
122
|
-
const
|
|
123
|
-
if (
|
|
124
|
-
throw new
|
|
125
|
-
if (
|
|
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) {
|
|
126
135
|
this.state = s.possibleState.lock, this._value = null;
|
|
127
136
|
return;
|
|
128
137
|
}
|
|
129
|
-
if (
|
|
138
|
+
if (S) {
|
|
130
139
|
this.state = s.possibleState.abort;
|
|
131
140
|
return;
|
|
132
141
|
}
|
|
133
|
-
this.setError(new
|
|
142
|
+
this.setError(new O(this.name, { cause: a }));
|
|
134
143
|
});
|
|
135
144
|
return this._value = {
|
|
136
|
-
promise:
|
|
145
|
+
promise: n,
|
|
137
146
|
abortController: o
|
|
138
|
-
},
|
|
147
|
+
}, n;
|
|
139
148
|
}
|
|
140
149
|
// Returns same promise as exec method
|
|
141
150
|
// but in reject state
|
|
@@ -184,56 +193,79 @@ i(s, "actionFlag", Symbol("__action_original_method__")), i(s, "possibleState",
|
|
|
184
193
|
ready: "ready",
|
|
185
194
|
abort: "abort"
|
|
186
195
|
}), i(s, "abortedByLock", Symbol("lock"));
|
|
187
|
-
let
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
throw new Error("ProtoModel instance is required");
|
|
192
|
-
return new z(
|
|
193
|
-
F(r),
|
|
194
|
-
{
|
|
195
|
-
get(e, o, a) {
|
|
196
|
-
const n = Reflect.get(e, o, a), l = typeof n == "function";
|
|
197
|
-
return l && h.actionFlag in n && typeof n[h.actionFlag] == "function" ? e.action(n) : l ? n.bind(e) : n;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
);
|
|
201
|
-
}
|
|
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;
|
|
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;
|
|
205
200
|
const f = class f {
|
|
206
201
|
constructor() {
|
|
207
202
|
// each model has its own effect scope to avoid memory leaks
|
|
208
|
-
i(this, x,
|
|
203
|
+
i(this, x, L(!0));
|
|
209
204
|
i(this, R, null);
|
|
210
205
|
// we use WeakMap to store actions as keys to avoid memory leaks
|
|
211
|
-
i(this, P, /* @__PURE__ */ new WeakMap());
|
|
212
206
|
i(this, C, /* @__PURE__ */ new WeakMap());
|
|
207
|
+
i(this, P, /* @__PURE__ */ new WeakMap());
|
|
213
208
|
i(this, M, /* @__PURE__ */ new Map());
|
|
214
209
|
// WeakMap doesn't have a size property, so we need to store the size of the map
|
|
215
|
-
i(this,
|
|
210
|
+
i(this, k, 0);
|
|
216
211
|
// watchers are stored in a set to avoid memory leaks
|
|
217
|
-
i(this,
|
|
212
|
+
i(this, E, /* @__PURE__ */ new Set());
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Wraps ProtoModel instance with proxy to handle get traps for actions
|
|
216
|
+
* and to return Action instance instead of original method.
|
|
217
|
+
*
|
|
218
|
+
* ```ts
|
|
219
|
+
* class TestModel extends ProtoModel {
|
|
220
|
+
* constructor() {
|
|
221
|
+
* super()
|
|
222
|
+
* }
|
|
223
|
+
*
|
|
224
|
+
* @action async someAction(): Promise<void> {
|
|
225
|
+
* return Promise.resolve()
|
|
226
|
+
* }
|
|
227
|
+
* }
|
|
228
|
+
*
|
|
229
|
+
* const model = ProtoModel.createModel(new TestModel())
|
|
230
|
+
* const action = model.someAction // will return Action instance instead of original method
|
|
231
|
+
* model.someAction.exec() // will execute action
|
|
232
|
+
* model.someAction.isPending // will return true if action is pending
|
|
233
|
+
* model.someAction.error // will return error if action is errored
|
|
234
|
+
* ```
|
|
235
|
+
* @param protoModel - ProtoModel instance.
|
|
236
|
+
* @returns model instance wrapped with proxy.
|
|
237
|
+
*/
|
|
238
|
+
static createModel(t) {
|
|
239
|
+
if (!(t instanceof f))
|
|
240
|
+
throw new Error("ProtoModel instance is required");
|
|
241
|
+
const e = new G(
|
|
242
|
+
F(t),
|
|
243
|
+
{
|
|
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;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
return t[m] = e, e;
|
|
218
251
|
}
|
|
219
252
|
/**
|
|
220
253
|
* Creates a model instance.
|
|
221
254
|
*
|
|
222
255
|
* @param args - arguments for the model constructor.
|
|
223
256
|
* @returns model instance.
|
|
224
|
-
* @see src/create-model.ts
|
|
225
257
|
*/
|
|
226
258
|
static model(...t) {
|
|
227
259
|
if (this.prototype === f.prototype)
|
|
228
260
|
throw new Error("ProtoModel is abstract class and can not be instantiated");
|
|
229
|
-
const e = new this(...t)
|
|
230
|
-
return e
|
|
261
|
+
const e = new this(...t);
|
|
262
|
+
return f.createModel(e);
|
|
231
263
|
}
|
|
232
264
|
get hasPendingActions() {
|
|
233
|
-
return !!this.getActionStatesRef(
|
|
265
|
+
return !!this.getActionStatesRef(l.possibleState.pending).value;
|
|
234
266
|
}
|
|
235
267
|
get hasActionWithError() {
|
|
236
|
-
return !!this.getActionStatesRef(
|
|
268
|
+
return !!this.getActionStatesRef(l.possibleState.error).value;
|
|
237
269
|
}
|
|
238
270
|
/**
|
|
239
271
|
* Registers watcher in the model effect scope.
|
|
@@ -294,7 +326,7 @@ const f = class f {
|
|
|
294
326
|
watch(...t) {
|
|
295
327
|
if (t.length === 0)
|
|
296
328
|
throw new Error("watch requires at least one argument");
|
|
297
|
-
const e = t.length === 1 ? this[d].run(() =>
|
|
329
|
+
const e = t.length === 1 ? this[d].run(() => B(t[0])) : this[d].run(() => D(...t));
|
|
298
330
|
if (!e)
|
|
299
331
|
throw new Error("watchStopHandler is undefined");
|
|
300
332
|
return this[p].add(e), () => {
|
|
@@ -302,29 +334,30 @@ const f = class f {
|
|
|
302
334
|
};
|
|
303
335
|
}
|
|
304
336
|
computed(t, e) {
|
|
305
|
-
return this[d].run(() =>
|
|
337
|
+
return this[d].run(() => T(t, e));
|
|
306
338
|
}
|
|
307
339
|
// @see https://github.com/trekhleb/javascript-algorithms/blob/master/src/algorithms/math/bits/updateBit.js
|
|
308
340
|
updateBit(t, e, o) {
|
|
309
|
-
const
|
|
310
|
-
return t &
|
|
341
|
+
const c = o ? 1 : 0, h = ~(1 << e);
|
|
342
|
+
return t & h | c << e;
|
|
311
343
|
}
|
|
312
344
|
createAction(t) {
|
|
313
345
|
const e = () => {
|
|
314
346
|
if (!this[m])
|
|
315
347
|
throw new Error("Model not set");
|
|
316
348
|
return this[m];
|
|
317
|
-
}, o =
|
|
349
|
+
}, o = l.create(
|
|
318
350
|
this,
|
|
319
351
|
t,
|
|
320
352
|
e,
|
|
321
|
-
this.setActionState.bind(this)
|
|
353
|
+
this.setActionState.bind(this),
|
|
354
|
+
this.validateArgs.bind(this)
|
|
322
355
|
);
|
|
323
|
-
return this[
|
|
356
|
+
return this[w].set(t, o), this[y].set(o, ++this[A]), this.setActionState(o), o;
|
|
324
357
|
}
|
|
325
358
|
getActionStatesRef(t) {
|
|
326
|
-
const e = this[
|
|
327
|
-
return this[
|
|
359
|
+
const e = this[g].get(t) || H(0);
|
|
360
|
+
return this[g].get(t) === void 0 && this[g].set(t, e), e;
|
|
328
361
|
}
|
|
329
362
|
/**
|
|
330
363
|
* Gets Action instance by wrapped original method or create Action instance.
|
|
@@ -370,9 +403,9 @@ const f = class f {
|
|
|
370
403
|
* @returns action
|
|
371
404
|
*/
|
|
372
405
|
action(t) {
|
|
373
|
-
if (!(
|
|
406
|
+
if (!(l.actionFlag in t && typeof t[l.actionFlag] == "function"))
|
|
374
407
|
throw new u("Action decorator is not applied to the method");
|
|
375
|
-
return this[
|
|
408
|
+
return this[w].get(t) || this.createAction(t);
|
|
376
409
|
}
|
|
377
410
|
/**
|
|
378
411
|
* It is public method in context ProtoModel,
|
|
@@ -388,6 +421,11 @@ const f = class f {
|
|
|
388
421
|
o !== t.state && (this.getActionStatesRef(o).value = this.updateBit(this.getActionStatesRef(o).value, e, !1));
|
|
389
422
|
this.getActionStatesRef(t.state).value = this.updateBit(this.getActionStatesRef(t.state).value, e, !0);
|
|
390
423
|
}
|
|
424
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
425
|
+
validateArgs(t, ...e) {
|
|
426
|
+
const o = `validateArgs is not implemented for action ${t.name} in the model`;
|
|
427
|
+
return [new Error(o)];
|
|
428
|
+
}
|
|
391
429
|
isModelOf(t) {
|
|
392
430
|
return this instanceof t;
|
|
393
431
|
}
|
|
@@ -397,9 +435,8 @@ const f = class f {
|
|
|
397
435
|
}), this[p] = /* @__PURE__ */ new Set(), this[d].stop();
|
|
398
436
|
}
|
|
399
437
|
};
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
function V(r, t) {
|
|
438
|
+
let v = f;
|
|
439
|
+
function N(r, t) {
|
|
403
440
|
if (t.static)
|
|
404
441
|
throw new Error("Action decorator is not supported for static methods");
|
|
405
442
|
if (t.private)
|
|
@@ -407,26 +444,26 @@ function V(r, t) {
|
|
|
407
444
|
let e;
|
|
408
445
|
try {
|
|
409
446
|
e = t.name.toString();
|
|
410
|
-
} catch (
|
|
411
|
-
const
|
|
412
|
-
throw new Error(
|
|
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);
|
|
413
450
|
}
|
|
414
451
|
const o = {
|
|
415
452
|
// Action constructor checks that model has method with the same name.
|
|
416
453
|
// We can`t define anonymous function and change name because Function.name is readonly property.
|
|
417
454
|
// So we need to create stub object to save original method name
|
|
418
|
-
[e]: function(...
|
|
419
|
-
return this.action(o[e]).exec(...
|
|
455
|
+
[e]: function(...c) {
|
|
456
|
+
return this.action(o[e]).exec(...c);
|
|
420
457
|
}
|
|
421
458
|
};
|
|
422
|
-
return o[e][
|
|
459
|
+
return o[e][l.actionFlag] = r, o[e];
|
|
423
460
|
}
|
|
424
461
|
export {
|
|
425
|
-
|
|
426
|
-
|
|
462
|
+
l as Action,
|
|
463
|
+
O as ActionError,
|
|
427
464
|
u as ActionInternalError,
|
|
428
465
|
b as ActionStatusConflictError,
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
466
|
+
j as ActionUnexpectedAbortError,
|
|
467
|
+
v as ProtoModel,
|
|
468
|
+
N as action
|
|
432
469
|
};
|