Skip to content

Commit a4c7c7a

Browse files
committed
refactor: improve query key type (service/reference)
Signed-off-by: samuel.park <[email protected]>
1 parent be33e94 commit a4c7c7a

10 files changed

+82
-83
lines changed

apps/web/src/api-clients/_common/composables/use-api-query-key.ts

+18-12
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import type { ComputedRef } from 'vue';
22
import { computed } from 'vue';
33

4-
import { SERVICE_PREFIX } from '@/api-clients/_common/constants/query-key-constant';
54
import type {
65
ResourceName, ServiceName, ServiceQueryKey, Verb,
76
} from '@/api-clients/_common/types/query-key-type';
8-
import type { QueryKeyBaseParams } from '@/query/_composables/use-query-key-base';
9-
import { useQueryKeyBase } from '@/query/_composables/use-query-key-base';
7+
import type { QueryKeyContextParams } from '@/query/_composables/use-query-key-context';
8+
import { useQueryKeyContext } from '@/query/_composables/use-query-key-context';
109

1110
/**
1211
* Generates a computed query key for API requests, incorporating global parameters.
@@ -15,29 +14,36 @@ import { useQueryKeyBase } from '@/query/_composables/use-query-key-base';
1514
* @param resource - The resource name, specifying the target API resource (e.g., 'public-data-table').
1615
* @param verb - The API action verb, defining the type of request (e.g., 'get', 'list', 'update').
1716
* @param queryKeyOptions - Optional query key options to merge with default params
18-
* @returns A computed reference to the query key array, structured as `[SERVICE_PREFIX, service, resource, verb, { globalParams }]`.
17+
* @returns A computed reference to the query key array, structured as `[QueryContext, service, resource, verb]`
1918
*
2019
* ### Example Usage:
2120
* ```ts
22-
* const queryKey = useAPIQueryKey('dashboard', 'public-data-table', 'get');
21+
* // Basic usage
22+
* const queryKey = useAPIQueryKey('dashboard', 'public-data-table', 'get');
23+
*
24+
* // With additional params
25+
* const queryKey = useAPIQueryKey('dashboard', 'public-data-table', 'get', {
26+
* workspaceId: 'custom-id',
27+
* isAdminMode: true
28+
* });
2329
* ```
30+
*
2431
* The generated query key ensures:
25-
* - **Type safety**: Prevents invalid API calls by enforcing a valid `service/resource/verb` combination.
26-
* - **Auto-completion**: Provides intelligent suggestions based on predefined API structure.
27-
* - **Cache management**: Enables precise cache invalidation and data synchronization.
32+
* - **Type safety**: Prevents invalid API calls by enforcing a valid `service/resource/verb` combination
33+
* - **Auto-completion**: Provides intelligent suggestions based on predefined API structure
34+
* - **Cache management**: Enables precise cache invalidation and data synchronization
2835
*/
2936

3037
export const useAPIQueryKey = <S extends ServiceName, R extends ResourceName<S>, V extends Verb<S, R>>(
3138
service: S,
3239
resource: R,
3340
verb: V,
34-
queryKeyOptions?: Partial<QueryKeyBaseParams>,
41+
queryKeyOptions?: Partial<QueryKeyContextParams>,
3542
): ComputedRef<ServiceQueryKey<S, R, V>> => {
36-
const queryKeyBase = useQueryKeyBase(queryKeyOptions);
43+
const queryKeyContext = useQueryKeyContext({ ...queryKeyOptions, context: 'service' });
3744

3845
return computed(() => [
39-
...queryKeyBase.value,
40-
SERVICE_PREFIX,
46+
queryKeyContext.value,
4147
service,
4248
resource,
4349
verb,

apps/web/src/api-clients/_common/helpers/service-query-invalidation-helper.ts

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
import { SERVICE_PREFIX } from '@/api-clients/_common/constants/query-key-constant';
21
import { queryClient } from '@/query';
2+
import type { QueryContext } from '@/query/_types/query-key-type';
33

4-
5-
6-
7-
export const invalidateServiceQuery = (mode?: 'ADMIN' | 'WORKSPACE') => {
8-
queryClient.invalidateQueries({
4+
/**
5+
* Invalidates all service queries based on the specified mode.
6+
*
7+
* @param mode - Optional mode filter ('ADMIN' | 'WORKSPACE')
8+
*/
9+
export const invalidateServiceQuery = async (mode?: 'admin' | 'workspace') => {
10+
await queryClient.invalidateQueries({
911
predicate: (query) => {
10-
const [queryMode,,, queryType] = query.queryKey;
11-
if (queryType !== SERVICE_PREFIX) return false;
12-
if (mode && mode !== queryMode) return false;
12+
const [queryContext] = query.queryKey as [QueryContext, ...unknown[]];
13+
if (!queryContext || queryContext.context !== 'service') return false;
14+
if (mode && mode !== queryContext.mode) return false;
1315
return true;
1416
},
1517
});

apps/web/src/api-clients/_common/types/query-key-type.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { API_DOC } from '@/api-clients/_common/constants/api-doc';
2-
import type { SERVICE_PREFIX } from '@/api-clients/_common/constants/query-key-constant';
3-
import type { QueryKeyBase } from '@/query/_types/query-key-type';
2+
import type { QueryContext } from '@/query/_types/query-key-type';
43

54

65

@@ -12,8 +11,7 @@ export type ResourceName<S extends ServiceName> = keyof (typeof API_DOC)[S];
1211
export type Verb<S extends ServiceName, R extends ResourceName<S>> = Extract<(typeof API_DOC)[S][R], string[]>[number] | string;
1312

1413
export type ServiceQueryKey<S extends ServiceName, R extends ResourceName<S>, V extends Verb<S, R>> = [
15-
...QueryKeyBase,
16-
typeof SERVICE_PREFIX,
14+
QueryContext,
1715
S,
1816
R,
1917
V,
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { ComputedRef } from 'vue';
22
import { computed, reactive } from 'vue';
33

4-
import type { QueryKeyBase } from '@/query/_types/query-key-type';
4+
import type { QueryContext } from '@/query/_types/query-key-type';
55

66
import { useAppContextStore } from '@/store/app-context/app-context-store';
77
import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store';
@@ -11,13 +11,10 @@ import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-worksp
1111
* Interface for global query parameters used across API requests.
1212
* These parameters are automatically included in API and reference query keys.
1313
*/
14-
export interface QueryKeyBaseParams {
15-
/** Flag indicating whether admin mode is enabled */
14+
export interface QueryKeyContextParams {
1615
isAdminMode?: boolean;
17-
/** Current workspace ID from the workspace context */
1816
workspaceId?: string;
19-
/** Additional parameters that might be added */
20-
[key: string]: any;
17+
context: 'service' | 'reference';
2118
}
2219

2320
/**
@@ -26,24 +23,28 @@ export interface QueryKeyBaseParams {
2623
* that are commonly used across different API queries.
2724
*
2825
* @param queryKeyOptions - Optional query key options to merge with default params
29-
* @returns A computed reference containing the combined global query parameters as an ordered array
26+
* @returns A computed reference containing the combined global query parameters as a QueryContext object
3027
*
3128
* ### Example Usage:
3229
* ```ts
33-
* const queryKeyBase = useQueryKeyBase();
34-
* // Access params (now returns array)
35-
* const [mode, workspaceId, others] = queryKeyBase.value;
30+
* const queryContext = useQueryKeyContext({ context: 'service' });
31+
* // Access params
32+
* const { mode, workspaceId, context } = queryContext.value;
3633
*
3734
* // With additional params
38-
* const params = useQueryKeyBase({ customParam: 'value' });
35+
* const params = useQueryKeyContext({
36+
* context: 'service',
37+
* isAdminMode: true,
38+
* workspaceId: 'custom-id'
39+
* });
3940
* ```
4041
*
4142
* ### Features:
42-
* - **Ordered Parameters**: Guarantees consistent parameter order: [mode, workspaceId, others]
43+
* - **Structured Context**: Returns a QueryContext object with mode, workspaceId, and context
4344
* - **Reactive State**: Automatically updates when workspace or admin mode changes
44-
* - **Parameter Merging**: Allows adding custom parameters in the others object
45+
* - **Type Safety**: Ensures context is always provided with valid values
4546
*/
46-
export const useQueryKeyBase = (queryKeyOptions?: Partial<QueryKeyBaseParams>): ComputedRef<QueryKeyBase> => {
47+
export const useQueryKeyContext = (queryKeyOptions: QueryKeyContextParams): ComputedRef<QueryContext> => {
4748
const appContextStore = useAppContextStore();
4849
const userWorkspaceStore = useUserWorkspaceStore();
4950

@@ -52,15 +53,17 @@ export const useQueryKeyBase = (queryKeyOptions?: Partial<QueryKeyBaseParams>):
5253
currentWorkspaceId: computed<string|undefined>(() => userWorkspaceStore.getters.currentWorkspaceId),
5354
});
5455

55-
return computed<QueryKeyBase>(() => {
56-
const { isAdminMode, workspaceId: _workspaceId, ...otherParams } = queryKeyOptions || {};
57-
const mode = (isAdminMode || _state.isAdminMode) ? 'ADMIN' : 'WORKSPACE';
56+
return computed<QueryContext>(() => {
57+
const {
58+
isAdminMode, workspaceId: _workspaceId, context,
59+
} = queryKeyOptions || {};
60+
const mode = (isAdminMode || _state.isAdminMode) ? 'admin' : 'workspace';
5861
const workspaceId = _workspaceId || _state.currentWorkspaceId;
5962

60-
return [
63+
return {
6164
mode,
6265
workspaceId,
63-
Object.keys(otherParams).length > 0 ? otherParams : undefined,
64-
];
66+
context,
67+
};
6568
});
6669
};
+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

2-
export type QueryKeyBase = [
3-
mode: 'ADMIN' | 'WORKSPACE',
2+
export interface QueryContext {
3+
mode: 'admin' | 'workspace',
44
workspaceId: string | undefined,
5-
others: Record<string, any> | undefined,
6-
];
5+
context: 'service' | 'reference',
6+
}
77

88

99

Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import type { ComputedRef } from 'vue';
22
import { computed } from 'vue';
33

4-
import type { QueryKeyBaseParams } from '@/query/_composables/use-query-key-base';
5-
import { useQueryKeyBase } from '@/query/_composables/use-query-key-base';
6-
import { getReferencePrimaryQueryKey } from '@/query/reference/_helper/reference-query-key-helper';
4+
import type { QueryKeyContextParams } from '@/query/_composables/use-query-key-context';
5+
import { useQueryKeyContext } from '@/query/_composables/use-query-key-context';
76
import type { ReferenceQueryKey } from '@/query/reference/_types/reference-query-key-type';
87
import type { ReferenceResourceType } from '@/query/reference/_types/reference-resource-type';
98

@@ -16,15 +15,18 @@ import type { ReferenceResourceType } from '@/query/reference/_types/reference-r
1615
*
1716
* @param resourceType - The type of reference resource (e.g., 'public-dashboard', 'project')
1817
* @param queryKeyOptions - Optional query key options to merge with default params
19-
* @returns A computed reference to the query key array, structured as `[REFERENCE_PREFIX, ...referencePrimaryKey, { globalParams }]`
18+
* @returns A computed reference to the query key array, structured as `[QueryContext, resourceType]`
2019
*
2120
* ### Example Usage:
2221
* ```ts
2322
* // Basic usage
2423
* const referenceKey = useReferenceQueryKey('public-dashboard');
2524
*
2625
* // With additional params
27-
* const referenceKey = useReferenceQueryKey('public-dashboard', { workspaceId: 'custom-id' });
26+
* const referenceKey = useReferenceQueryKey('public-dashboard', {
27+
* workspaceId: 'custom-id',
28+
* context: 'reference'
29+
* });
2830
* ```
2931
*
3032
* ### Features:
@@ -34,12 +36,12 @@ import type { ReferenceResourceType } from '@/query/reference/_types/reference-r
3436
*/
3537
export const useReferenceQueryKey = (
3638
resourceType: ReferenceResourceType,
37-
queryKeyOptions?: Partial<QueryKeyBaseParams>,
39+
queryKeyOptions?: Partial<QueryKeyContextParams>,
3840
): ComputedRef<ReferenceQueryKey> => {
39-
const queryKeyBase = useQueryKeyBase(queryKeyOptions);
41+
const queryKeyContext = useQueryKeyContext({ ...queryKeyOptions, context: 'reference' });
4042

4143
return computed(() => [
42-
...queryKeyBase.value,
43-
...getReferencePrimaryQueryKey(resourceType),
44+
queryKeyContext.value,
45+
resourceType,
4446
]);
4547
};

apps/web/src/query/reference/_constant/query-key-constant.ts

-1
This file was deleted.

apps/web/src/query/reference/_helper/reference-query-invalidation-helper.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import { queryClient } from '@/query';
2-
import { REFERENCE_PREFIX } from '@/query/reference/_constant/query-key-constant';
2+
import type { QueryContext } from '@/query/_types/query-key-type';
33

4-
5-
export const invalidateReferenceQuery = (mode?: 'ADMIN' | 'WORKSPACE') => {
6-
queryClient.invalidateQueries({
4+
/**
5+
* Invalidates all reference queries based on the specified mode.
6+
*
7+
* @param mode - Optional mode filter ('ADMIN' | 'WORKSPACE')
8+
*/
9+
export const invalidateReferenceQuery = async (mode?: 'admin' | 'workspace') => {
10+
await queryClient.invalidateQueries({
711
predicate: (query) => {
8-
const [queryMode,,, queryType] = query.queryKey;
9-
if (queryType !== REFERENCE_PREFIX) return false;
10-
if (mode && mode !== queryMode) return false;
12+
const [queryContext] = query.queryKey as [QueryContext, ...unknown[]];
13+
if (!queryContext || queryContext.context !== 'reference') return false;
14+
if (mode && mode !== queryContext.mode) return false;
1115
return true;
1216
},
1317
});

apps/web/src/query/reference/_helper/reference-query-key-helper.ts

-7
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
1-
import type { QueryKeyBase } from '@/query/_types/query-key-type';
2-
import { REFERENCE_PREFIX } from '@/query/reference/_constant/query-key-constant';
1+
import type { QueryContext } from '@/query/_types/query-key-type';
32
import type { ReferenceResourceType } from '@/query/reference/_types/reference-resource-type';
43

54

65
export type ReferenceQueryKey = [
7-
...QueryKeyBase,
8-
typeof REFERENCE_PREFIX,
6+
QueryContext,
97
ReferenceResourceType
108
];
11-
12-
// 명시적인 반환 타입 정의
13-
export const getReferencePrimaryQueryKey = (resourceType: ReferenceResourceType): [typeof REFERENCE_PREFIX, ReferenceResourceType] => [
14-
REFERENCE_PREFIX,
15-
resourceType,
16-
];

0 commit comments

Comments
 (0)