API: Support versioned frontend clients (#106545)

* Update the generator to include version

* Add versioned APIs

* Update imports

* Prettier
This commit is contained in:
Alex Khomenko
2025-06-13 13:24:37 +03:00
committed by GitHub
parent 3e3fa18118
commit 6a11d462cb
92 changed files with 157 additions and 143 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# RTK Query API Client Generator
This generator automates the process of creating RTK Query API clients for Grafana's API groups. It replaces the manual steps outlined in the [main API documentation](../README.md).
This generator automates the process of creating RTK Query API clients for Grafana's API groups. It replaces the manual steps outlined in the [main API documentation](../../public/app/api/README.md).
## Usage
@@ -42,7 +42,7 @@ The generator automates the following:
If an error about a missing OpenAPI schema appears, check that:
1. The API group and version exist in the backend
2. The `TestIntegrationOpenAPIs` test has been run to generate the schema (step 1 in the [main API documentation](../README.md)).
2. The `TestIntegrationOpenAPIs` test has been run to generate the schema (step 1 in the [main API documentation](../../public/app/api/README.md)).
3. The schema file exists at `data/openapi/<group>-<version>.json`
### Validation Errors
+3 -3
View File
@@ -33,13 +33,13 @@ export const formatEndpoints = () => (endpointsInput: string | string[]) => {
};
// List of created or modified files
export const getFilesToFormat = (groupName: string, isEnterprise = false) => {
export const getFilesToFormat = (groupName: string, version: string, isEnterprise = false) => {
const apiClientBasePath = isEnterprise ? 'public/app/extensions/api/clients' : 'public/app/api/clients';
const generateScriptPath = isEnterprise ? 'local/generate-enterprise-apis.ts' : 'scripts/generate-rtk-apis.ts';
return [
`${apiClientBasePath}/${groupName}/baseAPI.ts`,
`${apiClientBasePath}/${groupName}/index.ts`,
`${apiClientBasePath}/${groupName}/${version}/baseAPI.ts`,
`${apiClientBasePath}/${groupName}/${version}/index.ts`,
generateScriptPath,
...(isEnterprise ? [] : [`public/app/core/reducers/root.ts`, `public/app/store/configureStore.ts`]),
];
+11 -9
View File
@@ -27,7 +27,7 @@ export default function plopGenerator(plop: NodePlopAPI) {
plop.setHelper('formatEndpoints', formatEndpoints());
const generateRtkApiActions = (data: PlopData) => {
const { reducerPath, groupName, isEnterprise } = data;
const { reducerPath, groupName, version, isEnterprise } = data;
const apiClientBasePath = isEnterprise ? 'public/app/extensions/api/clients' : 'public/app/api/clients';
const generateScriptPath = isEnterprise ? 'local/generate-enterprise-apis.ts' : 'scripts/generate-rtk-apis.ts';
@@ -46,7 +46,7 @@ export default function plopGenerator(plop: NodePlopAPI) {
const actions: ActionConfig[] = [
{
type: 'add',
path: path.join(basePath, `${apiClientBasePath}/${groupName}/baseAPI.ts`),
path: path.join(basePath, `${apiClientBasePath}/${groupName}/${version}/baseAPI.ts`),
templateFile: './templates/baseAPI.ts.hbs',
},
{
@@ -58,7 +58,7 @@ export default function plopGenerator(plop: NodePlopAPI) {
},
{
type: 'add',
path: path.join(basePath, `${apiClientBasePath}/${groupName}/index.ts`),
path: path.join(basePath, `${apiClientBasePath}/${groupName}/${version}/index.ts`),
templateFile: './templates/index.ts.hbs',
},
];
@@ -70,7 +70,7 @@ export default function plopGenerator(plop: NodePlopAPI) {
type: 'modify',
path: path.join(basePath, 'public/app/core/reducers/root.ts'),
pattern: '// PLOP_INJECT_IMPORT',
template: `import { ${reducerPath} } from '${clientImportPath}/${groupName}';\n// PLOP_INJECT_IMPORT`,
template: `import { ${reducerPath} } from '${clientImportPath}/${groupName}/${version}';\n// PLOP_INJECT_IMPORT`,
},
{
type: 'modify',
@@ -82,7 +82,7 @@ export default function plopGenerator(plop: NodePlopAPI) {
type: 'modify',
path: path.join(basePath, 'public/app/store/configureStore.ts'),
pattern: '// PLOP_INJECT_IMPORT',
template: `import { ${reducerPath} } from '${clientImportPath}/${groupName}';\n// PLOP_INJECT_IMPORT`,
template: `import { ${reducerPath} } from '${clientImportPath}/${groupName}/${version}';\n// PLOP_INJECT_IMPORT`,
},
{
type: 'modify',
@@ -97,7 +97,7 @@ export default function plopGenerator(plop: NodePlopAPI) {
actions.push(
{
type: 'formatFiles',
files: getFilesToFormat(groupName, isEnterprise),
files: getFilesToFormat(groupName, version, isEnterprise),
},
{
type: 'runGenerateApis',
@@ -140,10 +140,12 @@ export default function plopGenerator(plop: NodePlopAPI) {
{
type: 'input',
name: 'reducerPath',
message: 'Reducer path (e.g. dashboardAPI):',
default: (answers: { groupName?: string }) => `${answers.groupName}API`,
message: 'Reducer path (e.g. dashboardAPIv0alpha1):',
default: (answers: { groupName?: string; version?: string }) => `${answers.groupName}API${answers.version}`,
validate: (input: string) =>
input?.endsWith('API') ? true : 'Reducer path should end with "API" (e.g. dashboardAPI)',
input?.endsWith('API') || input?.match(/API[a-z]\d+[a-z]*\d*$/)
? true
: 'Reducer path should end with "API" or "API<version>" (e.g. dashboardAPI, dashboardAPIv0alpha1)',
},
{
type: 'input',
@@ -1,5 +1,5 @@
'{{apiPathPrefix}}/{{groupName}}/endpoints.gen.ts': {
apiFile: '{{apiPathPrefix}}/{{groupName}}/baseAPI.ts',
'{{apiPathPrefix}}/{{groupName}}/{{version}}/endpoints.gen.ts': {
apiFile: '{{apiPathPrefix}}/{{groupName}}/{{version}}/baseAPI.ts',
schemaFile: '../data/openapi/{{group}}-{{version}}.json',
{{#if endpoints}}
filterEndpoints: [{{{formatEndpoints endpoints}}}],