Skip to content

Commit

Permalink
Merge pull request #2 from J-Kallunki/feature/create-lib-ts
Browse files Browse the repository at this point in the history
[Feature]: create-lib-tsreact
  • Loading branch information
J-Kallunki authored Dec 14, 2018
2 parents 8408e5e + 57e28ed commit 60f02f2
Show file tree
Hide file tree
Showing 25 changed files with 693 additions and 10 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ yarn jkallunki-scripts
### Directly run a selected script:

```bash
yarn j-cl-babel
yarn j-cl-tsreact
```
![Opinionated React setup with Webpack 4 and Typescript](readme-files/create-lib-tsreact.png)

```bash
yarn j-cl-babel
```
![Opinionated Javascript-library setup with Babel ES6](readme-files/create-lib-babel.png)

## Acknowledgements
Expand Down
2 changes: 0 additions & 2 deletions create-lib-babel/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#!/usr/bin/env node

const { log } = require("../utils");
const { createLibBabel } = require("./create-lib-babel");

createLibBabel();
234 changes: 234 additions & 0 deletions create-lib-ts-react/create-lib-ts-react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
const clear = require("clear");
const inquirer = require("inquirer");
const { objValueMap, log, createFile, createDir, getTmp, runPrettier, removeKeyLines, replaceKeys, cpFile, saveSettings } = require("../utils");

const choose = () => {
const choices = [
{ name: "Webpack 4", disabled: "Selected by default", value: "WEBPACK" },
{ name: "Typescript", disabled: "Selected by default", value: "TYPESCRIPT" },
{ name: "React", disabled: "Selected by default", value: "REACT" },
{ name: "ES2015 and ESM (ES Modules) builds", value: "ESM" },
{ name: "Emotion 10", value: "EMOTION" },
{ name: "TSlint", value: "TSLINT" },
{ name: "React-testing-library & Jest", value: "JEST" },
{ name: "Lint-staged & Prettier", value: "LINTSTAGED" },
{ name: "Styleguidist", value: "STYLEGUIDIST" },
{ name: "Travis CI", value: "TRAVIS" },
];
const questions = [
{
type: "checkbox",
name: "VERSION",
message: "Choose features?",
choices
}
];
return inquirer.prompt(questions);
};

const askQuestions = ifCoverage => {
const coverage = [
{
name: "COVERAGESTATEMENTS",
type: "input",
message: "Coverage test percent - statements:",
default: "90"
},
{
name: "COVERAGEBRANCHES",
type: "input",
message: "Coverage test percent - branches:",
default: "90"
},
{
name: "COVERAGEFUNCTIONS",
type: "input",
message: "Coverage test percent - functions:",
default: "90"
},
{
name: "COVERAGELINES",
type: "input",
message: "Coverage test percent - lines:",
default: "90"
}
];
const questions = [
{
name: "PACKAGENAME",
type: "input",
message: "Library name:"
},
{
name: "DESCRIPTION",
type: "input",
message: "Description:"
},
{
name: "GITREPOSITORY",
type: "input",
message: "Git repository url (https://github.com/user/repo):"
},
{
name: "LICENSE",
type: "input",
message: "License (MIT):",
default: "MIT"
},
{
name: "AUTHORNAME",
type: "input",
message: "Author name:",
},
{
name: "AUTHOREMAIL",
type: "input",
message: "Author email:",
},
{
name: "AUTHORURL",
type: "input",
message: "Author website (url):",
},
...(ifCoverage ? coverage : []),
];
return inquirer.prompt(questions);
};

const createLibTsReact = async () => {
const tempFiles = getTmp('create-lib-ts-react', 'files');
const files = {
packageJson: 'packagejson',
gitignore:'gitignore',
readme: 'README.md',
travisYml: 'travisyml',
prettierRc: 'prettierrc',
webpackConfig: 'webpackconfigjs',
tslintJson: 'tslintjson',
tsconfigJson: 'tsconfigjson',
tsconfigEsmJson: 'tsconfigesmjson',
tsconfigEs2015Json: 'tsconfiges2015json',
styleguideConfigJs: 'styleguideconfigjs',
jestConfigJs: 'jestconfigjs',
jestSetupJs: 'jestsetupjs',
npmRc: 'npmrc'
}
const realFilenames = {
packageJson: 'package.json',
gitignore: '.gitignore',
travisYml: '.travis.yml',
prettierRc: '.prettierrc',
webpackConfig: 'webpack.config.js',
tslintJson: 'tslint.json',
tsconfigJson: 'tsconfig.json',
tsconfigEsmJson: 'tsconfig.esm.json',
tsconfigEs2015Json: 'tsconfig.es2015.json',
styleguideConfigJs: 'styleguide.config.js',
jestConfigJs: 'jest.config.js',
jestSetupJs: 'jest.setup.js',
npmRc: '.npmrc'
}
const filesSrc = objValueMap(value => `${tempFiles}/${value}`)(files);

clear();
log.figlet();
log.info('Opinionated React setup with Webpack 4 and Typescript');
log.br();

// ask questions
let { VERSION } = await choose();
const isFeat = feat => VERSION.includes(feat);

const isStyleguidist = isFeat('STYLEGUIDIST');
if (!isStyleguidist) VERSION = [...VERSION, 'NOSTYLEGUIDIST'];
const isJest = isFeat('JEST');
if (!isJest) VERSION = [...VERSION, 'NOJEST'];
const isTslint = isFeat('TSLINT');
if (!isTslint) VERSION = [...VERSION, 'NOTSLINT'];
const isLintstaged = isFeat('LINTSTAGED');
if (!isLintstaged) VERSION = [...VERSION, 'NOLINTSTAGED'];
const isTravis = isFeat('TRAVIS');
const isEsm = isFeat('ESM');
if (!isEsm) VERSION = [...VERSION, 'NOESM'];
const versionsPackageJson = {
styleguidist: 'STYLEGUIDIST',
jest: 'JEST',
tslint: 'TSLINT',
lintstaged: 'LINTSTAGED',
emotion: 'EMOTION',
travis: 'TRAVIS',
esm: 'ESM',
nostyleguidist: 'NOSTYLEGUIDIST',
nojest: 'NOJEST',
notslint: 'NOTSLINT',
nolintstaged: 'NOLINTSTAGED',
noesm: 'NOESM',
};
removeKeyLines([filesSrc.packageJson], versionsPackageJson, VERSION);
const versionsWebpackConfig = {
tslint: 'TSLINT',
};
removeKeyLines([filesSrc.webpackConfig], versionsWebpackConfig, VERSION);

// ask questions
const answers = await askQuestions(isJest);

replaceKeys([filesSrc.packageJson, filesSrc.readme, filesSrc.jestConfigJs], answers);

runPrettier({ dir: tempFiles });
clear();
createDir('src');
cpFile(`${tempFiles}/indextsx`, 'src/index.tsx');
if (isJest) {
cpFile(`${tempFiles}/indextesttsx`, 'src/index.test.tsx');
}
Object.keys(files).forEach(key => {
const check = {
travisYml: isTravis,
prettierRc: isLintstaged,
tslintJson: isTslint,
styleguideConfigJs: isStyleguidist,
jestConfigJs: isJest,
jestSetupJs: isJest,
tsconfigEsmJson: isEsm,
tsconfigEs2015Json: isEsm
}
if (check[key] === undefined || check[key]) {
const dest = realFilenames.hasOwnProperty(key) ? realFilenames[key] : files[key];
cpFile(filesSrc[key], dest);
}
});

saveSettings({
createLibTsReact: {
version: VERSION,
answers
}
});

clear();
log.thankYou();
log.info(`Run command: ${log.color('green')('yarn')}`);
log.info(`Check created package.json: ${log.color('yellow')('scripts')}!`);
log.info(`Create your code to ${log.color('yellow')('src/')}`);

if (isLintstaged) {
log.br();
log.info(`I suggest adding VSCode Prettier-plugin:
${log.color('green')('CMD+Shift+P')} ${log.color('yellow')('ext install esbenp.prettier-vscode')}
${log.color('green')('CMD+Shift+P')} ${log.color('yellow')('openWorkspaceSettings')}
${log.color('yellow')('"editor.formatOnSave": true,')}
${log.color('yellow')('"prettier.singleQuote": true')}`);
}

if (isTravis) {
log.br();
log.info(`${log.color('cyan')('https://travis-ci.com/')} "${log.color('green')('Sign in with Github')}"`);
log.info(`${log.color('cyan')('https://travis-ci.com/profile')} "${log.color('green')('Add repo')}"`);
}
log.credits();
};

module.exports = {
createLibTsReact
};
9 changes: 9 additions & 0 deletions create-lib-ts-react/files/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# __PACKAGENAME__

__DESCRIPTION__

## Usage

## Contributing

## Acknowledgements
14 changes: 14 additions & 0 deletions create-lib-ts-react/files/gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
dist
build
styleguide
tmp
.cache
.awcache
coverage

# dependencies
node_modules

# editors
.idea
.vscode
11 changes: 11 additions & 0 deletions create-lib-ts-react/files/indextesttsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { render } from 'react-testing-library';
import { App } from './index';
test('calling render with the same component on the same container does not remount', () => {
const appRenderer = render(<App />);
const { getByTestId, rerender } = appRenderer;
expect(getByTestId('app').textContent).toBe(`Let's begin`);
// re-render the same component
rerender(<App />);
expect(getByTestId('app').textContent).toBe(`Let's begin`);
});
6 changes: 6 additions & 0 deletions create-lib-ts-react/files/indextsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react';
export const App = () => (
<div className="App" data-testid="app">
Let's begin
</div>
);
31 changes: 31 additions & 0 deletions create-lib-ts-react/files/jestconfigjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html

module.exports = {
// Automatically clear mock calls and instances between every test
clearMocks: true,

collectCoverage: true,
// The directory where Jest should output its coverage files
coverageDirectory: 'coverage',
collectCoverageFrom: [
'src/**/*.ts',
'src/**/*.tsx',
'!src/**/index.tsx',
'!src/**/*.d.ts',
'!src/**/*.test.ts',
'!src/**/*.test.tsx',
'!**/node_modules/**',
],
coverageThreshold: {
global: {
branches: __COVERAGEBRANCHES__,
functions: __COVERAGEFUNCTIONS__,
lines: __COVERAGELINES__,
statements: __COVERAGESTATEMENTS__,
},
},
preset: 'ts-jest',

setupTestFrameworkScriptFile: require.resolve('./jest.setup.js'),
};
5 changes: 5 additions & 0 deletions create-lib-ts-react/files/jestsetupjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// add some helpful assertions
require('jest-dom/extend-expect');

// this is basically: afterEach(cleanup)
require('react-testing-library/cleanup-after-each');
1 change: 1 addition & 0 deletions create-lib-ts-react/files/npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
save-exact=true
Loading

0 comments on commit 60f02f2

Please sign in to comment.