UNPKG

gts

Version:

Google TypeScript Style

290 lines (287 loc) 9.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ESLINT_IGNORE = exports.ESLINT_CONFIG = void 0; exports.addScripts = addScripts; exports.addDependencies = addDependencies; exports.installDefaultTemplate = installDefaultTemplate; exports.init = init; /** * Copyright 2017 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const cp = require("child_process"); const fs = require("fs"); const inquirer = require("inquirer"); const path = require("path"); const ncp_1 = require("ncp"); const util = require("util"); const writeFileAtomic = require("write-file-atomic"); const util_1 = require("./util"); const chalk = require("chalk"); const pkg = require('../../package.json'); const ncpp = util.promisify(ncp_1.ncp); const DEFAULT_PACKAGE_JSON = { name: '', version: '0.0.0', description: '', main: 'build/src/index.js', types: 'build/src/index.d.ts', files: ['build/src'], license: 'Apache-2.0', keywords: [], scripts: { test: 'echo "Error: no test specified" && exit 1' }, }; async function query(message, question, defaultVal, options) { if (options.yes) { return true; } else if (options.no) { return false; } if (message) { options.logger.log(message); } const answers = await inquirer.prompt({ type: 'confirm', name: 'query', message: question, default: defaultVal, }); return answers.query; } async function addScripts(packageJson, options) { let edits = false; const pkgManager = (0, util_1.getPkgManagerCommand)(options.yarn); const scripts = { lint: 'gts lint', clean: 'gts clean', compile: 'tsc', fix: 'gts fix', prepare: `${pkgManager} run compile`, pretest: `${pkgManager} run compile`, posttest: `${pkgManager} run lint`, }; if (!packageJson.scripts) { packageJson.scripts = {}; } for (const script of Object.keys(scripts)) { let install = true; const existing = packageJson.scripts[script]; const target = scripts[script]; if (existing !== target) { if (existing) { const message = `package.json already has a script for ${chalk.bold(script)}:\n` + `-${chalk.red(existing)}\n+${chalk.green(target)}`; install = await query(message, 'Replace', false, options); } if (install) { packageJson.scripts[script] = scripts[script]; edits = true; } } } return edits; } async function addDependencies(packageJson, options) { let edits = false; const deps = { gts: `^${pkg.version}`, typescript: pkg.devDependencies.typescript, '@types/node': pkg.devDependencies['@types/node'], }; if (!packageJson.devDependencies) { packageJson.devDependencies = {}; } for (const dep of Object.keys(deps)) { let install = true; const existing = packageJson.devDependencies[dep]; const target = deps[dep]; if (existing !== target) { if (existing) { const message = `Already have devDependency for ${chalk.bold(dep)}:\n` + `-${chalk.red(existing)}\n+${chalk.green(target)}`; install = await query(message, 'Overwrite', false, options); } if (install) { packageJson.devDependencies[dep] = deps[dep]; edits = true; } } } return edits; } function formatJson(object) { const json = JSON.stringify(object, null, ' '); return `${json}\n`; } async function writePackageJson(packageJson, options) { options.logger.log('Writing package.json...'); if (!options.dryRun) { await writeFileAtomic('./package.json', formatJson(packageJson)); } const preview = { scripts: packageJson.scripts, devDependencies: packageJson.devDependencies, }; options.logger.dir(preview); } exports.ESLINT_CONFIG = `let customConfig = []; let hasIgnoresFile = false; try { require.resolve('./eslint.ignores.js'); hasIgnoresFile = true; } catch { // eslint.ignores.js doesn't exist } if (hasIgnoresFile) { const ignores = require('./eslint.ignores.js'); customConfig = [{ignores}]; } module.exports = [...customConfig, ...require('gts')]; `; exports.ESLINT_IGNORE = "module.exports = ['build/']\n"; async function generateConfigFile(options, filename, contents) { let existing; try { existing = await (0, util_1.readFilep)(filename, 'utf8'); } catch (e) { const err = e; if (err.code === 'ENOENT') { /* not found, create it. */ } else { throw new Error(`Unknown error reading ${filename}: ${err.message}`); } } let writeFile = true; if (existing && existing === contents) { options.logger.log(`No edits needed in ${filename}`); return; } else if (existing) { writeFile = await query(`${chalk.bold(filename)} already exists`, 'Overwrite', false, options); } if (writeFile) { options.logger.log(`Writing ${filename}...`); if (!options.dryRun) { await writeFileAtomic(filename, contents); } options.logger.log(contents); } } async function generateESLintConfig(options) { return generateConfigFile(options, './eslint.config.js', exports.ESLINT_CONFIG); } async function generateESLintIgnore(options) { return generateConfigFile(options, './eslint.ignores.js', exports.ESLINT_IGNORE); } async function generateTsConfig(options) { const config = formatJson({ extends: './node_modules/gts/tsconfig-google.json', compilerOptions: { rootDir: '.', outDir: 'build' }, include: ['src/**/*.ts', 'test/**/*.ts'], }); return generateConfigFile(options, './tsconfig.json', config); } async function generatePrettierConfig(options) { const style = `module.exports = { ...require('gts/.prettierrc.json'), }; `; return generateConfigFile(options, './.prettierrc.js', style); } async function generateEditorConfig(options) { const config = `root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 insert_final_newline = true `; return generateConfigFile(options, './.editorconfig', config); } async function installDefaultTemplate(options) { const cwd = process.cwd(); const sourceDirName = path.join(__dirname, '../template'); const targetDirName = path.join(cwd, 'src'); try { fs.mkdirSync(targetDirName); } catch (e) { const err = e; if (err.code !== 'EEXIST') { throw err; } // Else, continue and populate files into the existing directory. } // Only install the template if no ts files exist in target directory. const files = fs.readdirSync(targetDirName); const tsFiles = files.filter(file => file.toLowerCase().endsWith('.ts')); if (tsFiles.length !== 0) { options.logger.log('Target src directory already has ts files. ' + 'Template files not installed.'); return false; } await ncpp(sourceDirName, targetDirName); options.logger.log('Default template installed.'); return true; } async function init(options) { let generatedPackageJson = false; let packageJson; try { packageJson = await (0, util_1.readJsonp)('./package.json'); } catch (e) { const err = e; if (err.code !== 'ENOENT') { throw new Error(`Unable to open package.json file: ${err.message}`); } const generate = await query(`${chalk.bold('package.json')} does not exist.`, 'Generate', true, options); if (!generate) { options.logger.log('Please run from a directory with your package.json.'); return false; } packageJson = DEFAULT_PACKAGE_JSON; generatedPackageJson = true; } const [addedDeps, addedScripts] = await Promise.all([ addDependencies(packageJson, options), addScripts(packageJson, options), ]); if (generatedPackageJson || addedDeps || addedScripts) { await writePackageJson(packageJson, options); } else { options.logger.log('No edits needed in package.json.'); } await Promise.all([ generateTsConfig(options), generateESLintConfig(options), generateESLintIgnore(options), generatePrettierConfig(options), generateEditorConfig(options), ]); await installDefaultTemplate(options); // Run `npm install` after initial setup so `npm run lint` works right away. if (!options.dryRun) { // --ignore-scripts so that compilation doesn't happen because there's no // source files yet. cp.spawnSync((0, util_1.getPkgManagerCommand)(options.yarn), ['install', '--ignore-scripts'], { stdio: 'inherit' }); } return true; } //# sourceMappingURL=init.js.map