@diphyx/harlemify 4.0.1 → 5.0.0
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 +15 -19
- package/dist/module.d.mts +5 -0
- package/dist/module.d.ts +5 -0
- package/dist/module.json +1 -1
- package/dist/runtime/composables/action.d.ts +2 -2
- package/dist/runtime/core/layers/action.d.ts +3 -2
- package/dist/runtime/core/layers/action.js +37 -69
- package/dist/runtime/core/layers/model.js +14 -0
- package/dist/runtime/core/layers/shape.d.ts +2 -2
- package/dist/runtime/core/layers/shape.js +3 -2
- package/dist/runtime/core/layers/view.d.ts +2 -2
- package/dist/runtime/core/layers/view.js +27 -5
- package/dist/runtime/core/store.d.ts +5 -23
- package/dist/runtime/core/store.js +8 -28
- package/dist/runtime/core/types/action.d.ts +78 -119
- package/dist/runtime/core/types/action.js +0 -16
- package/dist/runtime/core/types/base.d.ts +6 -0
- package/dist/runtime/core/types/base.js +0 -0
- package/dist/runtime/core/types/model.d.ts +47 -32
- package/dist/runtime/core/types/model.js +14 -0
- package/dist/runtime/core/types/shape.d.ts +30 -5
- package/dist/runtime/core/types/store.d.ts +14 -0
- package/dist/runtime/core/types/store.js +0 -0
- package/dist/runtime/core/types/view.d.ts +35 -24
- package/dist/runtime/core/types/view.js +5 -0
- package/dist/runtime/core/utils/action.d.ts +4 -4
- package/dist/runtime/core/utils/action.js +219 -203
- package/dist/runtime/core/utils/base.d.ts +4 -0
- package/dist/runtime/core/utils/base.js +24 -0
- package/dist/runtime/core/utils/error.d.ts +21 -0
- package/dist/runtime/core/utils/error.js +36 -0
- package/dist/runtime/core/utils/model.d.ts +3 -11
- package/dist/runtime/core/utils/model.js +104 -110
- package/dist/runtime/core/utils/shape.d.ts +6 -3
- package/dist/runtime/core/utils/shape.js +218 -14
- package/dist/runtime/core/utils/store.d.ts +8 -0
- package/dist/runtime/core/utils/store.js +35 -0
- package/dist/runtime/core/utils/view.d.ts +3 -4
- package/dist/runtime/core/utils/view.js +35 -14
- package/dist/runtime/index.d.ts +8 -4
- package/dist/runtime/index.js +4 -9
- package/package.json +2 -1
|
@@ -3,263 +3,279 @@ import { ref, computed, readonly, toValue, nextTick } from "vue";
|
|
|
3
3
|
import {
|
|
4
4
|
ActionApiMethod,
|
|
5
5
|
ActionStatus,
|
|
6
|
-
ActionConcurrent
|
|
7
|
-
DEFINITION
|
|
6
|
+
ActionConcurrent
|
|
8
7
|
} from "../types/action.js";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
import { trimStart, trimEnd, isEmptyRecord, isPlainObject } from "./base.js";
|
|
9
|
+
import {
|
|
10
|
+
ActionApiError,
|
|
11
|
+
ActionHandlerError,
|
|
12
|
+
ActionCommitError,
|
|
13
|
+
ActionConcurrentError,
|
|
14
|
+
isError,
|
|
15
|
+
toError
|
|
16
|
+
} from "./error.js";
|
|
17
|
+
import { resolveAliasInbound, resolveAliasOutbound } from "./shape.js";
|
|
18
|
+
function resolveValue(value, view, fallback) {
|
|
19
|
+
if (typeof value === "function") {
|
|
20
|
+
return value(view) || fallback;
|
|
17
21
|
}
|
|
22
|
+
return toValue(value) || fallback;
|
|
18
23
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
function resolveApiUrl(definition, view, options) {
|
|
25
|
+
const endpoint = trimEnd(definition.request.endpoint ?? "", "/");
|
|
26
|
+
let path = resolveValue(definition.request.url, view);
|
|
27
|
+
if (options?.params) {
|
|
28
|
+
for (const [key, value] of Object.entries(options.params)) {
|
|
29
|
+
path = path.replace(`:${key}`, encodeURIComponent(value));
|
|
30
|
+
}
|
|
24
31
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
name = "ActionCommitError";
|
|
28
|
-
constructor(cause) {
|
|
29
|
-
super(cause.message);
|
|
30
|
-
this.cause = cause;
|
|
32
|
+
if (endpoint) {
|
|
33
|
+
return `${endpoint}/${trimStart(path, "/")}`;
|
|
31
34
|
}
|
|
35
|
+
return path;
|
|
36
|
+
}
|
|
37
|
+
function resolveApiHeaders(definition, view, options) {
|
|
38
|
+
const initial = resolveValue(definition.request.headers, view, {});
|
|
39
|
+
const custom = options?.headers ?? {};
|
|
40
|
+
return defu(custom, initial);
|
|
32
41
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
function resolveApiQuery(definition, view, options) {
|
|
43
|
+
const initial = resolveValue(definition.request.query, view, {});
|
|
44
|
+
const custom = options?.query ?? {};
|
|
45
|
+
return defu(custom, initial);
|
|
46
|
+
}
|
|
47
|
+
function resolveApiBody(definition, view, target, options) {
|
|
48
|
+
if (definition.request.method === ActionApiMethod.GET || definition.request.method === ActionApiMethod.HEAD) {
|
|
49
|
+
return void 0;
|
|
37
50
|
}
|
|
51
|
+
const initial = resolveValue(definition.request.body, view, {});
|
|
52
|
+
const custom = options?.body ?? {};
|
|
53
|
+
const body = defu(custom, initial);
|
|
54
|
+
if (!isPlainObject(body)) {
|
|
55
|
+
return body;
|
|
56
|
+
}
|
|
57
|
+
if (!isEmptyRecord(target?.aliases())) {
|
|
58
|
+
return resolveAliasOutbound(body, target.aliases());
|
|
59
|
+
}
|
|
60
|
+
return body;
|
|
38
61
|
}
|
|
39
|
-
function
|
|
40
|
-
return
|
|
62
|
+
function resolveApiMethod(definition, view) {
|
|
63
|
+
return resolveValue(definition.request.method, view, ActionApiMethod.GET);
|
|
41
64
|
}
|
|
42
|
-
function
|
|
43
|
-
|
|
65
|
+
function resolveApiTimeout(definition, view, options) {
|
|
66
|
+
if (options?.timeout) {
|
|
67
|
+
return options.timeout;
|
|
68
|
+
}
|
|
69
|
+
if (definition.request.timeout) {
|
|
70
|
+
return resolveValue(definition.request.timeout, view);
|
|
71
|
+
}
|
|
72
|
+
return void 0;
|
|
44
73
|
}
|
|
45
|
-
function
|
|
46
|
-
|
|
74
|
+
function resolveApiSignal(options, abortController) {
|
|
75
|
+
if (options?.signal) {
|
|
76
|
+
return options.signal;
|
|
77
|
+
}
|
|
78
|
+
return abortController.signal;
|
|
47
79
|
}
|
|
48
|
-
function
|
|
49
|
-
|
|
80
|
+
function resolveCommitTarget(commit, model) {
|
|
81
|
+
if (commit) {
|
|
82
|
+
return model[commit.model];
|
|
83
|
+
}
|
|
84
|
+
return void 0;
|
|
50
85
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
model,
|
|
58
|
-
mode,
|
|
59
|
-
value,
|
|
60
|
-
options
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
};
|
|
86
|
+
function resolveCommitMode(commit, options) {
|
|
87
|
+
if (commit) {
|
|
88
|
+
if (options?.commit?.mode) {
|
|
89
|
+
return options.commit.mode;
|
|
90
|
+
}
|
|
91
|
+
return commit.mode;
|
|
64
92
|
}
|
|
65
|
-
return
|
|
93
|
+
return void 0;
|
|
66
94
|
}
|
|
67
|
-
function
|
|
68
|
-
if (typeof value === "function") {
|
|
69
|
-
|
|
70
|
-
return handler(view) || fallback;
|
|
95
|
+
function resolveCommitValue(commit, data) {
|
|
96
|
+
if (typeof commit.value === "function") {
|
|
97
|
+
return commit.value(data);
|
|
71
98
|
}
|
|
72
|
-
return
|
|
99
|
+
return data;
|
|
73
100
|
}
|
|
74
|
-
function
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
101
|
+
function isApiDefinition(definition) {
|
|
102
|
+
return "request" in definition;
|
|
103
|
+
}
|
|
104
|
+
function resolveConcurrent(definition, options) {
|
|
105
|
+
if (options?.concurrent) {
|
|
106
|
+
return options.concurrent;
|
|
79
107
|
}
|
|
80
|
-
|
|
108
|
+
if (isApiDefinition(definition) && definition.request.concurrent) {
|
|
109
|
+
return definition.request.concurrent;
|
|
110
|
+
}
|
|
111
|
+
return ActionConcurrent.BLOCK;
|
|
81
112
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
113
|
+
async function executeApi(definition, api, options) {
|
|
114
|
+
try {
|
|
115
|
+
definition.logger?.debug("Action API request", {
|
|
116
|
+
action: definition.key,
|
|
117
|
+
method: api.method,
|
|
118
|
+
url: api.url
|
|
119
|
+
});
|
|
120
|
+
if (options?.transformer?.request) {
|
|
121
|
+
api = options.transformer.request(api);
|
|
122
|
+
}
|
|
123
|
+
const response = await $fetch(api.url, {
|
|
124
|
+
method: api.method,
|
|
125
|
+
headers: api.headers,
|
|
126
|
+
query: api.query,
|
|
127
|
+
body: api.body,
|
|
128
|
+
timeout: api.timeout,
|
|
129
|
+
signal: api.signal,
|
|
130
|
+
responseType: "json"
|
|
131
|
+
});
|
|
132
|
+
definition.logger?.debug("Action API response received", {
|
|
133
|
+
action: definition.key,
|
|
134
|
+
method: api.method,
|
|
135
|
+
url: api.url
|
|
136
|
+
});
|
|
137
|
+
if (options?.transformer?.response) {
|
|
138
|
+
return options.transformer.response(response);
|
|
139
|
+
}
|
|
140
|
+
return response;
|
|
141
|
+
} catch (error) {
|
|
142
|
+
const fetchError = toError(error, ActionApiError);
|
|
143
|
+
definition.logger?.error("Action API error", {
|
|
144
|
+
action: definition.key,
|
|
145
|
+
error: fetchError.message
|
|
146
|
+
});
|
|
147
|
+
throw fetchError;
|
|
148
|
+
}
|
|
86
149
|
}
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
150
|
+
async function executeHandler(definition, model, view) {
|
|
151
|
+
try {
|
|
152
|
+
definition.logger?.debug("Action handler phase", {
|
|
153
|
+
action: definition.key
|
|
154
|
+
});
|
|
155
|
+
return await definition.callback({
|
|
156
|
+
model,
|
|
157
|
+
view
|
|
158
|
+
});
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (isError(error, ActionApiError, ActionHandlerError)) {
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
const handlerError = toError(error, ActionHandlerError);
|
|
164
|
+
definition.logger?.error("Action handler error", {
|
|
165
|
+
action: definition.key,
|
|
166
|
+
error: handlerError.message
|
|
167
|
+
});
|
|
168
|
+
throw handlerError;
|
|
169
|
+
}
|
|
91
170
|
}
|
|
92
|
-
function
|
|
93
|
-
if (definition.
|
|
94
|
-
return
|
|
171
|
+
function executeCommit(definition, target, mode, data) {
|
|
172
|
+
if (!definition.commit) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (!target || !mode) {
|
|
176
|
+
throw new ActionCommitError({
|
|
177
|
+
message: `Model "${definition.commit.model}" is not defined`
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
definition.logger?.debug("Action commit phase", {
|
|
182
|
+
action: definition.key,
|
|
183
|
+
target,
|
|
184
|
+
mode
|
|
185
|
+
});
|
|
186
|
+
if (!isEmptyRecord(target.aliases())) {
|
|
187
|
+
data = resolveAliasInbound(data, target.aliases());
|
|
188
|
+
}
|
|
189
|
+
const value = resolveCommitValue(definition.commit, data);
|
|
190
|
+
target.commit(mode, value, definition.commit.options);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
const commitError = toError(error, ActionCommitError);
|
|
193
|
+
definition.logger?.error("Action commit error", {
|
|
194
|
+
action: definition.key,
|
|
195
|
+
error: commitError.message
|
|
196
|
+
});
|
|
197
|
+
throw commitError;
|
|
95
198
|
}
|
|
96
|
-
const initial = resolveApiValue(definition.body, view, {});
|
|
97
|
-
const custom = resolveApiValue(payload?.body, view, {});
|
|
98
|
-
return defu(custom, initial);
|
|
99
199
|
}
|
|
100
|
-
export function createAction(definition,
|
|
200
|
+
export function createAction(definition, model, view) {
|
|
201
|
+
definition.logger?.debug("Registering action", {
|
|
202
|
+
action: definition.key,
|
|
203
|
+
type: isApiDefinition(definition) ? "api" : "handler"
|
|
204
|
+
});
|
|
205
|
+
let currentController = null;
|
|
206
|
+
let abortController = null;
|
|
207
|
+
let globalData = null;
|
|
101
208
|
const globalError = ref(null);
|
|
102
209
|
const globalStatus = ref(ActionStatus.IDLE);
|
|
103
210
|
const loading = computed(() => {
|
|
104
211
|
return globalStatus.value === ActionStatus.PENDING;
|
|
105
212
|
});
|
|
106
|
-
|
|
107
|
-
let currentController = null;
|
|
108
|
-
let abortController = null;
|
|
109
|
-
async function execute(payload) {
|
|
213
|
+
async function execute(options) {
|
|
110
214
|
await nextTick();
|
|
215
|
+
const concurrent = resolveConcurrent(definition, options);
|
|
111
216
|
if (loading.value) {
|
|
112
|
-
const concurrent = payload?.concurrent ?? definition.api?.concurrent ?? ActionConcurrent.BLOCK;
|
|
113
217
|
switch (concurrent) {
|
|
114
218
|
case ActionConcurrent.BLOCK: {
|
|
115
219
|
definition.logger?.error("Action blocked by concurrent guard", {
|
|
116
|
-
action: key
|
|
220
|
+
action: definition.key
|
|
117
221
|
});
|
|
118
|
-
throw
|
|
222
|
+
throw new ActionConcurrentError();
|
|
119
223
|
}
|
|
120
224
|
case ActionConcurrent.SKIP: {
|
|
121
225
|
definition.logger?.warn("Action skipped by concurrent guard", {
|
|
122
|
-
action: key
|
|
226
|
+
action: definition.key
|
|
123
227
|
});
|
|
124
228
|
return currentController;
|
|
125
229
|
}
|
|
126
230
|
case ActionConcurrent.CANCEL: {
|
|
127
231
|
definition.logger?.warn("Action cancelling previous execution", {
|
|
128
|
-
action: key
|
|
232
|
+
action: definition.key
|
|
129
233
|
});
|
|
130
234
|
abortController?.abort();
|
|
131
235
|
}
|
|
132
236
|
}
|
|
133
237
|
}
|
|
134
238
|
abortController = new AbortController();
|
|
135
|
-
const activeStatus =
|
|
136
|
-
const activeError =
|
|
239
|
+
const activeStatus = options?.bind?.status ?? globalStatus;
|
|
240
|
+
const activeError = options?.bind?.error ?? globalError;
|
|
137
241
|
activeStatus.value = ActionStatus.PENDING;
|
|
138
242
|
activeError.value = null;
|
|
139
243
|
currentController = (async () => {
|
|
140
244
|
try {
|
|
141
|
-
let
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
method: definition.api.method,
|
|
167
|
-
url
|
|
168
|
-
});
|
|
169
|
-
} catch (error) {
|
|
170
|
-
const errorMessage = error?.message ?? "API request failed";
|
|
171
|
-
const errorOptions = {
|
|
172
|
-
status: error?.status ?? error?.response?.status,
|
|
173
|
-
statusText: error?.statusText ?? error?.response?.statusText,
|
|
174
|
-
data: error?.data ?? error?.response?._data
|
|
175
|
-
};
|
|
176
|
-
definition.logger?.error("Action API error", {
|
|
177
|
-
action: key,
|
|
178
|
-
error: errorMessage
|
|
179
|
-
});
|
|
180
|
-
throw createApiError(errorMessage, errorOptions);
|
|
181
|
-
}
|
|
182
|
-
if (definition.handle) {
|
|
183
|
-
const handler = definition.handle;
|
|
184
|
-
try {
|
|
185
|
-
definition.logger?.debug("Action handle phase", {
|
|
186
|
-
action: key
|
|
187
|
-
});
|
|
188
|
-
result = await handler({
|
|
189
|
-
view,
|
|
190
|
-
commit: committer,
|
|
191
|
-
async api() {
|
|
192
|
-
return response;
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
} catch (handleError) {
|
|
196
|
-
if (handleError instanceof ApiError || handleError instanceof HandleError) {
|
|
197
|
-
throw handleError;
|
|
198
|
-
}
|
|
199
|
-
definition.logger?.error("Action handle error", {
|
|
200
|
-
action: key,
|
|
201
|
-
error: handleError?.message
|
|
202
|
-
});
|
|
203
|
-
throw createHandleError(handleError);
|
|
204
|
-
}
|
|
205
|
-
} else {
|
|
206
|
-
result = response;
|
|
207
|
-
}
|
|
208
|
-
} else if (definition.handle) {
|
|
209
|
-
const handler = definition.handle;
|
|
210
|
-
try {
|
|
211
|
-
definition.logger?.debug("Action handle phase", {
|
|
212
|
-
action: key
|
|
213
|
-
});
|
|
214
|
-
result = await handler({
|
|
215
|
-
view,
|
|
216
|
-
commit: committer
|
|
217
|
-
});
|
|
218
|
-
} catch (handleError) {
|
|
219
|
-
if (handleError instanceof HandleError) {
|
|
220
|
-
throw handleError;
|
|
221
|
-
}
|
|
222
|
-
definition.logger?.error("Action handle error", {
|
|
223
|
-
action: key,
|
|
224
|
-
error: handleError?.message
|
|
225
|
-
});
|
|
226
|
-
throw createHandleError(handleError);
|
|
227
|
-
}
|
|
245
|
+
let data;
|
|
246
|
+
if (isApiDefinition(definition)) {
|
|
247
|
+
const target = resolveCommitTarget(definition.commit, model);
|
|
248
|
+
const mode = resolveCommitMode(definition.commit, options);
|
|
249
|
+
const url = resolveApiUrl(definition, view, options);
|
|
250
|
+
const method = resolveApiMethod(definition, view);
|
|
251
|
+
const headers = resolveApiHeaders(definition, view, options);
|
|
252
|
+
const query = resolveApiQuery(definition, view, options);
|
|
253
|
+
const body = resolveApiBody(definition, view, target, options);
|
|
254
|
+
const timeout = resolveApiTimeout(definition, view, options);
|
|
255
|
+
const signal = resolveApiSignal(options, abortController);
|
|
256
|
+
data = await executeApi(
|
|
257
|
+
definition,
|
|
258
|
+
{
|
|
259
|
+
url,
|
|
260
|
+
method,
|
|
261
|
+
headers,
|
|
262
|
+
query,
|
|
263
|
+
body,
|
|
264
|
+
timeout,
|
|
265
|
+
signal
|
|
266
|
+
},
|
|
267
|
+
options
|
|
268
|
+
);
|
|
269
|
+
executeCommit(definition, target, mode, data);
|
|
228
270
|
} else {
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
if (payload?.transformer) {
|
|
232
|
-
result = payload.transformer(result);
|
|
233
|
-
}
|
|
234
|
-
if (definition.commit) {
|
|
235
|
-
try {
|
|
236
|
-
definition.logger?.debug("Action commit phase", {
|
|
237
|
-
action: key,
|
|
238
|
-
model: definition.commit.model,
|
|
239
|
-
mode: definition.commit.mode
|
|
240
|
-
});
|
|
241
|
-
executeCommit(
|
|
242
|
-
{
|
|
243
|
-
...definition.commit,
|
|
244
|
-
mode: payload?.commit?.mode ?? definition.commit.mode
|
|
245
|
-
},
|
|
246
|
-
mutations,
|
|
247
|
-
result
|
|
248
|
-
);
|
|
249
|
-
} catch (commitError) {
|
|
250
|
-
definition.logger?.error("Action commit error", {
|
|
251
|
-
action: key,
|
|
252
|
-
error: commitError?.message
|
|
253
|
-
});
|
|
254
|
-
throw createCommitError(commitError);
|
|
255
|
-
}
|
|
271
|
+
data = await executeHandler(definition, model, view);
|
|
256
272
|
}
|
|
257
|
-
|
|
273
|
+
globalData = data;
|
|
258
274
|
activeStatus.value = ActionStatus.SUCCESS;
|
|
259
275
|
definition.logger?.debug("Action success", {
|
|
260
|
-
action: key
|
|
276
|
+
action: definition.key
|
|
261
277
|
});
|
|
262
|
-
return
|
|
278
|
+
return data;
|
|
263
279
|
} catch (actionError) {
|
|
264
280
|
activeError.value = actionError;
|
|
265
281
|
activeStatus.value = ActionStatus.ERROR;
|
|
@@ -282,12 +298,12 @@ export function createAction(definition, mutations, view, key) {
|
|
|
282
298
|
return readonly(globalStatus);
|
|
283
299
|
},
|
|
284
300
|
get data() {
|
|
285
|
-
return
|
|
301
|
+
return globalData;
|
|
286
302
|
},
|
|
287
303
|
reset() {
|
|
288
304
|
globalError.value = null;
|
|
289
305
|
globalStatus.value = ActionStatus.IDLE;
|
|
290
|
-
|
|
306
|
+
globalData = null;
|
|
291
307
|
}
|
|
292
308
|
});
|
|
293
309
|
return action;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function trimStart(value: string, char: string): string;
|
|
2
|
+
export declare function trimEnd(value: string, char: string): string;
|
|
3
|
+
export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
4
|
+
export declare function isEmptyRecord(record: Record<string, unknown> | undefined): record is undefined;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function trimStart(value, char) {
|
|
2
|
+
return value.replace(new RegExp(`^${char}+`), "");
|
|
3
|
+
}
|
|
4
|
+
export function trimEnd(value, char) {
|
|
5
|
+
return value.replace(new RegExp(`${char}+$`), "");
|
|
6
|
+
}
|
|
7
|
+
export function isPlainObject(value) {
|
|
8
|
+
if (!value || typeof value !== "object") {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
if (Array.isArray(value)) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
export function isEmptyRecord(record) {
|
|
17
|
+
if (!record) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (Object.keys(record).length === 0) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class ActionApiError extends Error {
|
|
2
|
+
name: "ActionApiError";
|
|
3
|
+
status: number;
|
|
4
|
+
statusText: string;
|
|
5
|
+
data: unknown;
|
|
6
|
+
constructor(source: any);
|
|
7
|
+
}
|
|
8
|
+
export declare class ActionHandlerError extends Error {
|
|
9
|
+
name: "ActionHandlerError";
|
|
10
|
+
constructor(source: any);
|
|
11
|
+
}
|
|
12
|
+
export declare class ActionCommitError extends Error {
|
|
13
|
+
name: "ActionCommitError";
|
|
14
|
+
constructor(source: any);
|
|
15
|
+
}
|
|
16
|
+
export declare class ActionConcurrentError extends Error {
|
|
17
|
+
name: "ActionConcurrentError";
|
|
18
|
+
constructor();
|
|
19
|
+
}
|
|
20
|
+
export declare function isError(error: unknown, ...types: (abstract new (...args: never[]) => Error)[]): error is Error;
|
|
21
|
+
export declare function toError<T extends Error = Error>(error: unknown, ErrorType?: new (source: unknown) => T): T;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export class ActionApiError extends Error {
|
|
2
|
+
name = "ActionApiError";
|
|
3
|
+
constructor(source) {
|
|
4
|
+
super(source.message || "API request failed");
|
|
5
|
+
this.status = source?.status ?? source?.response?.status ?? 500;
|
|
6
|
+
this.statusText = source?.statusText ?? source?.response?.statusText ?? "Internal Server Error";
|
|
7
|
+
this.data = source?.data ?? source?.response?._data ?? null;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class ActionHandlerError extends Error {
|
|
11
|
+
name = "ActionHandlerError";
|
|
12
|
+
constructor(source) {
|
|
13
|
+
super(source.message || "Action handler failed");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class ActionCommitError extends Error {
|
|
17
|
+
name = "ActionCommitError";
|
|
18
|
+
constructor(source) {
|
|
19
|
+
super(source.message || "Action commit failed");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class ActionConcurrentError extends Error {
|
|
23
|
+
name = "ActionConcurrentError";
|
|
24
|
+
constructor() {
|
|
25
|
+
super("Action is already pending");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function isError(error, ...types) {
|
|
29
|
+
return types.some((ErrorType) => error instanceof ErrorType);
|
|
30
|
+
}
|
|
31
|
+
export function toError(error, ErrorType) {
|
|
32
|
+
if (ErrorType) {
|
|
33
|
+
return new ErrorType(error);
|
|
34
|
+
}
|
|
35
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
36
|
+
}
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import type { Store as SourceStore, BaseState } from "@harlem/core";
|
|
2
|
-
import
|
|
3
|
-
import { type
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function createMutations<M extends Model>(source: SourceStore<BaseState>, model: M): Mutations<M>;
|
|
6
|
-
export declare function executeCommit<M extends Model>(definition: {
|
|
7
|
-
model: keyof M;
|
|
8
|
-
mode: ActionOneMode | ActionManyMode;
|
|
9
|
-
value?: unknown;
|
|
10
|
-
options?: MutationsOneOptions | MutationsManyOptions;
|
|
11
|
-
}, mutations: Mutations<M>, result?: unknown): void;
|
|
12
|
-
export declare function createCommitter<M extends Model>(mutations: Mutations<M>): ActionCommitter<M>;
|
|
2
|
+
import type { Shape } from "../types/shape.js";
|
|
3
|
+
import { type ModelDefinition, type ModelCall } from "../types/model.js";
|
|
4
|
+
export declare function createModel<S extends Shape>(definition: ModelDefinition<S>, source: SourceStore<BaseState>): ModelCall<S>;
|