mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			116 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
import { execSync } from 'child_process';
 | 
						|
import path from 'path';
 | 
						|
 | 
						|
type PlopActionFunction = (
 | 
						|
  answers: Record<string, unknown>,
 | 
						|
  config?: Record<string, unknown>
 | 
						|
) => string | Promise<string>;
 | 
						|
 | 
						|
// Helper to remove quotes from operation IDs
 | 
						|
export const removeQuotes = (str: string | unknown) => {
 | 
						|
  if (typeof str !== 'string') {
 | 
						|
    return str;
 | 
						|
  }
 | 
						|
  return str.replace(/^['"](.*)['"]$/, '$1');
 | 
						|
};
 | 
						|
 | 
						|
export const formatEndpoints = () => (endpointsInput: string | string[]) => {
 | 
						|
  if (Array.isArray(endpointsInput)) {
 | 
						|
    return endpointsInput.map((op) => `'${removeQuotes(op)}'`).join(', ');
 | 
						|
  }
 | 
						|
 | 
						|
  // Handle string input (comma-separated)
 | 
						|
  if (typeof endpointsInput === 'string') {
 | 
						|
    const endpointsArray = endpointsInput
 | 
						|
      .split(',')
 | 
						|
      .map((id) => id.trim())
 | 
						|
      .filter(Boolean);
 | 
						|
 | 
						|
    return endpointsArray.map((op) => `'${removeQuotes(op)}'`).join(', ');
 | 
						|
  }
 | 
						|
 | 
						|
  return '';
 | 
						|
};
 | 
						|
 | 
						|
// List of created or modified files
 | 
						|
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}/${version}/baseAPI.ts`,
 | 
						|
    `${apiClientBasePath}/${groupName}/${version}/index.ts`,
 | 
						|
    generateScriptPath,
 | 
						|
    ...(isEnterprise ? [] : [`public/app/core/reducers/root.ts`, `public/app/store/configureStore.ts`]),
 | 
						|
  ];
 | 
						|
};
 | 
						|
 | 
						|
export const runGenerateApis =
 | 
						|
  (basePath: string): PlopActionFunction =>
 | 
						|
  (answers, config) => {
 | 
						|
    try {
 | 
						|
      const isEnterprise = answers.isEnterprise || (config && config.isEnterprise);
 | 
						|
 | 
						|
      let command;
 | 
						|
      if (isEnterprise) {
 | 
						|
        command = 'yarn process-specs && npx rtk-query-codegen-openapi ./local/generate-enterprise-apis.ts';
 | 
						|
      } else {
 | 
						|
        command = 'yarn generate-apis';
 | 
						|
      }
 | 
						|
 | 
						|
      console.log(`⏳ Running ${command} to generate endpoints...`);
 | 
						|
      execSync(command, { stdio: 'inherit', cwd: basePath });
 | 
						|
      return '✅ API endpoints generated successfully!';
 | 
						|
    } catch (error) {
 | 
						|
      const errorMessage = error instanceof Error ? error.message : String(error);
 | 
						|
      console.error('❌ Failed to generate API endpoints:', errorMessage);
 | 
						|
      return '❌ Failed to generate API endpoints. See error above.';
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
export const formatFiles =
 | 
						|
  (basePath: string): PlopActionFunction =>
 | 
						|
  (_, config) => {
 | 
						|
    if (!config || !Array.isArray(config.files)) {
 | 
						|
      console.error('Invalid config passed to formatFiles action');
 | 
						|
      return '❌ Formatting failed: Invalid configuration';
 | 
						|
    }
 | 
						|
 | 
						|
    const filesToFormat = config.files.map((file: string) => path.join(basePath, file));
 | 
						|
 | 
						|
    try {
 | 
						|
      const filesList = filesToFormat.map((file: string) => `"${file}"`).join(' ');
 | 
						|
 | 
						|
      console.log('🧹 Running ESLint on generated/modified files...');
 | 
						|
      try {
 | 
						|
        execSync(`yarn eslint --fix ${filesList}`, { cwd: basePath });
 | 
						|
      } catch (error) {
 | 
						|
        const errorMessage = error instanceof Error ? error.message : String(error);
 | 
						|
        console.warn(`⚠️ Warning: ESLint encountered issues: ${errorMessage}`);
 | 
						|
      }
 | 
						|
 | 
						|
      console.log('🧹 Running Prettier on generated/modified files...');
 | 
						|
      try {
 | 
						|
        // '--ignore-path' is necessary so the gitignored files ('local/' folder) can still be formatted
 | 
						|
        execSync(`yarn prettier --write ${filesList} --ignore-path=./.prettierignore`, { cwd: basePath });
 | 
						|
      } catch (error) {
 | 
						|
        const errorMessage = error instanceof Error ? error.message : String(error);
 | 
						|
        console.warn(`⚠️ Warning: Prettier encountered issues: ${errorMessage}`);
 | 
						|
      }
 | 
						|
 | 
						|
      return '✅ Files linted and formatted successfully!';
 | 
						|
    } catch (error) {
 | 
						|
      const errorMessage = error instanceof Error ? error.message : String(error);
 | 
						|
      console.error('⚠️ Warning: Formatting operations failed:', errorMessage);
 | 
						|
      return '⚠️ Warning: Formatting operations failed.';
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
export const validateGroup = (group: string) => {
 | 
						|
  return group && group.includes('.grafana.app') ? true : 'Group should be in format: name.grafana.app';
 | 
						|
};
 | 
						|
 | 
						|
export const validateVersion = (version: string) => {
 | 
						|
  return version && /^v\d+[a-z]*\d+$/.test(version) ? true : 'Version should be in format: v0alpha1, v1beta2, etc.';
 | 
						|
};
 |