Browse Source

🎉 Initial commit

pull/3/head
Nicolas Beaussart 6 years ago
commit
430e9f2cb8
No known key found for this signature in database GPG Key ID: 51D5A407BFCE64A9
  1. 56
      .circleci/config.yml
  2. 11
      .editorconfig
  3. 1
      .eslintignore
  4. 6
      .eslintrc
  5. 9
      .gitignore
  6. 102
      README.md
  7. 5
      bin/run
  8. 3
      bin/run.cmd
  9. 67
      package.json
  10. 31
      src/commands/hello/index.ts
  11. 104
      src/commands/wall/index.ts
  12. 1
      src/index.ts
  13. 33
      src/utls/base-command.ts
  14. 146
      src/utls/print.ts
  15. 14
      tsconfig.json
  16. 2127
      yarn.lock

56
.circleci/config.yml

@ -0,0 +1,56 @@
---
version: 2
jobs:
node-latest: &test
docker:
- image: node:latest
working_directory: ~/cli
steps:
- checkout
- restore_cache: &restore_cache
keys:
- v1-npm-{{checksum ".circleci/config.yml"}}-{{checksum "yarn.lock"}}
- v1-npm-{{checksum ".circleci/config.yml"}}
- run:
name: Install dependencies
command: yarn
- run: ./bin/run --version
- run: ./bin/run --help
- run:
name: Testing
command: yarn test
node-12:
<<: *test
docker:
- image: node:12
node-10:
<<: *test
docker:
- image: node:10
cache:
<<: *test
steps:
- checkout
- run:
name: Install dependencies
command: yarn
- save_cache:
key: v1-npm-{{checksum ".circleci/config.yml"}}-{{checksum "yarn.lock"}}
paths:
- ~/cli/node_modules
- /usr/local/share/.cache/yarn
- /usr/local/share/.config/yarn
workflows:
version: 2
"nbx":
jobs:
- node-latest
- node-12
- node-10
- cache:
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/

11
.editorconfig

@ -0,0 +1,11 @@
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

1
.eslintignore

@ -0,0 +1 @@
/lib

6
.eslintrc

@ -0,0 +1,6 @@
{
"extends": [
"oclif",
"oclif-typescript"
]
}

9
.gitignore

@ -0,0 +1,9 @@
*-debug.log
*-error.log
/.nyc_output
/dist
/lib
/package-lock.json
/tmp
node_modules
.idea/

102
README.md

@ -0,0 +1,102 @@
nbx
===
My own personal cli
[![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg)](https://oclif.io)
[![Version](https://img.shields.io/npm/v/nbx.svg)](https://npmjs.org/package/nbx)
[![CircleCI](https://circleci.com/gh/beaussart/nbx/tree/master.svg?style=shield)](https://circleci.com/gh/beaussart/nbx/tree/master)
[![Codecov](https://codecov.io/gh/beaussart/nbx/branch/master/graph/badge.svg)](https://codecov.io/gh/beaussart/nbx)
[![Downloads/week](https://img.shields.io/npm/dw/nbx.svg)](https://npmjs.org/package/nbx)
[![License](https://img.shields.io/npm/l/nbx.svg)](https://github.com/beaussart/nbx/blob/master/package.json)
<!-- toc -->
* [Usage](#usage)
* [Commands](#commands)
<!-- tocstop -->
# Usage
<!-- usage -->
```sh-session
$ npm install -g nbx
$ nbx COMMAND
running command...
$ nbx (-v|--version|version)
nbx/0.0.0 linux-x64 node-v10.16.0
$ nbx --help [COMMAND]
USAGE
$ nbx COMMAND
...
```
<!-- usagestop -->
# Commands
<!-- commands -->
* [`nbx hello [FILE]`](#nbx-hello-file)
* [`nbx help [COMMAND]`](#nbx-help-command)
* [`nbx wall TERMS`](#nbx-wall-terms)
## `nbx hello [FILE]`
describe the command here
```
USAGE
$ nbx hello [FILE]
OPTIONS
-f, --force
-h, --help show CLI help
-n, --name=name name to print
EXAMPLE
$ nbx hello
hello world from ./src/hello.ts!
```
_See code: [src/commands/hello/index.ts](https://github.com/beaussart/nbx/blob/v0.0.0/src/commands/hello/index.ts)_
## `nbx help [COMMAND]`
display help for nbx
```
USAGE
$ nbx help [COMMAND]
ARGUMENTS
COMMAND command to show help for
OPTIONS
--all see all commands in CLI
```
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v2.2.3/src/commands/help.ts)_
## `nbx wall TERMS`
describe the command here
```
USAGE
$ nbx wall TERMS
ARGUMENTS
TERMS The search terms for the wallpaper
OPTIONS
-a, --anime Enable anime category
-f, --force Override the file if found
-g, --general Enable general category
-h, --help show CLI help
-o, --output=output Output for the wallpaper
-p, --people Enable people category
-r, --random Pick one randomly
-s, --sketchy Enables sketchy search
-v, --verbose Verbose output
EXAMPLE
$ nbx wall
hello world from ./src/hello.ts!
```
_See code: [src/commands/wall/index.ts](https://github.com/beaussart/nbx/blob/v0.0.0/src/commands/wall/index.ts)_
<!-- commandsstop -->

5
bin/run

@ -0,0 +1,5 @@
#!/usr/bin/env node
require('@oclif/command').run()
.then(require('@oclif/command/flush'))
.catch(require('@oclif/errors/handle'))

3
bin/run.cmd

@ -0,0 +1,3 @@
@echo off
node "%~dp0\run" %*

67
package.json

@ -0,0 +1,67 @@
{
"name": "nbx",
"description": "My own personal cli",
"version": "0.0.0",
"author": "Nicolas Beaussart @beaussart",
"bin": {
"nbx": "./bin/run"
},
"bugs": "https://github.com/beaussart/nbx/issues",
"dependencies": {
"@oclif/command": "1",
"@oclif/config": "1",
"@oclif/errors": "1.2.2",
"@oclif/plugin-help": "2",
"@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"
},
"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"
},
"engines": {
"node": ">=8.0.0"
},
"files": [
"/bin",
"/lib",
"/npm-shrinkwrap.json",
"/oclif.manifest.json"
],
"homepage": "https://github.com/beaussart/nbx",
"keywords": [
"oclif"
],
"license": "MIT",
"main": "lib/index.js",
"oclif": {
"commands": "./lib/commands",
"bin": "nbx",
"plugins": [
"@oclif/plugin-help",
"@oclif/errors",
"@oclif/plugin-warn-if-update-available",
"@oclif/plugin-not-found"
]
},
"repository": "beaussart/nbx",
"scripts": {
"postpack": "rm -f oclif.manifest.json",
"posttest": "eslint . --ext .ts --config .eslintrc",
"prepack": "rm -rf lib && tsc -b && oclif-dev manifest && oclif-dev readme",
"test": "echo NO TESTS",
"version": "oclif-dev readme && git add README.md"
},
"types": "lib/index.d.ts"
}

31
src/commands/hello/index.ts

@ -0,0 +1,31 @@
import {Command, flags} from '@oclif/command'
export default class Index extends Command {
static description = 'describe the command here'
static examples = [
`$ nbx hello
hello world from ./src/hello.ts!
`,
]
static flags = {
help: flags.help({char: 'h'}),
// flag with a value (-n, --name=VALUE)
name: flags.string({char: 'n', description: 'name to print'}),
// flag with no value (-f, --force)
force: flags.boolean({char: 'f'}),
}
static args = [{name: 'file'}]
async run() {
const {args, flags} = this.parse(Index)
const name = flags.name || 'world'
this.log(`hello ${name} (${args.file}) from ./src/commands/hello.ts`)
if (args.file && flags.force) {
this.log(`you input --force and --file: ${args.file}`)
}
}
}

104
src/commands/wall/index.ts

@ -0,0 +1,104 @@
import {flags} from '@oclif/command'
import {BaseCommand} from '../../utls/base-command'
import axios from 'axios'
import * as jetpack from 'fs-jetpack'
function booleanToNumber(value: boolean): string {
return value ? '1' : '0'
}
interface WallhavenItem {
id: string;
url: string;
path: string;
}
export default class Wall extends BaseCommand {
static description = 'describe the command here'
static examples = [
`$ nbx wall
hello world from ./src/hello.ts!
`,
]
static args = [
{name: 'terms', description: 'The search terms for the wallpaper', required: true},
]
static flags = {
...BaseCommand.flags,
random: flags.boolean({char: 'r', description: 'Pick one randomly'}),
sketchy: flags.boolean({char: 's', description: 'Enables sketchy search'}),
general: flags.boolean({char: 'g', description: 'Enable general category'}),
anime: flags.boolean({char: 'a', description: 'Enable anime category'}),
people: flags.boolean({char: 'p', description: 'Enable people category'}),
output: flags.string({char: 'o', description: 'Output for the wallpaper'}),
force: flags.boolean({char: 'f', description: 'Override the file if found'}),
}
async run() {
const {args, argv, flags} = this.parse(Wall)
const {general, anime, people, output, force, random, sketchy} = flags
const {terms} = args
const {print: {spin}} = this.tools
this.vprint(args, 'args')
this.vprint(argv, 'argv')
this.vprint(flags, 'flags')
if (!general && !anime && !people) {
this.error('You must use at least one category flag')
}
const spinFetchList = spin('Searching wallpapers')
const categories = `${booleanToNumber(general)}${booleanToNumber(
anime
)}${booleanToNumber(people)}`
const {data: {data}} = await axios.get<{ data: WallhavenItem[] }>('https://wallhaven.cc/api/v1/search', {params: {
q: `${terms}`,
sorting: random ? 'random' : 'relevance',
categories,
purity: `1${booleanToNumber(sketchy)}0`,
atleast: '1920x1080',
ratios: '16x9',
}})
spinFetchList.succeed()
if (!data || data.length === 0) {
this.error('No image found, try another search term')
}
const firstImage = data[0]
this.vprint(firstImage, 'Image raw data')
const filename = output ? output : `wallhaven-${firstImage.id}.jpg`
const spinner = spin('Downloading wallpaper')
if (jetpack.exists(filename)) {
if (force) {
spinner.warn('Overrinding ' + filename)
} else {
spinner.fail('The file ' + filename + ' already exist')
this.error('The flag force was not set, aborting')
}
}
const writer = jetpack.createWriteStream(filename, {})
const response = await axios.get(firstImage.path, {
method: 'GET',
responseType: 'stream',
})
response.data.pipe(writer)
await new Promise((resolve, reject) => {
writer.on('finish', resolve)
writer.on('error', reject)
})
spinner.succeed()
}
}

1
src/index.ts

@ -0,0 +1 @@
export {run} from '@oclif/command'

33
src/utls/base-command.ts

@ -0,0 +1,33 @@
import {Command, flags} from '@oclif/command'
import {print} from './print'
import {Input } from '@oclif/parser'
import { args } from '@oclif/parser'
export interface BaseCommandFlags {
verbose: boolean;
}
export abstract class BaseCommand extends Command {
static flags = {
verbose: flags.boolean({char: 'v', description: 'Verbose output'}),
help: flags.help({char: 'h'}),
};
flags?: BaseCommandFlags;
public tools = {
print: print,
};
async init() {
// do some initialization
const {flags} = this.parse(<Input<any>> this.constructor)
this.flags = flags
}
vprint(value: any, title?: string) {
if (this.flags && this.flags.verbose) {
this.tools.print.debug(value, title)
}
}
}

146
src/utls/print.ts

@ -0,0 +1,146 @@
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,
}

14
tsconfig.json

@ -0,0 +1,14 @@
{
"compilerOptions": {
"declaration": true,
"importHelpers": true,
"module": "commonjs",
"outDir": "lib",
"rootDir": "src",
"strict": true,
"target": "es2017"
},
"include": [
"src/**/*"
]
}

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

Loading…
Cancel
Save