Skip to content

Commit 3d841f1

Browse files
committed
feat(codegen): support explicit tag overrides without altering defaults
1 parent 166bcc3 commit 3d841f1

File tree

4 files changed

+132
-5
lines changed

4 files changed

+132
-5
lines changed

packages/rtk-query-codegen-openapi/src/codegen.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export function generateEndpointDefinition({
119119
endpointBuilder = defaultEndpointBuilder,
120120
extraEndpointsProps,
121121
tags,
122+
tagOverrides,
122123
}: {
123124
operationName: string;
124125
type: 'query' | 'mutation';
@@ -127,14 +128,37 @@ export function generateEndpointDefinition({
127128
queryFn: ts.Expression;
128129
endpointBuilder?: ts.Identifier;
129130
extraEndpointsProps: ObjectPropertyDefinitions;
130-
tags: string[];
131+
tags?: string[];
132+
tagOverrides?: { providesTags?: string[]; invalidatesTags?: string[] };
131133
}) {
132134
const objectProperties = generateObjectProperties({ query: queryFn, ...extraEndpointsProps });
133-
if (tags.length > 0) {
135+
const providesTags =
136+
tagOverrides && 'providesTags' in tagOverrides
137+
? tagOverrides.providesTags
138+
: type === 'query'
139+
? tags
140+
: undefined;
141+
const invalidatesTags =
142+
tagOverrides && 'invalidatesTags' in tagOverrides
143+
? tagOverrides.invalidatesTags
144+
: type === 'mutation'
145+
? tags
146+
: undefined;
147+
148+
if (providesTags !== undefined) {
149+
objectProperties.push(
150+
factory.createPropertyAssignment(
151+
factory.createIdentifier('providesTags'),
152+
factory.createArrayLiteralExpression(providesTags.map((tag) => factory.createStringLiteral(tag)), false)
153+
)
154+
);
155+
}
156+
157+
if (invalidatesTags !== undefined) {
134158
objectProperties.push(
135159
factory.createPropertyAssignment(
136-
factory.createIdentifier(type === 'query' ? 'providesTags' : 'invalidatesTags'),
137-
factory.createArrayLiteralExpression(tags.map((tag) => factory.createStringLiteral(tag), false))
160+
factory.createIdentifier('invalidatesTags'),
161+
factory.createArrayLiteralExpression(invalidatesTags.map((tag) => factory.createStringLiteral(tag)), false)
138162
)
139163
);
140164
}

packages/rtk-query-codegen-openapi/src/generate.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ export async function generateApi(
253253
operation: { responses, requestBody },
254254
} = operationDefinition;
255255
const operationName = getOperationName({ verb, path, operation });
256-
const tags = tag ? getTags({ verb, pathItem }) : [];
256+
const tags = tag ? getTags({ verb, pathItem }) : undefined;
257257
const isQuery = testIsQuery(verb, overrides);
258258

259259
const returnsJson = apiGen.getResponseType(responses) === 'json';
@@ -408,6 +408,14 @@ export async function generateApi(
408408
).name
409409
);
410410

411+
const tagOverrides =
412+
overrides && (overrides.providesTags !== undefined || overrides.invalidatesTags !== undefined)
413+
? {
414+
...(overrides.providesTags !== undefined ? { providesTags: overrides.providesTags } : {}),
415+
...(overrides.invalidatesTags !== undefined ? { invalidatesTags: overrides.invalidatesTags } : {}),
416+
}
417+
: undefined;
418+
411419
return generateEndpointDefinition({
412420
operationName: operationNameSuffix ? capitalize(operationName + operationNameSuffix) : operationName,
413421
type: isQuery ? 'query' : 'mutation',
@@ -425,6 +433,7 @@ export async function generateApi(
425433
? generateQueryEndpointProps({ operationDefinition })
426434
: generateMutationEndpointProps({ operationDefinition }),
427435
tags,
436+
tagOverrides,
428437
});
429438
}
430439

packages/rtk-query-codegen-openapi/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ export type EndpointOverrides = {
154154
} & AtLeastOneKey<{
155155
type: 'mutation' | 'query';
156156
parameterFilter: ParameterMatcher;
157+
providesTags: string[];
158+
invalidatesTags: string[];
157159
}>;
158160

159161
export type ConfigFile =

packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,98 @@ describe('endpoint overrides', () => {
172172
expect(api).not.toMatch(/headers: {/);
173173
expect(api).toMatchSnapshot('should remove all parameters except for findPetsByStatus');
174174
});
175+
176+
it('should override generated tags', async () => {
177+
const api = await generateEndpoints({
178+
unionUndefined: true,
179+
tag: true,
180+
apiFile: './fixtures/emptyApi.ts',
181+
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
182+
filterEndpoints: ['getPetById', 'deletePet'],
183+
endpointOverrides: [
184+
{
185+
pattern: 'getPetById',
186+
providesTags: ['CustomQueryTag'],
187+
},
188+
{
189+
pattern: 'deletePet',
190+
invalidatesTags: [],
191+
},
192+
],
193+
});
194+
195+
expect(api).toMatch(/getPetById: build\.query[\s\S]*providesTags: \["CustomQueryTag"\]/);
196+
expect(api).not.toMatch(/getPetById: build\.query[\s\S]*providesTags: \["pet"\]/);
197+
expect(api).toMatch(/deletePet: build\.mutation[\s\S]*invalidatesTags: \[\]/);
198+
expect(api).not.toMatch(/deletePet: build\.mutation[\s\S]*invalidatesTags: \["pet"\]/);
199+
});
200+
201+
it('should allow tag overrides when tag generation is disabled', async () => {
202+
const api = await generateEndpoints({
203+
unionUndefined: true,
204+
apiFile: './fixtures/emptyApi.ts',
205+
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
206+
filterEndpoints: ['getPetById', 'deletePet'],
207+
endpointOverrides: [
208+
{
209+
pattern: 'getPetById',
210+
providesTags: ['ManualProvides'],
211+
},
212+
{
213+
pattern: 'deletePet',
214+
invalidatesTags: ['ManualInvalidates'],
215+
},
216+
],
217+
});
218+
219+
expect(api).toMatch(/getPetById: build\.query[\s\S]*providesTags: \["ManualProvides"\]/);
220+
expect(api).toMatch(/deletePet: build\.mutation[\s\S]*invalidatesTags: \["ManualInvalidates"\]/);
221+
expect(api).not.toMatch(/providesTags: \[\]/);
222+
expect(api).not.toMatch(/invalidatesTags: \[\]/);
223+
});
224+
225+
it('allows overriding tags regardless of inferred endpoint type', async () => {
226+
const api = await generateEndpoints({
227+
unionUndefined: true,
228+
apiFile: './fixtures/emptyApi.ts',
229+
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
230+
filterEndpoints: 'loginUser',
231+
endpointOverrides: [
232+
{
233+
pattern: 'loginUser',
234+
type: 'mutation',
235+
providesTags: ['LoginStatus'],
236+
},
237+
],
238+
});
239+
240+
expect(api).toMatch(/loginUser: build\.mutation/);
241+
expect(api).toMatch(/providesTags: \["LoginStatus"\]/);
242+
expect(api).not.toMatch(/invalidatesTags:/);
243+
});
244+
245+
it('allows overriding both providesTags and invalidatesTags simultaneously', async () => {
246+
const api = await generateEndpoints({
247+
unionUndefined: true,
248+
tag: true,
249+
apiFile: './fixtures/emptyApi.ts',
250+
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
251+
filterEndpoints: 'findPetsByStatus',
252+
endpointOverrides: [
253+
{
254+
pattern: 'findPetsByStatus',
255+
providesTags: ['CustomProvide'],
256+
invalidatesTags: ['CustomInvalidate'],
257+
},
258+
],
259+
});
260+
261+
expect(api).toMatch(/findPetsByStatus: build\.query/);
262+
expect(api).toMatch(/providesTags: \["CustomProvide"\]/);
263+
expect(api).toMatch(/invalidatesTags: \["CustomInvalidate"\]/);
264+
expect(api).not.toMatch(/providesTags: \["pet"\]/);
265+
expect(api).not.toMatch(/invalidatesTags: \["pet"\]/);
266+
});
175267
});
176268

177269
describe('option encodePathParams', () => {

0 commit comments

Comments
 (0)