@diphyx/harlemify 6.3.0 → 6.4.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 +0 -2
- package/dist/module.json +1 -1
- package/dist/runtime/composables/view.d.ts +3 -0
- package/dist/runtime/composables/view.js +4 -4
- package/dist/runtime/core/types/action.d.ts +23 -1
- package/dist/runtime/core/utils/action.js +61 -3
- package/dist/runtime/index.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,8 +99,6 @@ await execute();
|
|
|
99
99
|
| Vue | `^3.5.0` |
|
|
100
100
|
| Zod | `^4.0.0` |
|
|
101
101
|
|
|
102
|
-
> **Note:** Early Nuxt 4 versions (e.g., 4.1.x) may have issues resolving the `#build` alias for module templates. If you encounter build errors related to `#build/harlemify.config`, upgrade to the latest Nuxt 4 release.
|
|
103
|
-
|
|
104
102
|
## Documentation
|
|
105
103
|
|
|
106
104
|
[https://diphyx.github.io/harlemify/](https://diphyx.github.io/harlemify/)
|
package/dist/module.json
CHANGED
|
@@ -13,3 +13,6 @@ export type UseStoreView<T> = {
|
|
|
13
13
|
export declare function useStoreView<V extends Record<string, ViewCall>, K extends keyof V & string, T = V[K] extends ComputedRef<infer R> ? R : unknown>(store: {
|
|
14
14
|
view: V;
|
|
15
15
|
}, key: K): UseStoreView<T>;
|
|
16
|
+
export declare function useStoreView<V extends Record<string, ViewCall>, K extends keyof V & string, R, T = V[K] extends ComputedRef<infer U> ? U : unknown>(store: {
|
|
17
|
+
view: V;
|
|
18
|
+
}, key: K, resolver: (value: T) => R): UseStoreView<R>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { watch } from "vue";
|
|
1
|
+
import { computed, watch } from "vue";
|
|
2
2
|
import { debounce, throttle } from "../core/utils/base.js";
|
|
3
|
-
export function useStoreView(store, key) {
|
|
3
|
+
export function useStoreView(store, key, resolver) {
|
|
4
4
|
if (!store.view[key]) {
|
|
5
5
|
throw new Error(`View "${key}" not found in store`);
|
|
6
6
|
}
|
|
7
7
|
const source = store.view[key];
|
|
8
|
-
const data = source;
|
|
8
|
+
const data = resolver ? computed(() => resolver(source.value)) : source;
|
|
9
9
|
function resolveCallback(callback, callbackOptions) {
|
|
10
10
|
if (callbackOptions?.debounce) {
|
|
11
11
|
return debounce(callback, callbackOptions.debounce);
|
|
@@ -18,7 +18,7 @@ export function useStoreView(store, key) {
|
|
|
18
18
|
function track(handler, trackOptions) {
|
|
19
19
|
const callback = resolveCallback(handler, trackOptions);
|
|
20
20
|
const stop = watch(
|
|
21
|
-
|
|
21
|
+
data,
|
|
22
22
|
(value) => {
|
|
23
23
|
callback(value);
|
|
24
24
|
},
|
|
@@ -44,6 +44,7 @@ export interface ActionApiRequest<MD extends ModelDefinitions, VD extends ViewDe
|
|
|
44
44
|
body?: ActionApiRequestValue<MD, VD, unknown>;
|
|
45
45
|
timeout?: ActionApiRequestValue<MD, VD, number>;
|
|
46
46
|
concurrent?: ActionConcurrent;
|
|
47
|
+
hooks?: ActionHooks;
|
|
47
48
|
}
|
|
48
49
|
export type ActionApiRequestShortcut<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>> = Omit<ActionApiRequest<MD, VD>, "method">;
|
|
49
50
|
export interface ActionApiCommitContext<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>> {
|
|
@@ -54,6 +55,7 @@ export interface ActionApiCommitContext<MD extends ModelDefinitions, VD extends
|
|
|
54
55
|
query: Readonly<Record<string, unknown>>;
|
|
55
56
|
body: unknown;
|
|
56
57
|
}>;
|
|
58
|
+
params: Readonly<Record<string, string | number>>;
|
|
57
59
|
view: DeepReadonly<StoreView<MD, VD>>;
|
|
58
60
|
}
|
|
59
61
|
export interface ActionApiCommit<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>, K extends keyof MD = keyof MD> {
|
|
@@ -128,15 +130,35 @@ export interface ActionResolvedApi {
|
|
|
128
130
|
timeout?: number;
|
|
129
131
|
signal: AbortSignal;
|
|
130
132
|
}
|
|
133
|
+
export interface ActionHookRequest extends ActionResolvedApi {
|
|
134
|
+
error?: Error;
|
|
135
|
+
}
|
|
136
|
+
export interface ActionHookResponse {
|
|
137
|
+
status: number;
|
|
138
|
+
headers: Record<string, string>;
|
|
139
|
+
data: unknown;
|
|
140
|
+
}
|
|
141
|
+
export interface ActionHookPreContext {
|
|
142
|
+
request: Readonly<ActionResolvedApi>;
|
|
143
|
+
}
|
|
144
|
+
export interface ActionHookPostContext {
|
|
145
|
+
request: Readonly<ActionHookRequest>;
|
|
146
|
+
response?: Readonly<ActionHookResponse>;
|
|
147
|
+
}
|
|
148
|
+
export interface ActionHooks {
|
|
149
|
+
pre?: (context: ActionHookPreContext) => void | Promise<void>;
|
|
150
|
+
post?: (context: ActionHookPostContext) => void | Promise<void>;
|
|
151
|
+
}
|
|
131
152
|
export interface ActionCallTransformerOptions {
|
|
132
153
|
request?: (api: ActionResolvedApi) => ActionResolvedApi;
|
|
133
154
|
response?: (data: unknown) => unknown;
|
|
134
155
|
}
|
|
135
156
|
export interface ActionCallCommitOptions {
|
|
136
157
|
mode?: ModelOneMode | ModelManyMode | Record<string, ModelOneMode | ModelManyMode>;
|
|
158
|
+
options?: ModelOneCommitOptions | ModelManyCommitOptions | Record<string, ModelOneCommitOptions | ModelManyCommitOptions>;
|
|
137
159
|
}
|
|
138
160
|
export interface ActionApiCallOptions extends ActionCallBaseOptions {
|
|
139
|
-
params?: Record<string, string>;
|
|
161
|
+
params?: Record<string, string | number>;
|
|
140
162
|
headers?: Record<string, string>;
|
|
141
163
|
query?: Record<string, unknown>;
|
|
142
164
|
body?: unknown;
|
|
@@ -96,6 +96,19 @@ function resolveCommitMode(commit, options) {
|
|
|
96
96
|
}
|
|
97
97
|
return commit.mode;
|
|
98
98
|
}
|
|
99
|
+
function resolveCommitOptions(commit, options) {
|
|
100
|
+
const override = options?.commit?.options;
|
|
101
|
+
if (!override) {
|
|
102
|
+
return commit.options;
|
|
103
|
+
}
|
|
104
|
+
const values = Object.values(override);
|
|
105
|
+
const perModel = values.length > 0 && values.every((value) => isPlainObject(value));
|
|
106
|
+
const resolved = perModel ? override[commit.model] : override;
|
|
107
|
+
if (!resolved) {
|
|
108
|
+
return commit.options;
|
|
109
|
+
}
|
|
110
|
+
return merge(resolved, commit.options);
|
|
111
|
+
}
|
|
99
112
|
function resolveCommitTransform(commit, data, context) {
|
|
100
113
|
if (typeof commit.transform === "function") {
|
|
101
114
|
return commit.transform(data, context);
|
|
@@ -120,6 +133,25 @@ function resolveConcurrent(definition, options) {
|
|
|
120
133
|
}
|
|
121
134
|
return ActionConcurrent.BLOCK;
|
|
122
135
|
}
|
|
136
|
+
async function executeHook(definition, hooks, key, context) {
|
|
137
|
+
const hook = hooks?.[key];
|
|
138
|
+
if (!hook) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
definition.logger?.debug("Action API hook", {
|
|
142
|
+
action: definition.key,
|
|
143
|
+
hook: key
|
|
144
|
+
});
|
|
145
|
+
try {
|
|
146
|
+
await hook(context);
|
|
147
|
+
} catch (error) {
|
|
148
|
+
definition.logger?.error("Action API hook error", {
|
|
149
|
+
action: definition.key,
|
|
150
|
+
hook: key,
|
|
151
|
+
error
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
123
155
|
async function executeApi(definition, api, options) {
|
|
124
156
|
try {
|
|
125
157
|
definition.logger?.debug("Action API request", {
|
|
@@ -137,7 +169,31 @@ async function executeApi(definition, api, options) {
|
|
|
137
169
|
body: api.body,
|
|
138
170
|
timeout: api.timeout,
|
|
139
171
|
signal: api.signal,
|
|
140
|
-
responseType: "json"
|
|
172
|
+
responseType: "json",
|
|
173
|
+
async onRequest() {
|
|
174
|
+
await executeHook(definition, definition.request.hooks, "pre", {
|
|
175
|
+
request: api
|
|
176
|
+
});
|
|
177
|
+
},
|
|
178
|
+
async onResponse({ response: response2 }) {
|
|
179
|
+
await executeHook(definition, definition.request.hooks, "post", {
|
|
180
|
+
request: api,
|
|
181
|
+
response: {
|
|
182
|
+
status: response2.status,
|
|
183
|
+
headers: Object.fromEntries(response2.headers),
|
|
184
|
+
data: response2._data
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
},
|
|
188
|
+
async onRequestError({ error }) {
|
|
189
|
+
await executeHook(definition, definition.request.hooks, "post", {
|
|
190
|
+
request: {
|
|
191
|
+
...api,
|
|
192
|
+
error
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
throw error;
|
|
196
|
+
}
|
|
141
197
|
});
|
|
142
198
|
definition.logger?.debug("Action API response received", {
|
|
143
199
|
action: definition.key,
|
|
@@ -191,11 +247,12 @@ function executeCommit(definition, model, data, context, options) {
|
|
|
191
247
|
});
|
|
192
248
|
}
|
|
193
249
|
const mode = resolveCommitMode(commit, options);
|
|
250
|
+
const commitOptions = resolveCommitOptions(commit, options);
|
|
194
251
|
let value = resolveCommitTransform(commit, data, context);
|
|
195
252
|
if (!isEmptyRecord(target.aliases())) {
|
|
196
253
|
value = resolveAliasInbound(value, target.aliases());
|
|
197
254
|
}
|
|
198
|
-
plan.push({ commit, target, mode, value });
|
|
255
|
+
plan.push({ commit, target, mode, options: commitOptions, value });
|
|
199
256
|
}
|
|
200
257
|
} catch (error) {
|
|
201
258
|
const commitError = toError(error, ActionCommitError);
|
|
@@ -213,7 +270,7 @@ function executeCommit(definition, model, data, context, options) {
|
|
|
213
270
|
mode: entry.mode
|
|
214
271
|
});
|
|
215
272
|
try {
|
|
216
|
-
entry.target.commit(entry.mode, entry.value, entry.
|
|
273
|
+
entry.target.commit(entry.mode, entry.value, entry.options);
|
|
217
274
|
} catch (error) {
|
|
218
275
|
const commitError = toError(error, ActionCommitError);
|
|
219
276
|
definition.logger?.error("Action commit error", {
|
|
@@ -297,6 +354,7 @@ export function createAction(definition, model, view) {
|
|
|
297
354
|
);
|
|
298
355
|
const context = {
|
|
299
356
|
request: { url, method, headers, query, body },
|
|
357
|
+
params: options?.params ?? {},
|
|
300
358
|
view
|
|
301
359
|
};
|
|
302
360
|
data = executeCommit(definition, model, response, context, options);
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type { ModelOneCommitOptions, ModelManyCommitOptions } from "./core/types
|
|
|
7
7
|
export { ViewClone } from "./core/types/view.js";
|
|
8
8
|
export type { ViewDefinitionOptions } from "./core/types/view.js";
|
|
9
9
|
export { ActionStatus, ActionConcurrent, ActionType, ActionApiMethod } from "./core/types/action.js";
|
|
10
|
-
export type { ActionCall, ActionApiCall, ActionApiCommitContext, ActionHandlerCall, ActionCallOptions, ActionCallBaseOptions, ActionApiCallOptions, ActionHandlerCallOptions, ActionCallTransformerOptions, ActionCallBindOptions, ActionCallCommitOptions, ActionHandlerOptions, ActionResolvedApi, } from "./core/types/action.js";
|
|
10
|
+
export type { ActionCall, ActionApiCall, ActionApiCommitContext, ActionHandlerCall, ActionCallOptions, ActionCallBaseOptions, ActionApiCallOptions, ActionHandlerCallOptions, ActionCallTransformerOptions, ActionCallBindOptions, ActionCallCommitOptions, ActionHandlerOptions, ActionResolvedApi, ActionHooks, ActionHookPreContext, ActionHookPostContext, ActionHookRequest, ActionHookResponse, } from "./core/types/action.js";
|
|
11
11
|
export { ActionApiError, ActionHandlerError, ActionCommitError, ActionConcurrentError, isError, toError, } from "./core/utils/error.js";
|
|
12
12
|
export type { ComposeCallback, ComposeCall, ComposeDefinitions, ComposeContext, StoreCompose, } from "./core/types/compose.js";
|
|
13
13
|
export { useStoreCompose } from "./composables/compose.js";
|