1import execa = require('execa'); 2import * as fs from 'fs'; 3import chalk from 'chalk'; 4import { useSpinner } from '../utils/useSpinner'; 5import { Task, TaskRunner } from './task'; 6 7const path = require('path'); 8 9let distDir: string, cwd: string; 10 11const clean = () => useSpinner('Cleaning', () => execa('npm', ['run', 'clean'])); 12 13const compile = () => 14 useSpinner('Compiling sources', async () => { 15 try { 16 await execa('tsc', ['-p', './tsconfig.json']); 17 } catch (e) { 18 console.log(e); 19 throw e; 20 } 21 }); 22 23const savePackage = ({ path, pkg }: { path: string; pkg: {} }) => 24 useSpinner('Updating package.json', async () => { 25 new Promise<void>((resolve, reject) => { 26 fs.writeFile(path, JSON.stringify(pkg, null, 2), (err) => { 27 if (err) { 28 reject(err); 29 return; 30 } 31 resolve(); 32 }); 33 }); 34 }); 35 36const preparePackage = async (pkg: any) => { 37 pkg.bin = { 38 'grafana-toolkit': './bin/grafana-toolkit.js', 39 }; 40 41 await savePackage({ 42 path: `${cwd}/dist/package.json`, 43 pkg, 44 }); 45}; 46 47const copyFiles = () => { 48 const files = [ 49 'README.md', 50 'CHANGELOG.md', 51 'config/circleci/config.yml', 52 'bin/grafana-toolkit.js', 53 'src/config/prettier.plugin.config.json', 54 'src/config/prettier.plugin.rc.js', 55 'src/config/tsconfig.plugin.json', 56 'src/config/tsconfig.plugin.local.json', 57 'src/config/eslint.plugin.js', 58 'src/config/styles.mock.js', 59 'src/config/jest.plugin.config.local.js', 60 'src/config/matchMedia.js', 61 'src/config/react-inlinesvg.tsx', 62 ]; 63 64 return useSpinner(`Moving ${files.join(', ')} files`, async () => { 65 const promises = files.map((file) => { 66 return new Promise<void>((resolve, reject) => { 67 const basedir = path.dirname(`${distDir}/${file}`); 68 if (!fs.existsSync(basedir)) { 69 fs.mkdirSync(basedir, { recursive: true }); 70 } 71 fs.copyFile(`${cwd}/${file}`, `${distDir}/${file}`, (err) => { 72 if (err) { 73 reject(err); 74 return; 75 } 76 resolve(); 77 }); 78 }); 79 }); 80 81 await Promise.all(promises); 82 }); 83}; 84 85const copySassFiles = () => { 86 const files = ['_variables.generated.scss', '_variables.dark.generated.scss', '_variables.light.generated.scss']; 87 return useSpinner(`Copy scss files ${files.join(', ')} files`, async () => { 88 const sassDir = path.resolve(cwd, '../../public/sass/'); 89 const promises = files.map((file) => { 90 return new Promise<void>((resolve, reject) => { 91 const name = file.replace('.generated', ''); 92 fs.copyFile(`${sassDir}/${file}`, `${distDir}/sass/${name}`, (err) => { 93 if (err) { 94 reject(err); 95 return; 96 } 97 resolve(); 98 }); 99 }); 100 }); 101 102 await Promise.all(promises); 103 }); 104}; 105 106interface ToolkitBuildOptions {} 107 108const toolkitBuildTaskRunner: TaskRunner<ToolkitBuildOptions> = async () => { 109 cwd = path.resolve(__dirname, '../../../'); 110 distDir = `${cwd}/dist`; 111 const pkg = require(`${cwd}/package.json`); 112 console.log(chalk.yellow(`Building ${pkg.name} (package.json version: ${pkg.version})`)); 113 114 await clean(); 115 await compile(); 116 await preparePackage(pkg); 117 fs.mkdirSync('./dist/bin'); 118 fs.mkdirSync('./dist/sass'); 119 await copyFiles(); 120 await copySassFiles(); 121}; 122 123export const toolkitBuildTask = new Task<ToolkitBuildOptions>('@grafana/toolkit build', toolkitBuildTaskRunner); 124