commit
430e9f2cb8
No known key found for this signature in database
GPG Key ID: 51D5A407BFCE64A9
16 changed files with 2716 additions and 0 deletions
-
56.circleci/config.yml
-
11.editorconfig
-
1.eslintignore
-
6.eslintrc
-
9.gitignore
-
102README.md
-
5bin/run
-
3bin/run.cmd
-
67package.json
-
31src/commands/hello/index.ts
-
104src/commands/wall/index.ts
-
1src/index.ts
-
33src/utls/base-command.ts
-
146src/utls/print.ts
-
14tsconfig.json
-
2127yarn.lock
@ -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: /.*/ |
|||
@ -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 |
|||
@ -0,0 +1 @@ |
|||
/lib |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"extends": [ |
|||
"oclif", |
|||
"oclif-typescript" |
|||
] |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
*-debug.log |
|||
*-error.log |
|||
/.nyc_output |
|||
/dist |
|||
/lib |
|||
/package-lock.json |
|||
/tmp |
|||
node_modules |
|||
.idea/ |
|||
@ -0,0 +1,102 @@ |
|||
nbx |
|||
=== |
|||
|
|||
My own personal cli |
|||
|
|||
[](https://oclif.io) |
|||
[](https://npmjs.org/package/nbx) |
|||
[](https://circleci.com/gh/beaussart/nbx/tree/master) |
|||
[](https://codecov.io/gh/beaussart/nbx) |
|||
[](https://npmjs.org/package/nbx) |
|||
[](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 --> |
|||
@ -0,0 +1,5 @@ |
|||
#!/usr/bin/env node |
|||
|
|||
require('@oclif/command').run() |
|||
.then(require('@oclif/command/flush')) |
|||
.catch(require('@oclif/errors/handle')) |
|||
@ -0,0 +1,3 @@ |
|||
@echo off |
|||
|
|||
node "%~dp0\run" %* |
|||
@ -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" |
|||
} |
|||
@ -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}`) |
|||
} |
|||
} |
|||
} |
|||
@ -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() |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export {run} from '@oclif/command' |
|||
@ -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) |
|||
} |
|||
} |
|||
} |
|||
@ -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, |
|||
} |
|||
@ -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
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue