@diphyx/harlemify 5.1.0 → 5.2.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/dist/module.d.mts CHANGED
@@ -4,13 +4,13 @@ interface RuntimeModelConfig {
4
4
  identifier?: string;
5
5
  }
6
6
 
7
+ interface RuntimeViewConfig {
8
+ clone?: ViewClone;
9
+ }
7
10
  declare enum ViewClone {
8
11
  SHALLOW = "shallow",
9
12
  DEEP = "deep"
10
13
  }
11
- interface RuntimeViewConfig {
12
- clone?: ViewClone;
13
- }
14
14
 
15
15
  interface RuntimeActionConfig {
16
16
  endpoint?: string;
package/dist/module.d.ts CHANGED
@@ -4,13 +4,13 @@ interface RuntimeModelConfig {
4
4
  identifier?: string;
5
5
  }
6
6
 
7
+ interface RuntimeViewConfig {
8
+ clone?: ViewClone;
9
+ }
7
10
  declare enum ViewClone {
8
11
  SHALLOW = "shallow",
9
12
  DEEP = "deep"
10
13
  }
11
- interface RuntimeViewConfig {
12
- clone?: ViewClone;
13
- }
14
14
 
15
15
  interface RuntimeActionConfig {
16
16
  endpoint?: string;
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.0.0 || >=4.0.0"
6
6
  },
7
- "version": "5.1.0",
7
+ "version": "5.2.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "unknown"
@@ -12,6 +12,6 @@ export type UseStoreAction<T> = {
12
12
  };
13
13
  export declare function useIsolatedActionError(): Ref<Error | null>;
14
14
  export declare function useIsolatedActionStatus(): Ref<ActionStatus>;
15
- export declare function useStoreAction<A extends Record<string, ActionCall>, K extends keyof A & string, T = Awaited<ReturnType<A[K]>>>(store: {
15
+ export declare function useStoreAction<A extends Record<string, ActionCall<any>>, K extends keyof A & string, T = Awaited<ReturnType<A[K]>>>(store: {
16
16
  action: A;
17
17
  }, key: K, options?: UseStoreActionOptions): UseStoreAction<T>;
@@ -1,5 +1,7 @@
1
1
  import { ref, computed } from "vue";
2
- import { ActionStatus } from "../core/types/action.js";
2
+ import {
3
+ ActionStatus
4
+ } from "../core/types/action.js";
3
5
  export function useIsolatedActionError() {
4
6
  return ref(null);
5
7
  }
@@ -1,46 +1,69 @@
1
+ import { wrapBaseDefinition } from "../utils/base.js";
1
2
  import {
2
3
  ActionApiMethod
3
4
  } from "../types/action.js";
4
5
  export function createActionFactory(config, logger) {
5
6
  function apiCall(request, commit) {
6
- const mergedRequest = {
7
- endpoint: config?.endpoint,
8
- headers: config?.headers,
9
- query: config?.query,
10
- timeout: config?.timeout,
11
- concurrent: config?.concurrent,
12
- ...request
13
- };
14
- let key = "";
15
- return {
16
- get key() {
17
- return key;
7
+ return wrapBaseDefinition({
8
+ request: {
9
+ endpoint: config?.endpoint,
10
+ headers: config?.headers,
11
+ query: config?.query,
12
+ timeout: config?.timeout,
13
+ concurrent: config?.concurrent,
14
+ ...request
18
15
  },
19
- setKey(value) {
20
- key = value;
21
- },
22
- request: mergedRequest,
23
16
  commit,
24
17
  logger
25
- };
18
+ });
26
19
  }
27
20
  function apiGet(request, commit) {
28
21
  return apiCall({ ...request, method: ActionApiMethod.GET }, commit);
29
22
  }
30
23
  function apiHead(request, commit) {
31
- return apiCall({ ...request, method: ActionApiMethod.HEAD }, commit);
24
+ return apiCall(
25
+ {
26
+ ...request,
27
+ method: ActionApiMethod.HEAD
28
+ },
29
+ commit
30
+ );
32
31
  }
33
32
  function apiPost(request, commit) {
34
- return apiCall({ ...request, method: ActionApiMethod.POST }, commit);
33
+ return apiCall(
34
+ {
35
+ ...request,
36
+ method: ActionApiMethod.POST
37
+ },
38
+ commit
39
+ );
35
40
  }
36
41
  function apiPut(request, commit) {
37
- return apiCall({ ...request, method: ActionApiMethod.PUT }, commit);
42
+ return apiCall(
43
+ {
44
+ ...request,
45
+ method: ActionApiMethod.PUT
46
+ },
47
+ commit
48
+ );
38
49
  }
39
50
  function apiPatch(request, commit) {
40
- return apiCall({ ...request, method: ActionApiMethod.PATCH }, commit);
51
+ return apiCall(
52
+ {
53
+ ...request,
54
+ method: ActionApiMethod.PATCH
55
+ },
56
+ commit
57
+ );
41
58
  }
42
59
  function apiDelete(request, commit) {
43
- return apiCall({ ...request, method: ActionApiMethod.DELETE }, commit);
60
+ return apiCall(
61
+ {
62
+ ...request,
63
+ method: ActionApiMethod.DELETE
64
+ },
65
+ commit
66
+ );
44
67
  }
45
68
  const api = Object.assign(apiCall, {
46
69
  get: apiGet,
@@ -50,18 +73,15 @@ export function createActionFactory(config, logger) {
50
73
  patch: apiPatch,
51
74
  delete: apiDelete
52
75
  });
53
- function handler(callback) {
54
- let key = "";
55
- return {
56
- get key() {
57
- return key;
58
- },
59
- setKey(value) {
60
- key = value;
61
- },
76
+ function handler(callback, options) {
77
+ return wrapBaseDefinition({
62
78
  callback,
79
+ options: {
80
+ concurrent: config?.concurrent,
81
+ ...options
82
+ },
63
83
  logger
64
- };
84
+ });
65
85
  }
66
86
  return {
67
87
  api,
@@ -1,16 +1,10 @@
1
+ import { wrapBaseDefinition } from "../utils/base.js";
1
2
  import {
2
3
  ModelKind
3
4
  } from "../types/model.js";
4
5
  export function createModelFactory(config, logger) {
5
6
  function one(shape, options) {
6
- let key = "";
7
- return {
8
- get key() {
9
- return key;
10
- },
11
- setKey(value) {
12
- key = value;
13
- },
7
+ return wrapBaseDefinition({
14
8
  shape,
15
9
  kind: ModelKind.OBJECT,
16
10
  options: {
@@ -18,17 +12,10 @@ export function createModelFactory(config, logger) {
18
12
  ...options
19
13
  },
20
14
  logger
21
- };
15
+ });
22
16
  }
23
17
  function many(shape, options) {
24
- let key = "";
25
- return {
26
- get key() {
27
- return key;
28
- },
29
- setKey(value) {
30
- key = value;
31
- },
18
+ return wrapBaseDefinition({
32
19
  shape,
33
20
  kind: ModelKind.ARRAY,
34
21
  options: {
@@ -36,7 +23,7 @@ export function createModelFactory(config, logger) {
36
23
  ...options
37
24
  },
38
25
  logger
39
- };
26
+ });
40
27
  }
41
28
  return {
42
29
  one,
@@ -1,13 +1,7 @@
1
+ import { wrapBaseDefinition } from "../utils/base.js";
1
2
  export function createViewFactory(config, logger) {
2
3
  function from(model, resolver, options) {
3
- let key = "";
4
- const definition = {
5
- get key() {
6
- return key;
7
- },
8
- setKey(value) {
9
- key = value;
10
- },
4
+ return wrapBaseDefinition({
11
5
  model: [model],
12
6
  resolver,
13
7
  options: {
@@ -15,18 +9,10 @@ export function createViewFactory(config, logger) {
15
9
  ...options
16
10
  },
17
11
  logger
18
- };
19
- return definition;
12
+ });
20
13
  }
21
14
  function merge(models, resolver, options) {
22
- let key = "";
23
- return {
24
- get key() {
25
- return key;
26
- },
27
- setKey(value) {
28
- key = value;
29
- },
15
+ return wrapBaseDefinition({
30
16
  models,
31
17
  resolver,
32
18
  options: {
@@ -34,7 +20,7 @@ export function createViewFactory(config, logger) {
34
20
  ...options
35
21
  },
36
22
  logger
37
- };
23
+ });
38
24
  }
39
25
  return {
40
26
  from,
@@ -52,18 +52,21 @@ export interface ActionApiDefinition<MD extends ModelDefinitions, VD extends Vie
52
52
  request: ActionApiRequest<MD, VD>;
53
53
  commit?: ActionApiCommit<MD>;
54
54
  }
55
+ export interface ActionHandlerOptions {
56
+ payload?: unknown;
57
+ concurrent?: ActionConcurrent;
58
+ }
55
59
  export type ActionHandlerCallback<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>, R = void> = (context: {
56
60
  model: StoreModel<MD>;
57
61
  view: StoreView<MD, VD>;
62
+ payload: unknown;
58
63
  }) => Promise<R>;
59
64
  export interface ActionHandlerDefinition<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>, R = void> extends BaseDefinition {
60
65
  callback: ActionHandlerCallback<MD, VD, R>;
66
+ options?: ActionHandlerOptions;
61
67
  }
62
68
  export type ActionDefinition<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>> = ActionApiDefinition<MD, VD> | ActionHandlerDefinition<MD, VD, unknown>;
63
69
  export type ActionDefinitions<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>> = Record<string, ActionDefinition<MD, VD>>;
64
- export type StoreAction<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>, AD extends ActionDefinitions<MD, VD>> = {
65
- [K in keyof AD]: ActionCall;
66
- };
67
70
  export interface ActionApiFactory<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>> {
68
71
  (request: ActionApiRequest<MD, VD>, commit?: ActionApiCommit<MD>): ActionApiDefinition<MD, VD>;
69
72
  get(request: ActionApiRequestShortcut<MD, VD>, commit?: ActionApiCommit<MD>): ActionApiDefinition<MD, VD>;
@@ -74,7 +77,7 @@ export interface ActionApiFactory<MD extends ModelDefinitions, VD extends ViewDe
74
77
  delete(request: ActionApiRequestShortcut<MD, VD>, commit?: ActionApiCommit<MD>): ActionApiDefinition<MD, VD>;
75
78
  }
76
79
  export interface ActionHandlerFactory<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>> {
77
- <R>(callback: ActionHandlerCallback<MD, VD, R>): ActionHandlerDefinition<MD, VD, R>;
80
+ <R>(callback: ActionHandlerCallback<MD, VD, R>, options?: ActionHandlerOptions): ActionHandlerDefinition<MD, VD, R>;
78
81
  }
79
82
  export interface ActionFactory<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>> {
80
83
  api: ActionApiFactory<MD, VD>;
@@ -84,8 +87,9 @@ export interface ActionCallBindOptions {
84
87
  status?: Ref<ActionStatus>;
85
88
  error?: Ref<Error | null>;
86
89
  }
87
- export interface ActionCallCommitOptions {
88
- mode?: ModelOneMode | ModelManyMode;
90
+ export interface ActionCallBaseOptions {
91
+ concurrent?: ActionConcurrent;
92
+ bind?: ActionCallBindOptions;
89
93
  }
90
94
  export interface ActionResolvedApi {
91
95
  url: string;
@@ -100,7 +104,10 @@ export interface ActionCallTransformerOptions {
100
104
  request?: (api: ActionResolvedApi) => ActionResolvedApi;
101
105
  response?: (data: unknown) => unknown;
102
106
  }
103
- export interface ActionCallOptions {
107
+ export interface ActionCallCommitOptions {
108
+ mode?: ModelOneMode | ModelManyMode;
109
+ }
110
+ export interface ActionApiCallOptions extends ActionCallBaseOptions {
104
111
  params?: Record<string, string>;
105
112
  headers?: Record<string, string>;
106
113
  query?: Record<string, unknown>;
@@ -108,14 +115,30 @@ export interface ActionCallOptions {
108
115
  timeout?: number;
109
116
  signal?: AbortSignal;
110
117
  transformer?: ActionCallTransformerOptions;
111
- concurrent?: ActionConcurrent;
112
- bind?: ActionCallBindOptions;
113
118
  commit?: ActionCallCommitOptions;
114
119
  }
115
- export interface ActionCall<T = void> {
116
- (options?: ActionCallOptions): Promise<T>;
120
+ export interface ActionResolvedHandler<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>> {
121
+ model: StoreModel<MD>;
122
+ view: StoreView<MD, VD>;
123
+ payload: unknown;
124
+ }
125
+ export interface ActionHandlerCallOptions extends ActionCallBaseOptions {
126
+ payload?: unknown;
127
+ }
128
+ export type ActionCallOptions = ActionApiCallOptions | ActionHandlerCallOptions;
129
+ export interface ActionCallBase {
117
130
  readonly error: Readonly<Ref<Error | null>>;
118
131
  readonly status: Readonly<Ref<ActionStatus>>;
119
132
  readonly loading: ComputedRef<boolean>;
120
133
  reset: () => void;
121
134
  }
135
+ export interface ActionApiCall<T = void> extends ActionCallBase {
136
+ (options?: ActionApiCallOptions): Promise<T>;
137
+ }
138
+ export interface ActionHandlerCall<T = void> extends ActionCallBase {
139
+ (options?: ActionHandlerCallOptions): Promise<T>;
140
+ }
141
+ export type ActionCall<T = void> = ActionApiCall<T> | ActionHandlerCall<T>;
142
+ export type StoreAction<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>, AD extends ActionDefinitions<MD, VD>> = {
143
+ [K in keyof AD]: AD[K] extends ActionApiDefinition<MD, VD> ? ActionApiCall : AD[K] extends ActionHandlerDefinition<MD, VD, infer R> ? ActionHandlerCall<R> : never;
144
+ };
@@ -1,11 +1,11 @@
1
1
  import type { ModelDefinitions, ModelFactory, StoreModel } from "./model.js";
2
2
  import type { ViewDefinitions, ViewFactory, StoreView } from "./view.js";
3
- import type { ActionDefinition, ActionDefinitions, ActionFactory, StoreAction } from "./action.js";
4
- export interface StoreConfig<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>, _AD extends ActionDefinitions<MD, VD>> {
3
+ import type { ActionDefinitions, ActionFactory, StoreAction } from "./action.js";
4
+ export interface StoreConfig<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>, AD extends ActionDefinitions<MD, VD>> {
5
5
  name: string;
6
6
  model: (factory: ModelFactory) => MD;
7
7
  view: (factory: ViewFactory<MD>) => VD;
8
- action: (factory: ActionFactory<MD, VD>) => Record<string, ActionDefinition<MD, VD>>;
8
+ action: (factory: ActionFactory<MD, VD>) => AD;
9
9
  }
10
10
  export interface Store<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>, AD extends ActionDefinitions<MD, VD>> {
11
11
  model: StoreModel<MD>;
@@ -1,13 +1,13 @@
1
1
  import type { ComputedRef } from "vue";
2
2
  import type { BaseDefinition } from "./base.js";
3
3
  import type { ModelDefinitions, ModelDefinitionInfer, ModelDefinitionInferTuple } from "./model.js";
4
+ export interface RuntimeViewConfig {
5
+ clone?: ViewClone;
6
+ }
4
7
  export declare enum ViewClone {
5
8
  SHALLOW = "shallow",
6
9
  DEEP = "deep"
7
10
  }
8
- export interface RuntimeViewConfig {
9
- clone?: ViewClone;
10
- }
11
11
  export interface ViewDefinitionOptions {
12
12
  clone?: ViewClone;
13
13
  }
@@ -77,13 +77,22 @@ function resolveApiSignal(options, abortController) {
77
77
  }
78
78
  return abortController.signal;
79
79
  }
80
- function resolveCommitTarget(commit, model) {
80
+ function resolveHandlerPayload(definition, options) {
81
+ if (options?.payload !== void 0) {
82
+ return options.payload;
83
+ }
84
+ if (definition.options?.payload !== void 0) {
85
+ return definition.options.payload;
86
+ }
87
+ return void 0;
88
+ }
89
+ function resolveApiCommitTarget(commit, model) {
81
90
  if (commit) {
82
91
  return model[commit.model];
83
92
  }
84
93
  return void 0;
85
94
  }
86
- function resolveCommitMode(commit, options) {
95
+ function resolveApiCommitMode(commit, options) {
87
96
  if (commit) {
88
97
  if (options?.commit?.mode) {
89
98
  return options.commit.mode;
@@ -92,14 +101,17 @@ function resolveCommitMode(commit, options) {
92
101
  }
93
102
  return void 0;
94
103
  }
95
- function resolveCommitValue(commit, data) {
104
+ function resolveApiCommitValue(commit, data) {
96
105
  if (typeof commit.value === "function") {
97
106
  return commit.value(data);
98
107
  }
99
108
  return data;
100
109
  }
101
110
  function isApiDefinition(definition) {
102
- return "request" in definition;
111
+ return !("callback" in definition);
112
+ }
113
+ function isHandlerDefinition(definition) {
114
+ return "callback" in definition;
103
115
  }
104
116
  function resolveConcurrent(definition, options) {
105
117
  if (options?.concurrent) {
@@ -108,6 +120,9 @@ function resolveConcurrent(definition, options) {
108
120
  if (isApiDefinition(definition) && definition.request.concurrent) {
109
121
  return definition.request.concurrent;
110
122
  }
123
+ if (isHandlerDefinition(definition) && definition.options?.concurrent) {
124
+ return definition.options.concurrent;
125
+ }
111
126
  return ActionConcurrent.BLOCK;
112
127
  }
113
128
  async function executeApi(definition, api, options) {
@@ -147,15 +162,13 @@ async function executeApi(definition, api, options) {
147
162
  throw fetchError;
148
163
  }
149
164
  }
150
- async function executeHandler(definition, model, view) {
165
+ async function executeHandler(definition, handler) {
151
166
  try {
152
167
  definition.logger?.debug("Action handler phase", {
153
168
  action: definition.key
154
169
  });
155
- return await definition.callback({
156
- model,
157
- view
158
- });
170
+ const data = await definition.callback(handler);
171
+ return data;
159
172
  } catch (error) {
160
173
  if (isError(error, ActionApiError, ActionHandlerError)) {
161
174
  throw error;
@@ -186,7 +199,7 @@ function executeCommit(definition, target, mode, data) {
186
199
  if (!isEmptyRecord(target.aliases())) {
187
200
  data = resolveAliasInbound(data, target.aliases());
188
201
  }
189
- const value = resolveCommitValue(definition.commit, data);
202
+ const value = resolveApiCommitValue(definition.commit, data);
190
203
  target.commit(mode, value, definition.commit.options);
191
204
  } catch (error) {
192
205
  const commitError = toError(error, ActionCommitError);
@@ -241,10 +254,10 @@ export function createAction(definition, model, view) {
241
254
  activeError.value = null;
242
255
  currentController = (async () => {
243
256
  try {
244
- let data;
257
+ let data = void 0;
245
258
  if (isApiDefinition(definition)) {
246
- const target = resolveCommitTarget(definition.commit, model);
247
- const mode = resolveCommitMode(definition.commit, options);
259
+ const target = resolveApiCommitTarget(definition.commit, model);
260
+ const mode = resolveApiCommitMode(definition.commit, options);
248
261
  const url = resolveApiUrl(definition, view, options);
249
262
  const method = resolveApiMethod(definition, view);
250
263
  const headers = resolveApiHeaders(definition, view, options);
@@ -266,8 +279,13 @@ export function createAction(definition, model, view) {
266
279
  options
267
280
  );
268
281
  executeCommit(definition, target, mode, data);
269
- } else {
270
- data = await executeHandler(definition, model, view);
282
+ } else if (isHandlerDefinition(definition)) {
283
+ const payload = resolveHandlerPayload(definition, options);
284
+ data = await executeHandler(definition, {
285
+ model,
286
+ view,
287
+ payload
288
+ });
271
289
  }
272
290
  activeStatus.value = ActionStatus.SUCCESS;
273
291
  definition.logger?.debug("Action success", {
@@ -1,3 +1,5 @@
1
+ import type { BaseDefinition } from "../types/base.js";
2
+ export declare function wrapBaseDefinition<T extends Omit<BaseDefinition, "key" | "setKey">>(definition: T): T & BaseDefinition;
1
3
  export declare function trimStart(value: string, char: string): string;
2
4
  export declare function trimEnd(value: string, char: string): string;
3
5
  export declare function isObject(value: unknown): value is object;
@@ -1,3 +1,22 @@
1
+ export function wrapBaseDefinition(definition) {
2
+ let key = "";
3
+ return Object.defineProperties(definition, {
4
+ key: {
5
+ get() {
6
+ return key;
7
+ },
8
+ enumerable: true,
9
+ configurable: true
10
+ },
11
+ setKey: {
12
+ value(value) {
13
+ key = value;
14
+ },
15
+ enumerable: true,
16
+ configurable: true
17
+ }
18
+ });
19
+ }
1
20
  export function trimStart(value, char) {
2
21
  return value.replace(new RegExp(`^${char}+`), "");
3
22
  }
@@ -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, ActionApiMethod } from "./core/types/action.js";
10
- export type { ActionCall, ActionCallOptions, ActionCallTransformerOptions, ActionCallBindOptions, ActionCallCommitOptions, ActionResolvedApi, } from "./core/types/action.js";
10
+ export type { ActionCall, ActionApiCall, ActionHandlerCall, ActionCallOptions, ActionCallBaseOptions, ActionApiCallOptions, ActionHandlerCallOptions, ActionCallTransformerOptions, ActionCallBindOptions, ActionCallCommitOptions, ActionHandlerOptions, ActionResolvedApi, } from "./core/types/action.js";
11
11
  export { ActionApiError, ActionHandlerError, ActionCommitError, ActionConcurrentError } from "./core/utils/error.js";
12
12
  export { useIsolatedActionStatus, useIsolatedActionError, useStoreAction } from "./composables/action.js";
13
13
  export type { UseStoreActionOptions, UseStoreAction } from "./composables/action.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diphyx/harlemify",
3
- "version": "5.1.0",
3
+ "version": "5.2.0",
4
4
  "description": "API state management for Nuxt powered by Harlem",
5
5
  "keywords": [
6
6
  "nuxt",