Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions packages/rtk-query-codegen-openapi/src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export function generateEndpointDefinition({
endpointBuilder = defaultEndpointBuilder,
extraEndpointsProps,
tags,
tagOverrides,
}: {
operationName: string;
type: 'query' | 'mutation';
Expand All @@ -127,14 +128,37 @@ export function generateEndpointDefinition({
queryFn: ts.Expression;
endpointBuilder?: ts.Identifier;
extraEndpointsProps: ObjectPropertyDefinitions;
tags: string[];
tags?: string[];
tagOverrides?: { providesTags?: string[]; invalidatesTags?: string[] };
}) {
const objectProperties = generateObjectProperties({ query: queryFn, ...extraEndpointsProps });
if (tags.length > 0) {
const providesTags =
tagOverrides && 'providesTags' in tagOverrides
? tagOverrides.providesTags
: type === 'query'
? tags
: undefined;
const invalidatesTags =
tagOverrides && 'invalidatesTags' in tagOverrides
? tagOverrides.invalidatesTags
: type === 'mutation'
? tags
: undefined;

if (providesTags !== undefined) {
objectProperties.push(
factory.createPropertyAssignment(
factory.createIdentifier('providesTags'),
factory.createArrayLiteralExpression(providesTags.map((tag) => factory.createStringLiteral(tag)), false)
)
);
}

if (invalidatesTags !== undefined) {
objectProperties.push(
factory.createPropertyAssignment(
factory.createIdentifier(type === 'query' ? 'providesTags' : 'invalidatesTags'),
factory.createArrayLiteralExpression(tags.map((tag) => factory.createStringLiteral(tag), false))
factory.createIdentifier('invalidatesTags'),
factory.createArrayLiteralExpression(invalidatesTags.map((tag) => factory.createStringLiteral(tag)), false)
)
);
}
Expand Down
11 changes: 10 additions & 1 deletion packages/rtk-query-codegen-openapi/src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ export async function generateApi(
operation: { responses, requestBody },
} = operationDefinition;
const operationName = getOperationName({ verb, path, operation });
const tags = tag ? getTags({ verb, pathItem }) : [];
const tags = tag ? getTags({ verb, pathItem }) : undefined;
const isQuery = testIsQuery(verb, overrides);

const returnsJson = apiGen.getResponseType(responses) === 'json';
Expand Down Expand Up @@ -408,6 +408,14 @@ export async function generateApi(
).name
);

const tagOverrides =
overrides && (overrides.providesTags !== undefined || overrides.invalidatesTags !== undefined)
? {
...(overrides.providesTags !== undefined ? { providesTags: overrides.providesTags } : {}),
...(overrides.invalidatesTags !== undefined ? { invalidatesTags: overrides.invalidatesTags } : {}),
}
: undefined;

return generateEndpointDefinition({
operationName: operationNameSuffix ? capitalize(operationName + operationNameSuffix) : operationName,
type: isQuery ? 'query' : 'mutation',
Expand All @@ -425,6 +433,7 @@ export async function generateApi(
? generateQueryEndpointProps({ operationDefinition })
: generateMutationEndpointProps({ operationDefinition }),
tags,
tagOverrides,
});
}

Expand Down
2 changes: 2 additions & 0 deletions packages/rtk-query-codegen-openapi/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ export type EndpointOverrides = {
} & AtLeastOneKey<{
type: 'mutation' | 'query';
parameterFilter: ParameterMatcher;
providesTags: string[];
invalidatesTags: string[];
}>;

export type ConfigFile =
Expand Down
92 changes: 92 additions & 0 deletions packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,98 @@ describe('endpoint overrides', () => {
expect(api).not.toMatch(/headers: {/);
expect(api).toMatchSnapshot('should remove all parameters except for findPetsByStatus');
});

it('should override generated tags', async () => {
const api = await generateEndpoints({
unionUndefined: true,
tag: true,
apiFile: './fixtures/emptyApi.ts',
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
filterEndpoints: ['getPetById', 'deletePet'],
endpointOverrides: [
{
pattern: 'getPetById',
providesTags: ['CustomQueryTag'],
},
{
pattern: 'deletePet',
invalidatesTags: [],
},
],
});

expect(api).toMatch(/getPetById: build\.query[\s\S]*providesTags: \["CustomQueryTag"\]/);
expect(api).not.toMatch(/getPetById: build\.query[\s\S]*providesTags: \["pet"\]/);
expect(api).toMatch(/deletePet: build\.mutation[\s\S]*invalidatesTags: \[\]/);
expect(api).not.toMatch(/deletePet: build\.mutation[\s\S]*invalidatesTags: \["pet"\]/);
});

it('should allow tag overrides when tag generation is disabled', async () => {
const api = await generateEndpoints({
unionUndefined: true,
apiFile: './fixtures/emptyApi.ts',
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
filterEndpoints: ['getPetById', 'deletePet'],
endpointOverrides: [
{
pattern: 'getPetById',
providesTags: ['ManualProvides'],
},
{
pattern: 'deletePet',
invalidatesTags: ['ManualInvalidates'],
},
],
});

expect(api).toMatch(/getPetById: build\.query[\s\S]*providesTags: \["ManualProvides"\]/);
expect(api).toMatch(/deletePet: build\.mutation[\s\S]*invalidatesTags: \["ManualInvalidates"\]/);
expect(api).not.toMatch(/providesTags: \[\]/);
expect(api).not.toMatch(/invalidatesTags: \[\]/);
});

it('allows overriding tags regardless of inferred endpoint type', async () => {
const api = await generateEndpoints({
unionUndefined: true,
apiFile: './fixtures/emptyApi.ts',
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
filterEndpoints: 'loginUser',
endpointOverrides: [
{
pattern: 'loginUser',
type: 'mutation',
providesTags: ['LoginStatus'],
},
],
});

expect(api).toMatch(/loginUser: build\.mutation/);
expect(api).toMatch(/providesTags: \["LoginStatus"\]/);
expect(api).not.toMatch(/invalidatesTags:/);
});

it('allows overriding both providesTags and invalidatesTags simultaneously', async () => {
const api = await generateEndpoints({
unionUndefined: true,
tag: true,
apiFile: './fixtures/emptyApi.ts',
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
filterEndpoints: 'findPetsByStatus',
endpointOverrides: [
{
pattern: 'findPetsByStatus',
providesTags: ['CustomProvide'],
invalidatesTags: ['CustomInvalidate'],
},
],
});

expect(api).toMatch(/findPetsByStatus: build\.query/);
expect(api).toMatch(/providesTags: \["CustomProvide"\]/);
expect(api).toMatch(/invalidatesTags: \["CustomInvalidate"\]/);
expect(api).not.toMatch(/providesTags: \["pet"\]/);
expect(api).not.toMatch(/invalidatesTags: \["pet"\]/);
});
});

describe('option encodePathParams', () => {
Expand Down