UNPKG

8.57 kBJavaScriptView Raw
1"use strict";
2const child_process_1 = require("child_process");
3const cli_ux_1 = require("cli-ux");
4const json = require("comment-json");
5const fs = require("fs");
6const lodash_1 = require("lodash");
7const path = require("path");
8const util = require("util");
9const spawnPromise = util.promisify(child_process_1.exec);
10const command_1 = require("@oclif/command");
11// import * as inquirer from 'inquirer'
12// const enum TOptions {
13// typescript = 'typescript',
14// commitizen = 'commitizen',
15// tslint = 'tslint',
16// prettier = 'prettier',
17// jest = 'jest'
18// }
19class BearerPackageInit extends command_1.Command {
20 async run() {
21 const { flags } = this.parse(BearerPackageInit);
22 this.cwd = path.resolve(flags.path);
23 this.force = flags.force;
24 // add typescript
25 // add husky
26 // add commitizen
27 // add lint-staged => prettier
28 // const { choices } = await inquirer.prompt<{ choices: TOptions[] }>([
29 // {
30 // type: 'checkbox',
31 // choices: [
32 // {
33 // name: 'Typescript',
34 // value: TOptions.typescript,
35 // checked: true
36 // },
37 // {
38 // name: 'Commitizen (convential commits)',
39 // value: TOptions.commitizen,
40 // checked: true
41 // },
42 // {
43 // name: 'tslint (Typescript linter)',
44 // value: TOptions.tslint,
45 // checked: true
46 // },
47 // {
48 // name: 'prettier (format your code)',
49 // value: TOptions.prettier,
50 // checked: true
51 // },
52 // {
53 // name: 'jest (test your code)',
54 // value: TOptions.jest,
55 // checked: true
56 // }
57 // ],
58 // message: `Select things to add`,
59 // name: 'choices'
60 // }
61 // ])
62 // const options = new Set(choices)
63 // add dependencies
64 const dependencies = [
65 'typescript',
66 'husky',
67 'lint-staged',
68 'commitlint',
69 '@commitlint/config-conventional',
70 '@commitlint/cli',
71 'cz-conventional-changelog',
72 'tslint',
73 BEARER_TSLINT,
74 BEARER_TSCONFIG,
75 'tslint-config-prettier',
76 'prettier',
77 'jest',
78 'ts-jest',
79 '@types/jest'
80 ];
81 try {
82 await this.installDependencies(dependencies);
83 await this.initTypescriptProject();
84 await this.addHooksAndScripts();
85 await this.addTsLintConfig();
86 await this.setupJest();
87 }
88 catch (e) {
89 cli_ux_1.cli.action.stop();
90 return this.error(e);
91 }
92 // update package json
93 // update ts config
94 }
95 async installDependencies(dependencies) {
96 return this.withLoader(`Installing depenencies:\n * ${dependencies.join('\n * ')}`, () => this.runCommand(`yarn add -D ${dependencies.join(' ')}`));
97 }
98 async addHooksAndScripts() {
99 const packageFile = path.join(this.cwd, 'package.json');
100 try {
101 cli_ux_1.cli.action.start('Adding hooks');
102 const projectPackage = JSON.parse(fs.readFileSync(packageFile, { encoding: 'utf8' }));
103 if (!lodash_1.get(projectPackage, LINT_STAGED_KEY)) {
104 lodash_1.set(projectPackage, LINT_STAGED_KEY, LINT_STAGED);
105 }
106 else {
107 this.log('lint-staged already setup, skipping');
108 }
109 if (!lodash_1.get(projectPackage, COMMIT_LINT_CONFIG_KEY)) {
110 lodash_1.set(projectPackage, COMMIT_LINT_CONFIG_KEY, COMMIT_LINT_CONFIG);
111 }
112 else {
113 this.log('lint-staged already setup, skipping');
114 }
115 if (!lodash_1.get(projectPackage, LINT_STAGED_HOOK)) {
116 lodash_1.set(projectPackage, LINT_STAGED_HOOK, LINT_STAGED_HOOK_VALUE);
117 }
118 else {
119 this.log('lint-staged hook already setup, skipping');
120 }
121 if (!lodash_1.get(projectPackage, COMMIT_LINT_HOOK)) {
122 lodash_1.set(projectPackage, COMMIT_LINT_HOOK, COMMIT_LINT_HOOK_VALUE);
123 }
124 else {
125 this.log('commitlint hook already setup, skipping');
126 }
127 lodash_1.set(projectPackage, 'scripts.start', 'tsc --watch');
128 lodash_1.set(projectPackage, 'scripts.build', 'tsc -p tsconfig.json');
129 lodash_1.set(projectPackage, 'scripts.clean', 'rm -rf lib');
130 lodash_1.set(projectPackage, 'scripts.prepack', 'yarn clean && yarn build');
131 lodash_1.set(projectPackage, 'scripts.test', 'jest');
132 lodash_1.set(projectPackage, 'scripts.test:ci', 'jest --coverage');
133 fs.writeFileSync(packageFile, JSON.stringify(projectPackage, null, 2));
134 fs.writeFileSync(path.join(this.cwd, 'commitlint.config.js'), "module.exports = { extends: ['@commitlint/config-conventional'] }");
135 cli_ux_1.cli.action.stop();
136 }
137 catch (e) {
138 throw e;
139 }
140 }
141 async initTypescriptProject() {
142 return this.withLoader('Init Typescript stuff', async () => {
143 await this.runCommand('yarn tsc --init');
144 const configFile = path.join(this.cwd, 'tsconfig.json');
145 const src = path.join(this.cwd, 'src');
146 const config = json.parse(fs.readFileSync(configFile, { encoding: 'utf8' }), undefined, true);
147 lodash_1.set(config, 'extends', BEARER_TSCONFIG);
148 fs.writeFileSync(configFile, json.stringify(config, null, 2));
149 if (!fs.existsSync(src)) {
150 fs.mkdirSync(src);
151 fs.writeFileSync(path.join(src, 'index.ts'), '');
152 }
153 });
154 }
155 async addTsLintConfig() {
156 return this.withLoader('Init TSlint stuff', async () => {
157 const configFile = path.join(this.cwd, 'tslint.json');
158 if (!fs.existsSync(configFile)) {
159 await this.runCommand('yarn tslint --init');
160 }
161 const config = json.parse(fs.readFileSync(configFile, { encoding: 'utf8' }), undefined, true);
162 // as soon a we have created a bearer tslint we use it herer
163 lodash_1.set(config, 'extends', BEARER_TSLINT);
164 fs.writeFileSync(configFile, json.stringify(config, null, 2));
165 fs.writeFileSync(path.join(this.cwd, '.prettierrc'), json.stringify(prettierConfig, null, 2));
166 });
167 }
168 async setupJest() {
169 // check if a jest config is already present in package.json
170 if (!fs.existsSync(path.join(this.cwd, 'jest.config.js'))) {
171 return this.withLoader('Init Jest stuff', async () => {
172 await this.runCommand('yarn ts-jest config:init');
173 });
174 }
175 }
176 async withLoader(title, block) {
177 try {
178 cli_ux_1.cli.action.start(title);
179 await block();
180 cli_ux_1.cli.action.stop();
181 }
182 catch (e) {
183 if (this.force) {
184 console.error('Error on ', title, '\n', e.toString());
185 }
186 else {
187 throw e;
188 }
189 }
190 }
191 async runCommand(command) {
192 await spawnPromise(command, {
193 cwd: this.cwd
194 });
195 }
196}
197BearerPackageInit.description = 'describe the command here';
198BearerPackageInit.flags = {
199 path: command_1.flags.string({ char: 'p', default: process.cwd() }),
200 force: command_1.flags.boolean({ char: 'f', default: false })
201};
202BearerPackageInit.args = [{ name: 'file' }];
203const COMMIT_LINT_HOOK = 'husky.hooks.commit-msg';
204const COMMIT_LINT_HOOK_VALUE = 'commitlint -E HUSKY_GIT_PARAMS';
205const COMMIT_LINT_CONFIG = './node_modules/cz-conventional-changelog';
206const COMMIT_LINT_CONFIG_KEY = 'config.commitizen.path';
207const LINT_STAGED_HOOK = 'husky.hooks.pre-commit';
208const LINT_STAGED_HOOK_VALUE = 'lint-staged';
209const LINT_STAGED_KEY = 'lint-staged';
210const LINT_STAGED = {
211 '*.{css,md,tsx,ts}': ['prettier --write', 'tslint -c tslint.json --fix', 'git add']
212};
213const BEARER_TSLINT = '@bearer/tslint-config';
214const BEARER_TSCONFIG = '@bearer/tsconfig';
215const prettierConfig = {
216 semi: false,
217 singleQuote: true,
218 printWidth: 120,
219 tabWidth: 2
220};
221module.exports = BearerPackageInit;