Browse Source

add new command add:prettier

pull/3/head
Nicolas Beaussart 6 years ago
parent
commit
130116cfb0
No known key found for this signature in database GPG Key ID: 51D5A407BFCE64A9
  1. 1
      .gitignore
  2. 21
      README.md
  3. 44
      package.json
  4. 150
      src/commands/add/prettier.ts
  5. 6
      src/commands/wall/index.ts
  6. 46
      src/utls/base-command.ts
  7. 146
      src/utls/print.ts
  8. 807
      yarn.lock

1
.gitignore

@ -7,3 +7,4 @@
/tmp
node_modules
.idea/
.nbxrc

21
README.md

@ -30,10 +30,31 @@ USAGE
<!-- usagestop -->
# Commands
<!-- commands -->
* [`nbx add:prettier`](#nbx-addprettier)
* [`nbx hello [FILE]`](#nbx-hello-file)
* [`nbx help [COMMAND]`](#nbx-help-command)
* [`nbx wall TERMS`](#nbx-wall-terms)
## `nbx add:prettier`
describe the command here
```
USAGE
$ nbx add:prettier
OPTIONS
-h, --help show CLI help
-r, --random Pick one randomly
-v, --verbose Verbose output
EXAMPLE
$ nbx wall
hello world from ./src/hello.ts!
```
_See code: [src/commands/add/prettier.ts](https://github.com/beaussart/nbx/blob/v0.0.0/src/commands/add/prettier.ts)_
## `nbx hello [FILE]`
describe the command here

44
package.json

@ -1,34 +1,39 @@
{
"name": "nbx",
"description": "My own personal cli",
"version": "0.0.0",
"author": "Nicolas Beaussart @beaussart",
"version": "1.0.0",
"author": "Nicolas Beaussart @beaussan",
"bin": {
"nbx": "./bin/run"
},
"bugs": "https://github.com/beaussart/nbx/issues",
"dependencies": {
"@oclif/command": "1",
"@oclif/config": "1",
"@oclif/command": "1.5.19",
"@oclif/config": "1.13.3",
"@oclif/errors": "1.2.2",
"@oclif/plugin-help": "2",
"@oclif/plugin-help": "2.2.3",
"@oclif/plugin-not-found": "1.2.3",
"@oclif/plugin-warn-if-update-available": "1.7.0",
"axios": "0.19.1",
"colors": "1.3.3",
"fs-jetpack": "2.2.3",
"ora": "4.0.0",
"tslib": "1"
"cosmiconfig": "6.0.0",
"gluegun": "4.1.2",
"isomorphic-git": "0.78.3",
"latest-version": "5.1.0",
"prompts": "2.3.0",
"tslib": "1.10.0"
},
"devDependencies": {
"@oclif/dev-cli": "1",
"@types/node": "10",
"eslint": "5.13",
"eslint-config-oclif": "3.1",
"eslint-config-oclif-typescript": "0.1",
"globby": "10",
"ts-node": "8",
"typescript": "3.3"
"@oclif/dev-cli": "1.22.2",
"@types/node": "10.17.14",
"@types/nodegit": "0.26.1",
"@types/prompts": "2.0.3",
"eslint": "5.13.0",
"eslint-config-oclif": "3.1.0",
"eslint-config-oclif-typescript": "0.1.0",
"globby": "10.0.2",
"ts-node": "8.6.2",
"typescript": "3.7.5"
},
"engines": {
"node": ">=8.0.0"
@ -53,7 +58,12 @@
"@oclif/errors",
"@oclif/plugin-warn-if-update-available",
"@oclif/plugin-not-found"
]
],
"topics": {
"add": {
"description": "install library to projects"
}
}
},
"repository": "beaussart/nbx",
"scripts": {

150
src/commands/add/prettier.ts

@ -0,0 +1,150 @@
// import {flags} from '@oclif/command'
import {BaseCommand} from '../../utls/base-command'
import * as latestVersion from 'latest-version'
import {system, filesystem} from 'gluegun'
import * as prompts from 'prompts'
import * as fs from 'fs'
import {plugins, statusMatrix, add, commit, config as gitConfig} from 'isomorphic-git'
plugins.set('fs', fs)
export default class Prettier extends BaseCommand {
static description = 'describe the command here'
static examples = [
`$ nbx wall
hello world from ./src/hello.ts!
`,
]
static flags = {
...BaseCommand.flags,
}
async run() {
const packagePath = filesystem.path('.', 'package.json')
if (filesystem.exists(packagePath) !== 'file') {
this.error('There is no package.json not found in the current folder')
}
const packageJson = filesystem.read(packagePath, 'json')
if (packageJson.devDependencies.prettier) {
this.error('Prettier is already installed in this project.')
}
const {mask, shouldCommit} = await prompts([
{
type: 'text',
message: 'On what files it should run prettier',
name: 'mask',
initial: '**/*.{js,vue,json,ts,tsx,md,yml,html}',
},
{
type: 'confirm',
message: 'Do you want gitmoji commits with the prettier setup ?',
name: 'shouldCommit',
initial: true,
},
], {onCancel: () => this.error('User canceled prompt.')})
if (shouldCommit) {
const {config} = await this.getConfig()
if (!config?.git?.user) {
this.error('Missing config key git.user for git commits')
}
if (!config?.git?.email) {
this.error('Missing config key git.email for git commits')
}
await gitConfig({
dir: '.',
path: 'user.name',
value: config?.git?.user,
})
await gitConfig({
dir: '.',
path: 'user.email',
value: config?.git?.email,
})
const changes = (await statusMatrix({dir: '.', pattern: '**'}))
.filter(([_, head, workdir, stage]) => !(head === 1 && workdir === 1 && stage === 1))
if (changes.length > 0) {
this.error('There is unsaved changed in the git repository, aborting')
}
}
const addDevDependency = async (name: string): Promise<void> => {
await this.runWithSpinner(`Adding ${name} dependency`, async () => {
const versionToInstall = await latestVersion(name)
await system.exec(`yarn add -D ${name}@${versionToInstall}`)
if (shouldCommit) {
await add({filepath: 'package.json', dir: '.'})
await add({filepath: 'yarn.lock', dir: '.'})
await commit({dir: '.', message: `:heavy_plus_sign: add ${name}@${versionToInstall}`})
}
})
}
await addDevDependency('prettier')
await addDevDependency('husky')
await addDevDependency('pretty-quick')
await this.runWithSpinner('Adding package.json scripts', async () => {
const packageJsonWithDeps = filesystem.read(packagePath, 'json')
const finalPackageJson = {
...packageJsonWithDeps,
scripts: {
...packageJsonWithDeps.scripts,
// eslint-disable-next-line no-useless-escape
'format:write': `prettier --write "${mask}"`,
// eslint-disable-next-line no-useless-escape
'format:check': `prettier --list-different "${mask}"`,
},
husky: {
hooks: {
'pre-commit': 'pretty-quick --staged',
},
},
}
await filesystem.write(packagePath, finalPackageJson, {jsonIndent: 2})
await system.exec('yarn')
if (shouldCommit) {
await add({filepath: 'package.json', dir: '.'})
await commit({dir: '.', message: ':wrench: add script and husky to package.json'})
}
})
await this.runWithSpinner('Adding .prettierrc config file', async () => {
const prettierRcFile = {
semi: true,
singleQuote: true,
printWidth: 120,
quoteProps: 'consistent',
trailingComma: 'all',
}
await filesystem.write(filesystem.path('.', '.prettierrc'), prettierRcFile, {jsonIndent: 2})
if (shouldCommit) {
await add({filepath: '.prettierrc', dir: '.'})
await commit({dir: '.', message: ':wrench: add prettierrc config file'})
}
})
await this.runWithSpinner('Updating code to match prettier style', async () => {
await system.exec('yarn format:write')
if (shouldCommit) {
const commitsPromice = (await statusMatrix({dir: '.', pattern: '**'}))
.filter(([_, head, workdir, stage]) => !(head === 1 && workdir === 1 && stage === 1))
.map(arr => arr[0])
.map(filepath => add({filepath, dir: '.'}))
await Promise.all(commitsPromice)
await commit({dir: '.', message: ':art: apply prettier style to project'})
}
})
}
}

6
src/commands/wall/index.ts

@ -1,7 +1,7 @@
import {flags} from '@oclif/command'
import {BaseCommand} from '../../utls/base-command'
import axios from 'axios'
import * as jetpack from 'fs-jetpack'
import {filesystem} from 'gluegun'
function booleanToNumber(value: boolean): string {
return value ? '1' : '0'
@ -76,7 +76,7 @@ hello world from ./src/hello.ts!
const filename = output ? output : `wallhaven-${firstImage.id}.jpg`
const spinner = spin('Downloading wallpaper')
if (jetpack.exists(filename)) {
if (filesystem.exists(filename)) {
if (force) {
spinner.warn('Overrinding ' + filename)
} else {
@ -85,7 +85,7 @@ hello world from ./src/hello.ts!
}
}
const writer = jetpack.createWriteStream(filename, {})
const writer = filesystem.createWriteStream(filename, {})
const response = await axios.get(firstImage.path, {
method: 'GET',

46
src/utls/base-command.ts

@ -1,12 +1,18 @@
import {Command, flags} from '@oclif/command'
import {print} from './print'
import {Input} from '@oclif/parser'
import { args } from '@oclif/parser'
import {print} from 'gluegun'
export interface BaseCommandFlags {
verbose: boolean;
}
export interface NbxConfig {
git: {
user: string;
email: string;
};
}
export abstract class BaseCommand extends Command {
static flags = {
verbose: flags.boolean({char: 'v', description: 'Verbose output'}),
@ -21,8 +27,14 @@ export abstract class BaseCommand extends Command {
async init() {
// do some initialization
const {flags} = this.parse(<Input<any>> this.constructor)
const {flags, args, argv} = this.parse(<Input<any>> this.constructor)
this.flags = flags
if (flags.verbose) {
this.tools.print.debug(args, 'args')
this.tools.print.debug(argv, 'argv')
this.tools.print.debug(flags, 'flags')
}
}
vprint(value: any, title?: string) {
@ -30,4 +42,32 @@ export abstract class BaseCommand extends Command {
this.tools.print.debug(value, title)
}
}
async runWithSpinner(name: string, func: (spinner: any) => Promise<any>): Promise<any> {
const spinner = this.tools.print.spin(name)
try {
const maybeRet = await func(spinner)
if (spinner.isSpinning) {
spinner.succeed()
}
return maybeRet
// eslint-disable-next-line unicorn/catch-error-name
} catch (maybeError) {
spinner.fail(maybeError.message)
this.error(maybeError)
}
}
async getConfig(): Promise<{ config: NbxConfig; path: string }> {
const cosmic = await import('cosmiconfig').then(cosmic => cosmic.cosmiconfig)
const explorer = cosmic('nbx')
const data = await explorer.search()
if (!data || data.isEmpty || !data.config) {
this.error('Config not found. Tried to look for a .nbxrc, .nbxrc.json, .nbxrc.yaml, .nbxrc.yml, .nbxrc.js')
}
return {
config: data?.config,
path: data?.filepath,
}
}
}

146
src/utls/print.ts

@ -1,146 +0,0 @@
import * as importedColors from 'colors/safe'
type NbxPrintColors = typeof importedColors & {
highlight: (t: string) => string;
info: (t: string) => string;
warning: (t: string) => string;
success: (t: string) => string;
error: (t: string) => string;
line: (t: string) => string;
muted: (t: string) => string;
}
// We're extending `colors` with a few more attributes
const colors = importedColors as NbxPrintColors
colors.setTheme({
highlight: 'cyan',
info: 'reset',
warning: 'yellow',
success: 'green',
error: 'red',
line: 'grey',
muted: 'grey',
})
/**
* Print a blank line.
*/
function newline() {
// eslint-disable-next-line no-console
console.log('')
}
/**
* Prints a divider line
*/
function divider() {
// eslint-disable-next-line no-console
console.log(colors.line('---------------------------------------------------------------'))
}
/**
* Prints text without theming.
*
* Use this when you're writing stuff outside the toolbox of our
* printing scheme. hint: rarely.
*
* @param message The message to write.
*/
function fancy(message: any): void {
// eslint-disable-next-line no-console
console.log(message)
}
/**
* Writes a normal information message.
*
* This is the default type you should use.
*
* @param message The message to show.
*/
function info(message: string): void {
// eslint-disable-next-line no-console
console.log(colors.info(message))
}
/**
* Writes an error message.
*
* This is when something horribly goes wrong.
*
* @param message The message to show.
*/
function error(message: string): void {
// eslint-disable-next-line no-console
console.log(colors.error(message))
}
/**
* Writes a warning message.
*
* This is when the user might not be getting what they're expecting.
*
* @param message The message to show.
*/
function warning(message: string): void {
// eslint-disable-next-line no-console
console.log(colors.warning(message))
}
/**
* Writes a debug message.
*
* This is for devs only.
*
* @param message The message to show.
*/
function debug(message: string, title = 'DEBUG'): void {
const topLine = `vvv -----[ ${title} ]----- vvv`
const botLine = `^^^ -----[ ${title} ]----- ^^^`
// eslint-disable-next-line no-console
console.log(colors.rainbow(topLine))
// eslint-disable-next-line no-console
console.log(message)
// eslint-disable-next-line no-console
console.log(colors.rainbow(botLine))
}
/**
* Writes a success message.
*
* When something is successful. Use sparingly.
*
* @param message The message to show.
*/
function success(message: string): void {
// eslint-disable-next-line no-console
console.log(colors.success(message))
}
/**
* Creates a spinner and starts it up.
*
* @param config The text for the spinner or an ora configuration object.
* @returns The spinner.
*/
function spin(config?: string | object): any {
return require('ora')(config || '').start()
}
const checkmark = colors.success('✔︎')
const xmark = colors.error('ⅹ')
export const print = {
colors,
newline,
divider,
fancy,
info,
error,
warning,
debug,
success,
spin,
checkmark,
xmark,
}

807
yarn.lock
File diff suppressed because it is too large
View File

Loading…
Cancel
Save