Skip to content

Commit

Permalink
♻️ CLI refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Franck committed Jun 8, 2019
1 parent 1ae6c40 commit ead151b
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 224 deletions.
61 changes: 19 additions & 42 deletions src/cli.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
const ejs = require('ejs')
const path = require('path')
const inquirer = require('inquirer')
const { isNil } = require('lodash')
const getYear = require('date-fns/get_year')
const boxen = require('boxen')
const { getProjectInfos } = require('./utils')

const { getTemplate, createReadme } = require('./utils')
const { buildReadmeContent, writeReadme } = require('./readme')
const { getProjectInfos } = require('./project-infos')
const questionsBuilders = require('./questions')
const { showEndMessage } = require('./utils')

/**
* Ask user questions and return context to generate a README
*
* @param {Object} projectInfos
*/
const askQuestions = async projectInfos => {
let answersContext = {
Expand All @@ -35,44 +34,22 @@ const askQuestions = async projectInfos => {
}

/**
* Display end message
* Main process:
* 1) Gather project infos
* 2) Ask user questions
* 3) Build README content
* 4) Create README.md file
*
* @param {Object} args
*/
const displayEndMessage = () => {
process.stdout.write(
boxen(
`
README.md was successfully generated.
Thanks for using readme-md-generator !
`,
{
padding: 1,
margin: { top: 2, bottom: 3 },
borderColor: 'cyan',
align: 'center',
borderStyle: 'double'
}
)
)
}

module.exports = async args => {
const templatePath = path.resolve(
__dirname,
`../templates/${args.template}.md`
)

const template = await getTemplate(templatePath)
const mainProcess = async args => {
const projectInfos = await getProjectInfos()
const context = await askQuestions(projectInfos)
const currentYear = getYear(new Date())

const readmeContent = ejs.render(template, {
filename: templatePath,
currentYear,
...context
})
const answersContext = await askQuestions(projectInfos)
const readmeContent = await buildReadmeContent(answersContext, args.template)

await createReadme(readmeContent)
await writeReadme(readmeContent)

displayEndMessage()
showEndMessage()
}

module.exports = mainProcess
5 changes: 3 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/usr/bin/env node

const yargs = require('yargs')
const generateReadme = require('./cli')

const main = require('./cli')

yargs
.usage('Usage: $0 <command> [options]')
Expand All @@ -13,7 +14,7 @@ yargs
desc: 'The name of template you want to use',
default: 'default'
}),
args => generateReadme(args)
args => main(args)
)
.help()
.epilog(
Expand Down
141 changes: 141 additions & 0 deletions src/project-infos/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
const getProjectName = require('project-name')
const isNil = require('lodash/isNil')
const get = require('lodash/get')
const util = require('util')
const ora = require('ora')
const exec = util.promisify(require('child_process').exec)

const { getPackageJson } = require('../utils')

const GITHUB_URL = 'https://github.com/'

/**
* Clean repository url by removing '.git' and 'git+'
*
* @param {string} reposUrl
*/
const cleanReposUrl = reposUrl =>
reposUrl
.replace('\n', '')
.replace('git+', '')
.replace('.git', '')

/**
* Get repository url from pakage json
*
* @param {Object} reposUrl
*/
const getReposUrlFromPackageJson = async packageJson => {
const reposUrl = get(packageJson, 'repository.url', undefined)
return isNil(reposUrl) ? undefined : cleanReposUrl(reposUrl)
}

/**
* Get repository url from git
*/
const getReposUrlFromGit = async () => {
try {
const result = await exec('git config --get remote.origin.url')
return cleanReposUrl(result.stdout)
} catch (err) {
return undefined
}
}

/**
* Get repository url from package.json or git
*
* @param {Object} packageJson
*/
const getReposUrl = async packageJson =>
(await getReposUrlFromPackageJson(packageJson)) ||
(await getReposUrlFromGit())

/**
* Get repository issues url from package.json or git
*
* @param {Object} packageJson
*/
const getReposIssuesUrl = async packageJson => {
let reposIssuesUrl = get(packageJson, 'bugs.url', undefined)

if (isNil(reposIssuesUrl)) {
const reposUrl = await getReposUrl()

if (!isNil(reposUrl)) {
reposIssuesUrl = `${reposUrl}/issues`
}
}

return reposIssuesUrl
}

/**
* Check if repository is a Github repository
*
* @param {string} repositoryUrl
*/
const isGithubRepository = repositoryUrl =>
!isNil(repositoryUrl) && repositoryUrl.includes(GITHUB_URL)

/**
* Get github username from repository url
*
* @param {string} repositoryUrl
*/
const getGithubUsernameFromRepositoryUrl = repositoryUrl =>
repositoryUrl.replace(GITHUB_URL, '').split('/')[0]

/**
* Get license url from github repository url
*
* @param {string} repositoryUrl
*/
const getLicenseUrlFromGithubRepositoryUrl = repositoryUrl =>
`${repositoryUrl}/blob/master/LICENSE`

/**
* Get project informations from git and package.json
*/
const getProjectInfos = async () => {
const spinner = ora('Gathering project infos').start()

const packageJson = await getPackageJson()
const name = getProjectName() || undefined
const description = get(packageJson, 'description', undefined)
const engines = get(packageJson, 'engines', undefined)
const author = get(packageJson, 'author', undefined)
const version = get(packageJson, 'version', undefined)
const licenseName = get(packageJson, 'license', undefined)
const documentationUrl = get(packageJson, 'homepage', undefined)
const repositoryUrl = await getReposUrl(packageJson)
const contributingUrl = await getReposIssuesUrl(packageJson)
const isGithubRepos = isGithubRepository(repositoryUrl)
const githubUsername = isGithubRepos
? getGithubUsernameFromRepositoryUrl(repositoryUrl)
: undefined
const licenseUrl = isGithubRepos
? getLicenseUrlFromGithubRepositoryUrl(repositoryUrl)
: undefined

spinner.succeed('Project infos gathered')

return {
name,
description,
version,
author,
repositoryUrl,
contributingUrl,
githubUsername,
engines,
licenseName,
licenseUrl,
documentationUrl,
isGithubRepos
}
}

module.exports = {
getProjectInfos
}
34 changes: 11 additions & 23 deletions src/questions/index.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
const askProjectName = require('./project-name')
const askProjectDescription = require('./project-description')
const askAuhtorName = require('./author-name')
const askAuthorGithub = require('./author-github')
const askAuthorTwitter = require('./author-twitter')
const askLicenseName = require('./license-name')
const askLicenseUrl = require('./license-url')
const askContributing = require('./contributing')
const askProjectVersion = require('./project-version')
const askProjectPrerequisites = require('./project-prerequisites')
const askProjectDocumentationUrl = require('./project-documentation-url')

module.exports = {
askProjectName,
askProjectVersion,
askProjectDescription,
askProjectDocumentationUrl,
askAuhtorName,
askAuthorGithub,
askAuthorTwitter,
askProjectPrerequisites,
askLicenseName,
askLicenseUrl,
askContributing
askProjectName: require('./project-name'),
askProjectVersion: require('./project-version'),
askProjectDescription: require('./project-description'),
askProjectDocumentationUrl: require('./project-documentation-url'),
askAuhtorName: require('./author-name'),
askAuthorGithub: require('./author-github'),
askAuthorTwitter: require('./author-twitter'),
askProjectPrerequisites: require('./project-prerequisites'),
askLicenseName: require('./license-name'),
askLicenseUrl: require('./license-url'),
askContributing: require('./contributing')
}
2 changes: 1 addition & 1 deletion src/questions/project-prerequisites.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const isNil = require('lodash/isNil')
const isEmpty = require('lodash/isEmpty')
const isNil = require('lodash/isNil')

/**
* Return engines as formatted choices
Expand Down
60 changes: 60 additions & 0 deletions src/readme/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const ejs = require('ejs')
const path = require('path')
const ora = require('ora')
const util = require('util')
const getYear = require('date-fns/get_year')
const readFile = util.promisify(require('fs').readFile)
const writeFile = util.promisify(require('fs').writeFile)

/**
* Create readme file from the given readmeContent
*
* @param {string} readmeContent
*/
const writeReadme = async readmeContent =>
await writeFile('README.md', readmeContent)

/**
* Get README template content from the given templatePath
*
* @param {string} templatePath
*/
const getReadmeTemplate = async templatePath => {
const spinner = ora('Loading README template').start()

try {
const template = await readFile(templatePath, 'utf8')
spinner.succeed('README template loaded')
return template
} catch (err) {
spinner.fail('README template loading fail')
throw err
}
}

/**
* Build README content with the given answersContext and templateName
*
* @param {Object} context
* @param {string} templateName
*/
const buildReadmeContent = async (context, templateName) => {
const currentYear = getYear(new Date())
const templatePath = path.resolve(
__dirname,
`../../templates/${templateName}.md`
)
const template = await getReadmeTemplate(templatePath)

return ejs.render(template, {
filename: templatePath,
currentYear,
...context
})
}

module.exports = {
getReadmeTemplate,
writeReadme,
buildReadmeContent
}
Loading

0 comments on commit ead151b

Please sign in to comment.