@qualisero/openapi-endpoint 0.12.3 → 0.14.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 +135 -252
- package/dist/cli.js +1318 -58
- package/dist/index.d.ts +9 -213
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -143
- package/dist/openapi-helpers.d.ts +4 -17
- package/dist/openapi-helpers.d.ts.map +1 -1
- package/dist/openapi-helpers.js +3 -93
- package/dist/openapi-mutation.d.ts +48 -111
- package/dist/openapi-mutation.d.ts.map +1 -1
- package/dist/openapi-mutation.js +75 -104
- package/dist/openapi-query.d.ts +46 -209
- package/dist/openapi-query.d.ts.map +1 -1
- package/dist/openapi-query.js +50 -88
- package/dist/openapi-utils.d.ts +31 -4
- package/dist/openapi-utils.d.ts.map +1 -1
- package/dist/openapi-utils.js +45 -56
- package/dist/types.d.ts +250 -280
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +11 -0
- package/package.json +3 -2
- package/dist/openapi-endpoint.d.ts +0 -18
- package/dist/openapi-endpoint.d.ts.map +0 -1
- package/dist/openapi-endpoint.js +0 -24
- package/dist/types-documentation.d.ts +0 -158
- package/dist/types-documentation.d.ts.map +0 -1
- package/dist/types-documentation.js +0 -9
|
@@ -1,118 +1,55 @@
|
|
|
1
|
-
import { type ComputedRef, type Ref
|
|
2
|
-
import
|
|
3
|
-
import { type OpenApiHelpers } from './openapi-helpers';
|
|
1
|
+
import { type ComputedRef, type Ref } from 'vue';
|
|
2
|
+
import type { MaybeRefOrGetter } from '@vue/reactivity';
|
|
4
3
|
import { type AxiosResponse } from 'axios';
|
|
5
|
-
|
|
4
|
+
import { type EndpointConfig, type MutationOptions, type MutateFn, type MutateAsyncFn } from './types';
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
8
|
-
* Ensures the operation is a mutation (POST/PUT/PATCH/DELETE) at runtime.
|
|
9
|
-
* Returns a reactive mutation object, including helpers for query key and enabled state.
|
|
6
|
+
* Return type of `useEndpointMutation` (the `useMutation` composable on a generated namespace).
|
|
10
7
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* @template TResponse Response data type
|
|
9
|
+
* @template TPathParams Path parameters type (concrete, required values)
|
|
10
|
+
* @template TRequest Request body type (`never` if none)
|
|
11
|
+
* @template TQueryParams Query parameters type
|
|
13
12
|
*
|
|
14
|
-
* @
|
|
15
|
-
* @param operationId The OpenAPI operation ID to mutate.
|
|
16
|
-
* @param pathParams Optional path parameters for the endpoint, can be reactive.
|
|
17
|
-
* @param options Optional mutation options, including Vue Query options and custom axios options:
|
|
18
|
-
* - 'dontUpdateCache': If true, will not update cache with returned data (default: false)
|
|
19
|
-
* - 'dontInvalidate': If true, will not invalidate matching GET queries (default: false)
|
|
20
|
-
* - 'invalidateOperations': List of additional OperationIds to invalidate after mutation (can also be a map of OperationId to path parameters)
|
|
21
|
-
* - 'refetchEndpoints': List of additional EndpointQueryReturn objects to refetch after mutation
|
|
22
|
-
* - `axiosOptions`: Custom axios request options (e.g., headers, params)
|
|
23
|
-
* - All properties from {@link UseMutationOptions} (from @tanstack/vue-query)
|
|
24
|
-
* @throws Error if the operation is not a mutation operation.
|
|
25
|
-
* @returns Mutation object with
|
|
26
|
-
* - `data`: ComputedRef of response data.
|
|
27
|
-
* - `isEnabled`: ComputedRef indicating if mutation can be executed (path resolved).
|
|
28
|
-
* - `extraPathParams`: Ref to set of additional path parameters when calling mutate.
|
|
29
|
-
* - `mutate` and `mutateAsync`: Functions to trigger the mutation, taking an object with:
|
|
30
|
-
* - `data`: The request body data for the mutation.
|
|
31
|
-
* - `pathParams`: Optional additional path parameters for the mutation.
|
|
32
|
-
* - `axiosOptions`: Optional axios configuration overrides for this specific mutation call.
|
|
33
|
-
* - `dontUpdateCache`, `dontInvalidate`, `invalidateOperations`, `refetchEndpoints`: Same as options, but can be set per-mutation.
|
|
34
|
-
* - All other properties and methods from the underlying Vue Query mutation object.
|
|
13
|
+
* @group Types
|
|
35
14
|
*/
|
|
36
|
-
export
|
|
37
|
-
|
|
38
|
-
data: ComputedRef<AxiosResponse<
|
|
15
|
+
export interface MutationReturn<TResponse, TPathParams extends Record<string, unknown> = Record<string, never>, TRequest = never, TQueryParams extends Record<string, unknown> = Record<string, never>> {
|
|
16
|
+
/** The Axios response (undefined until mutation completes). */
|
|
17
|
+
data: ComputedRef<AxiosResponse<TResponse> | undefined>;
|
|
18
|
+
/** The error if the mutation failed. */
|
|
19
|
+
error: Ref<Error | null>;
|
|
20
|
+
/** True while the mutation is in progress. */
|
|
21
|
+
isPending: Ref<boolean>;
|
|
22
|
+
/** True when the mutation succeeded. */
|
|
23
|
+
isSuccess: Ref<boolean>;
|
|
24
|
+
/** True when the mutation failed. */
|
|
25
|
+
isError: Ref<boolean>;
|
|
26
|
+
/** Execute the mutation (non-blocking). */
|
|
27
|
+
mutate: MutateFn<TPathParams, TRequest, TQueryParams>;
|
|
28
|
+
/** Execute the mutation and await the response. */
|
|
29
|
+
mutateAsync: MutateAsyncFn<TResponse, TPathParams, TRequest, TQueryParams>;
|
|
30
|
+
/** Reset the mutation state. */
|
|
31
|
+
reset: () => void;
|
|
32
|
+
/** Whether the mutation can execute (all required path params are resolved). */
|
|
39
33
|
isEnabled: ComputedRef<boolean>;
|
|
40
|
-
|
|
41
|
-
pathParams: ComputedRef<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
pathParams: ComputedRef<GetPathParameters<Ops, Op>>;
|
|
62
|
-
context: Ref<unknown, unknown>;
|
|
63
|
-
error: Ref<null, null>;
|
|
64
|
-
isError: Ref<false, false>;
|
|
65
|
-
isPending: Ref<true, true>;
|
|
66
|
-
isSuccess: Ref<false, false>;
|
|
67
|
-
status: Ref<"pending", "pending">;
|
|
68
|
-
failureCount: Ref<number, number>;
|
|
69
|
-
failureReason: Ref<Error | null, Error | null>;
|
|
70
|
-
isPaused: Ref<boolean, boolean>;
|
|
71
|
-
variables: import("@vue/shared").IfAny<GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, Ref<GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>>, [GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>] extends [Ref<any, any>] ? Ref<any, any> & (GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>) : Ref<GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>>>;
|
|
72
|
-
isIdle: Ref<false, false>;
|
|
73
|
-
submittedAt: Ref<number, number>;
|
|
74
|
-
mutate: (variables: GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, options?: import("@tanstack/query-core").MutateOptions<AxiosResponse<any, any, {}>, Error, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, unknown> | undefined) => void;
|
|
75
|
-
mutateAsync: import("@tanstack/query-core").MutateFunction<AxiosResponse<any, any, {}>, Error, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, unknown>;
|
|
76
|
-
reset: import("@tanstack/query-core").MutationObserverResult<TData, TError, TVariables, TOnMutateResult>["reset"];
|
|
77
|
-
} | {
|
|
78
|
-
data: ComputedRef<AxiosResponse<GetResponseData<Ops, Op>> | undefined>;
|
|
79
|
-
isEnabled: ComputedRef<boolean>;
|
|
80
|
-
extraPathParams: Ref<GetPathParameters<Ops, Op>, GetPathParameters<Ops, Op>>;
|
|
81
|
-
pathParams: ComputedRef<GetPathParameters<Ops, Op>>;
|
|
82
|
-
context: Ref<unknown, unknown>;
|
|
83
|
-
error: Ref<Error, Error>;
|
|
84
|
-
isError: Ref<true, true>;
|
|
85
|
-
isPending: Ref<false, false>;
|
|
86
|
-
isSuccess: Ref<false, false>;
|
|
87
|
-
status: Ref<"error", "error">;
|
|
88
|
-
failureCount: Ref<number, number>;
|
|
89
|
-
failureReason: Ref<Error | null, Error | null>;
|
|
90
|
-
isPaused: Ref<boolean, boolean>;
|
|
91
|
-
variables: import("@vue/shared").IfAny<GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, Ref<GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>>, [GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>] extends [Ref<any, any>] ? Ref<any, any> & (GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>) : Ref<GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>>>;
|
|
92
|
-
isIdle: Ref<false, false>;
|
|
93
|
-
submittedAt: Ref<number, number>;
|
|
94
|
-
mutate: (variables: GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, options?: import("@tanstack/query-core").MutateOptions<AxiosResponse<any, any, {}>, Error, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, unknown> | undefined) => void;
|
|
95
|
-
mutateAsync: import("@tanstack/query-core").MutateFunction<AxiosResponse<any, any, {}>, Error, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, unknown>;
|
|
96
|
-
reset: import("@tanstack/query-core").MutationObserverResult<TData, TError, TVariables, TOnMutateResult>["reset"];
|
|
97
|
-
} | {
|
|
98
|
-
data: ComputedRef<AxiosResponse<GetResponseData<Ops, Op>> | undefined>;
|
|
99
|
-
isEnabled: ComputedRef<boolean>;
|
|
100
|
-
extraPathParams: Ref<GetPathParameters<Ops, Op>, GetPathParameters<Ops, Op>>;
|
|
101
|
-
pathParams: ComputedRef<GetPathParameters<Ops, Op>>;
|
|
102
|
-
context: Ref<unknown, unknown>;
|
|
103
|
-
error: Ref<null, null>;
|
|
104
|
-
isError: Ref<false, false>;
|
|
105
|
-
isPending: Ref<false, false>;
|
|
106
|
-
isSuccess: Ref<true, true>;
|
|
107
|
-
status: Ref<"success", "success">;
|
|
108
|
-
failureCount: Ref<number, number>;
|
|
109
|
-
failureReason: Ref<Error | null, Error | null>;
|
|
110
|
-
isPaused: Ref<boolean, boolean>;
|
|
111
|
-
variables: import("@vue/shared").IfAny<GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, Ref<GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>>, [GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>] extends [Ref<any, any>] ? Ref<any, any> & (GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>) : Ref<GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>>>;
|
|
112
|
-
isIdle: Ref<false, false>;
|
|
113
|
-
submittedAt: Ref<number, number>;
|
|
114
|
-
mutate: (variables: GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, options?: import("@tanstack/query-core").MutateOptions<AxiosResponse<any, any, {}>, Error, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, unknown> | undefined) => void;
|
|
115
|
-
mutateAsync: import("@tanstack/query-core").MutateFunction<AxiosResponse<any, any, {}>, Error, GetRequestBody<Ops, Op> extends never ? void | QMutationVars<Ops, Op> : QMutationVars<Ops, Op>, unknown>;
|
|
116
|
-
reset: import("@tanstack/query-core").MutationObserverResult<TData, TError, TVariables, TOnMutateResult>["reset"];
|
|
117
|
-
};
|
|
34
|
+
/** The resolved path parameters. */
|
|
35
|
+
pathParams: ComputedRef<TPathParams>;
|
|
36
|
+
/** Additional path params that can be supplied at mutation time. */
|
|
37
|
+
extraPathParams: Ref<TPathParams>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Execute a type-safe mutation (POST/PUT/PATCH/DELETE) with automatic cache management.
|
|
41
|
+
*
|
|
42
|
+
* This is a low-level primitive — in normal usage it is called by the generated
|
|
43
|
+
* per-operation `useMutation` wrappers in `api-client.ts`, not directly.
|
|
44
|
+
*
|
|
45
|
+
* @template TResponse The response data type
|
|
46
|
+
* @template TPathParams The path parameters type (concrete, required values)
|
|
47
|
+
* @template TRequest The request body type (`never` if no body)
|
|
48
|
+
* @template TQueryParams The query parameters type
|
|
49
|
+
*
|
|
50
|
+
* @param config Endpoint config: axios instance, queryClient, path, method, listPath, operationsRegistry
|
|
51
|
+
* @param pathParams Path parameters (reactive). Pass `undefined` for operations without path params.
|
|
52
|
+
* @param options Mutation options (dontInvalidate, refetchEndpoints, etc.)
|
|
53
|
+
*/
|
|
54
|
+
export declare function useEndpointMutation<TResponse, TPathParams extends Record<string, unknown> = Record<string, never>, TRequest = never, TQueryParams extends Record<string, unknown> = Record<string, never>>(config: EndpointConfig, pathParams?: MaybeRefOrGetter<Record<string, string | number | undefined> | null | undefined>, options?: MutationOptions<TResponse, TPathParams, TRequest, TQueryParams>): MutationReturn<TResponse, TPathParams, TRequest, TQueryParams>;
|
|
118
55
|
//# sourceMappingURL=openapi-mutation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi-mutation.d.ts","sourceRoot":"","sources":["../src/openapi-mutation.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"openapi-mutation.d.ts","sourceRoot":"","sources":["../src/openapi-mutation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,WAAW,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAA;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEvD,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAA;AAE1C,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,eAAe,EAEpB,KAAK,QAAQ,EACb,KAAK,aAAa,EAGnB,MAAM,SAAS,CAAA;AAShB;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc,CAC7B,SAAS,EACT,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACnE,QAAQ,GAAG,KAAK,EAChB,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAEpE,+DAA+D;IAC/D,IAAI,EAAE,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC,CAAA;IACvD,wCAAwC;IACxC,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAA;IACxB,8CAA8C;IAC9C,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACvB,wCAAwC;IACxC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACvB,qCAAqC;IACrC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACrB,2CAA2C;IAC3C,MAAM,EAAE,QAAQ,CAAC,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;IACrD,mDAAmD;IACnD,WAAW,EAAE,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;IAC1E,gCAAgC;IAChC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,gFAAgF;IAChF,SAAS,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IAC/B,oCAAoC;IACpC,UAAU,EAAE,WAAW,CAAC,WAAW,CAAC,CAAA;IACpC,oEAAoE;IACpE,eAAe,EAAE,GAAG,CAAC,WAAW,CAAC,CAAA;CAClC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EACT,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACnE,QAAQ,GAAG,KAAK,EAChB,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAEpE,MAAM,EAAE,cAAc,EACtB,UAAU,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,EAC7F,OAAO,CAAC,EAAE,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,GACxE,cAAc,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,CAuLhE"}
|
package/dist/openapi-mutation.js
CHANGED
|
@@ -1,125 +1,82 @@
|
|
|
1
|
-
import { computed, ref
|
|
1
|
+
import { computed, ref } from 'vue';
|
|
2
2
|
import { useMutation } from '@tanstack/vue-query';
|
|
3
|
-
import { HttpMethod, } from './types.js';
|
|
4
|
-
import {
|
|
3
|
+
import { HttpMethod, isMutationMethod, } from './types.js';
|
|
4
|
+
import { isPathResolved, normalizeParamsOptions, useResolvedOperation, resolvePath, generateQueryKey, } from './openapi-utils.js';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
* Ensures the operation is a mutation (POST/PUT/PATCH/DELETE) at runtime.
|
|
8
|
-
* Returns a reactive mutation object, including helpers for query key and enabled state.
|
|
6
|
+
* Execute a type-safe mutation (POST/PUT/PATCH/DELETE) with automatic cache management.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* This is a low-level primitive — in normal usage it is called by the generated
|
|
9
|
+
* per-operation `useMutation` wrappers in `api-client.ts`, not directly.
|
|
12
10
|
*
|
|
13
|
-
* @template
|
|
14
|
-
* @
|
|
15
|
-
* @
|
|
16
|
-
* @
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* - `axiosOptions`: Custom axios request options (e.g., headers, params)
|
|
22
|
-
* - All properties from {@link UseMutationOptions} (from @tanstack/vue-query)
|
|
23
|
-
* @throws Error if the operation is not a mutation operation.
|
|
24
|
-
* @returns Mutation object with
|
|
25
|
-
* - `data`: ComputedRef of response data.
|
|
26
|
-
* - `isEnabled`: ComputedRef indicating if mutation can be executed (path resolved).
|
|
27
|
-
* - `extraPathParams`: Ref to set of additional path parameters when calling mutate.
|
|
28
|
-
* - `mutate` and `mutateAsync`: Functions to trigger the mutation, taking an object with:
|
|
29
|
-
* - `data`: The request body data for the mutation.
|
|
30
|
-
* - `pathParams`: Optional additional path parameters for the mutation.
|
|
31
|
-
* - `axiosOptions`: Optional axios configuration overrides for this specific mutation call.
|
|
32
|
-
* - `dontUpdateCache`, `dontInvalidate`, `invalidateOperations`, `refetchEndpoints`: Same as options, but can be set per-mutation.
|
|
33
|
-
* - All other properties and methods from the underlying Vue Query mutation object.
|
|
11
|
+
* @template TResponse The response data type
|
|
12
|
+
* @template TPathParams The path parameters type (concrete, required values)
|
|
13
|
+
* @template TRequest The request body type (`never` if no body)
|
|
14
|
+
* @template TQueryParams The query parameters type
|
|
15
|
+
*
|
|
16
|
+
* @param config Endpoint config: axios instance, queryClient, path, method, listPath, operationsRegistry
|
|
17
|
+
* @param pathParams Path parameters (reactive). Pass `undefined` for operations without path params.
|
|
18
|
+
* @param options Mutation options (dontInvalidate, refetchEndpoints, etc.)
|
|
34
19
|
*/
|
|
35
|
-
export function useEndpointMutation(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
throw new Error(`Operation ${String(operationId)} is not a mutation operation (POST/PUT/PATCH/DELETE)`);
|
|
20
|
+
export function useEndpointMutation(config, pathParams, options) {
|
|
21
|
+
if (!isMutationMethod(config.method)) {
|
|
22
|
+
throw new Error(`Operation at '${config.path}' uses method ${config.method} and cannot be used with useMutation(). ` +
|
|
23
|
+
`Use useQuery() for GET/HEAD/OPTIONS operations.`);
|
|
40
24
|
}
|
|
41
|
-
const {
|
|
42
|
-
const {
|
|
43
|
-
const { axiosOptions, dontInvalidate, dontUpdateCache, invalidateOperations, refetchEndpoints, queryParams, ...useMutationOptions } = options;
|
|
25
|
+
const { pathParams: resolvedPathParamsInput, options: resolvedOptions } = normalizeParamsOptions(pathParams, options);
|
|
26
|
+
const { axiosOptions, dontInvalidate, dontUpdateCache, invalidateOperations, refetchEndpoints, queryParams, ...useMutationOptions } = resolvedOptions;
|
|
44
27
|
const extraPathParams = ref({});
|
|
45
|
-
|
|
46
|
-
// This ensures that when pathParams is a function, it gets called within the computed
|
|
47
|
-
// so Vue can track dependencies of variables referenced inside the function
|
|
48
|
-
const basePathParams = computed(() => {
|
|
49
|
-
const result = toValue(pathParams);
|
|
50
|
-
return result;
|
|
51
|
-
});
|
|
52
|
-
const allPathParams = computed(() => ({
|
|
53
|
-
...basePathParams.value,
|
|
54
|
-
...extraPathParams.value,
|
|
55
|
-
}));
|
|
56
|
-
const resolvedPath = computed(() => resolvePath(path, allPathParams.value));
|
|
57
|
-
const queryKey = computed(() => generateQueryKey(resolvedPath.value));
|
|
58
|
-
// Make query parameters reactive
|
|
59
|
-
const allQueryParams = computed(() => {
|
|
60
|
-
const result = toValue(queryParams);
|
|
61
|
-
return result;
|
|
62
|
-
});
|
|
28
|
+
const { resolvedPath, queryKey, queryParams: resolvedQueryParams, pathParams: allPathParams, } = useResolvedOperation(config.path, resolvedPathParamsInput, queryParams, extraPathParams);
|
|
63
29
|
const mutation = useMutation({
|
|
64
30
|
mutationFn: async (vars) => {
|
|
65
|
-
const {
|
|
66
|
-
|
|
67
|
-
|
|
31
|
+
const { pathParams: pathParamsFromMutate, axiosOptions: axiosOptionsFromMutate, queryParams: queryParamsFromMutate, } = (vars || {});
|
|
32
|
+
const data = vars?.data;
|
|
33
|
+
extraPathParams.value = (pathParamsFromMutate || {});
|
|
68
34
|
if (!isPathResolved(resolvedPath.value)) {
|
|
69
|
-
return Promise.reject(new Error(`
|
|
35
|
+
return Promise.reject(new Error(`Cannot execute mutation at '${config.path}': path parameters not resolved. ` +
|
|
36
|
+
`Path: '${resolvedPath.value}', provided params: ${JSON.stringify(allPathParams.value)}`));
|
|
70
37
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
method: method.toLowerCase(),
|
|
38
|
+
await config.queryClient.cancelQueries({ queryKey: queryKey.value, exact: false });
|
|
39
|
+
return config.axios({
|
|
40
|
+
method: config.method.toLowerCase(),
|
|
75
41
|
url: resolvedPath.value,
|
|
76
42
|
...(data !== undefined && { data }),
|
|
77
43
|
...axiosOptions,
|
|
78
44
|
...axiosOptionsFromMutate,
|
|
79
45
|
params: {
|
|
80
46
|
...(axiosOptions?.params || {}),
|
|
81
|
-
...(
|
|
47
|
+
...(resolvedQueryParams.value || {}),
|
|
82
48
|
...(queryParamsFromMutate || {}),
|
|
83
49
|
},
|
|
84
50
|
});
|
|
85
51
|
},
|
|
86
|
-
onSuccess: async (response, vars
|
|
52
|
+
onSuccess: async (response, vars) => {
|
|
87
53
|
const data = response.data;
|
|
88
|
-
const { dontInvalidate: dontInvalidateMutate, dontUpdateCache: dontUpdateCacheMutate, invalidateOperations: invalidateOperationsMutate, refetchEndpoints: refetchEndpointsMutate, } = vars || {};
|
|
89
|
-
//
|
|
90
|
-
if (
|
|
91
|
-
// dontUpdateCacheMutate supersedes dontUpdateCache from options
|
|
92
|
-
(dontUpdateCacheMutate !== undefined ? !dontUpdateCacheMutate : !dontUpdateCache) &&
|
|
54
|
+
const { dontInvalidate: dontInvalidateMutate, dontUpdateCache: dontUpdateCacheMutate, invalidateOperations: invalidateOperationsMutate, refetchEndpoints: refetchEndpointsMutate, } = (vars || {});
|
|
55
|
+
// Update cache for PUT/PATCH
|
|
56
|
+
if ((dontUpdateCacheMutate !== undefined ? !dontUpdateCacheMutate : !dontUpdateCache) &&
|
|
93
57
|
data &&
|
|
94
|
-
[HttpMethod.PUT, HttpMethod.PATCH].includes(method)) {
|
|
95
|
-
await
|
|
58
|
+
[HttpMethod.PUT, HttpMethod.PATCH].includes(config.method)) {
|
|
59
|
+
await config.queryClient.setQueryData(queryKey.value, data);
|
|
96
60
|
}
|
|
97
|
-
// Invalidate queries for this path
|
|
61
|
+
// Invalidate queries for this path
|
|
98
62
|
if (dontInvalidateMutate !== undefined ? !dontInvalidateMutate : !dontInvalidate) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
63
|
+
await config.queryClient.invalidateQueries({
|
|
64
|
+
queryKey: queryKey.value,
|
|
65
|
+
exact: config.method !== HttpMethod.POST,
|
|
66
|
+
});
|
|
67
|
+
// Invalidate associated list path
|
|
68
|
+
if (config.listPath) {
|
|
69
|
+
const listResolvedPath = resolvePath(config.listPath, resolvedPathParamsInput);
|
|
104
70
|
if (isPathResolved(listResolvedPath)) {
|
|
105
71
|
const listQueryKey = generateQueryKey(listResolvedPath);
|
|
106
|
-
|
|
107
|
-
// For queries with query parameters (objects), strip the last element before comparing.
|
|
108
|
-
// This matches:
|
|
109
|
-
// - List queries without params: ["api", "user"]
|
|
110
|
-
// - List queries with params: ["api", "user", {filter}] → normalized to ["api", "user"]
|
|
111
|
-
// But NOT single-item queries where last element is a primitive:
|
|
112
|
-
// - Single-item: ["api", "user", "uuid"] → kept as ["api", "user", "uuid"]
|
|
113
|
-
await h.queryClient.invalidateQueries({
|
|
72
|
+
await config.queryClient.invalidateQueries({
|
|
114
73
|
predicate: (query) => {
|
|
115
74
|
const qKey = query.queryKey;
|
|
116
75
|
if (!qKey || qKey.length === 0)
|
|
117
76
|
return false;
|
|
118
|
-
// Normalize query key: strip last element if it's an object (query params)
|
|
119
77
|
const normalizedKey = typeof qKey[qKey.length - 1] === 'object' && qKey[qKey.length - 1] !== null
|
|
120
78
|
? qKey.slice(0, -1)
|
|
121
79
|
: qKey;
|
|
122
|
-
// Compare with listQueryKey
|
|
123
80
|
if (normalizedKey.length !== listQueryKey.length)
|
|
124
81
|
return false;
|
|
125
82
|
for (let i = 0; i < listQueryKey.length; i++) {
|
|
@@ -132,47 +89,61 @@ pathParamsOrOptions, optionsOrNull) {
|
|
|
132
89
|
}
|
|
133
90
|
}
|
|
134
91
|
}
|
|
92
|
+
// Resolve invalidateOperations entries using the registry
|
|
93
|
+
const registry = config.operationsRegistry || {};
|
|
94
|
+
const allInvalidateOps = [invalidateOperations, invalidateOperationsMutate].filter(Boolean);
|
|
135
95
|
const operationsWithPathParams = [];
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
96
|
+
for (const ops of allInvalidateOps) {
|
|
97
|
+
if (!ops)
|
|
98
|
+
continue;
|
|
99
|
+
if (Array.isArray(ops)) {
|
|
100
|
+
operationsWithPathParams.push(...ops.map((id) => [id, {}]));
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
operationsWithPathParams.push(...Object.entries(ops).map(([id, params]) => [id, params]));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
141
106
|
if (operationsWithPathParams.length > 0) {
|
|
142
107
|
const promises = operationsWithPathParams.map(([opId, opParams]) => {
|
|
143
|
-
const opInfo =
|
|
108
|
+
const opInfo = registry[opId];
|
|
109
|
+
if (!opInfo) {
|
|
110
|
+
console.warn(`Cannot invalidate operation '${opId}': not found in operations registry`);
|
|
111
|
+
return Promise.resolve();
|
|
112
|
+
}
|
|
144
113
|
const opPath = resolvePath(opInfo.path, {
|
|
145
114
|
...allPathParams.value,
|
|
146
115
|
...opParams,
|
|
147
116
|
});
|
|
148
117
|
if (isPathResolved(opPath)) {
|
|
149
118
|
const opQueryKey = generateQueryKey(opPath);
|
|
150
|
-
return
|
|
119
|
+
return config.queryClient.invalidateQueries({ queryKey: opQueryKey, exact: true });
|
|
151
120
|
}
|
|
152
121
|
else {
|
|
153
|
-
console.warn(`Cannot invalidate operation '${
|
|
154
|
-
return Promise.
|
|
122
|
+
console.warn(`Cannot invalidate operation '${opId}', path not resolved: ${opPath}`);
|
|
123
|
+
return Promise.resolve();
|
|
155
124
|
}
|
|
156
125
|
});
|
|
157
126
|
await Promise.all(promises);
|
|
158
127
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
128
|
+
const allRefetch = [
|
|
129
|
+
...(refetchEndpoints || []),
|
|
130
|
+
...(vars?.refetchEndpoints || []),
|
|
131
|
+
...(refetchEndpointsMutate || []),
|
|
132
|
+
];
|
|
133
|
+
if (allRefetch.length > 0) {
|
|
134
|
+
await Promise.all(allRefetch.map((ep) => ep.refetch()));
|
|
164
135
|
}
|
|
165
136
|
},
|
|
166
137
|
onSettled: () => {
|
|
167
138
|
extraPathParams.value = {};
|
|
168
139
|
},
|
|
169
140
|
...useMutationOptions,
|
|
170
|
-
},
|
|
141
|
+
}, config.queryClient);
|
|
171
142
|
return {
|
|
172
143
|
...mutation,
|
|
173
144
|
data: mutation.data,
|
|
174
145
|
isEnabled: computed(() => isPathResolved(resolvedPath.value)),
|
|
175
|
-
extraPathParams,
|
|
146
|
+
extraPathParams: extraPathParams,
|
|
176
147
|
pathParams: allPathParams,
|
|
177
148
|
};
|
|
178
149
|
}
|