Giter Site home page Giter Site logo

infinitered / gluegun Goto Github PK

View Code? Open in Web Editor NEW
2.9K 33.0 144.0 3.56 MB

A delightful toolkit for building TypeScript-powered command-line apps.

License: MIT License

JavaScript 5.57% TypeScript 88.40% EJS 6.00% Shell 0.03%
cli javascript toolkit nodejs

gluegun's Introduction

npm module CircleCI code style: prettier

Gluegun

gluegun

Gluegun is a delightful toolkit for building Node-based command-line interfaces (CLIs) in TypeScript or modern JavaScript, with support for:

๐ŸŒฏ parameters - command-line arguments and options
๐ŸŽ› template - generating files from templates
๐Ÿ—„ patching - manipulating file contents
๐Ÿ’พ filesystem - moving files and directories around
โš’ system - executing other command-line scripts
๐ŸŽ… http - interacting with API servers
๐Ÿ›Ž prompt - auto-complete prompts
๐Ÿ’ƒ print - printing pretty colors and tables
๐Ÿ‘ฉโ€โœˆ๏ธ semver - working with semantic versioning
๐ŸŽป strings - manipulating strings & template data
๐Ÿ“ฆ packageManager - installing NPM packages with Yarn or NPM

In addition, gluegun supports expanding your CLI's ecosystem with a robust set of easy-to-write plugins and extensions.

Notice

Gluegun is at a stable point and we aren't planning on building new features for it, although the community continues to send in PRs and we release them if they are performance, stability, types, or other similar enhancements. Read the Community Supported section to learn more.

Why use Gluegun?

Introductory YouTube video by our CTO, Jamon Holmgren: https://www.youtube.com/watch?v=_KEqXfLOSQY

You might want to use Gluegun if:

  • You need to build a CLI app
  • You want to have powerful tools at your fingertips
  • And you don't want to give up flexibility at the same time

If so ... welcome!

Quick Start

Just run the gluegun CLI like this:

# spin up your new CLI
npx gluegun new movies

# choose TypeScript or Modern JavaScript
# now jump into the source
cd movies

# and link your new executable
yarn link

# and run it!
movies help

You should see your new CLI help. Open the folder in your favorite editor and start building your CLI!

Code

Let's start with what a gluegun CLI looks like.

// in movie/src/cli.[js|ts]...

// ready
const { build } = require('gluegun')

// aim
const movieCLI = build('movie')
  .src(`${__dirname}/src`)
  .plugins('node_modules', { matching: 'movie-*' })
  .help()
  .version()
  .defaultCommand()
  .create()

// fire!
movieCLI.run()

Commands

Commands are simple objects that provide a name, optional aliases, and a function to run.

// in movie/src/commands/foo.js
module.exports = {
  name: 'foo',
  alias: 'f',
  run: async function (toolbox) {
    // gluegun provides all these features and more!
    const { system, print, filesystem, strings } = toolbox

    // ...and be the CLI you wish to see in the world
    const awesome = strings.trim(await system.run('whoami'))
    const moreAwesome = strings.kebabCase(`${awesome} and a keyboard`)
    const contents = `๐Ÿšจ Warning! ${moreAwesome} coming thru! ๐Ÿšจ`
    const home = process.env['HOME']
    filesystem.write(`${home}/realtalk.json`, { contents })

    print.info(`${print.checkmark} Citius`)
    print.warning(`${print.checkmark} Altius`)
    print.success(`${print.checkmark} Fortius`)
  },
}

See the toolbox api docs for more details on what you can do.

See the runtime docs for more details on building your own CLI and join us in the #gluegun channel of the Infinite Red Community Slack (community.infinite.red) to get friendly help!

Who Is Using This?

Additionally, the first versions of the AWS Amplify CLI (a CLI toolchain for simplifying serverless web and mobile development) used Gluegun. They've since integrated Gluegun's functionality into their CLI in a bespoke way, but you can still see Gluegun patterns in their CLI.

What's under the hood?

We've assembled an all-star cast of libraries to help you build your CLI.

โญ๏ธ ejs for templating
โญ๏ธ semver for version investigations
โญ๏ธ fs-jetpack for the filesystem
โญ๏ธ yargs-parser, enquirer, colors, ora and cli-table3 for the command line
โญ๏ธ axios & apisauce for web & apis
โญ๏ธ cosmiconfig for flexible configuration
โญ๏ธ cross-spawn for running sub-commands
โญ๏ธ execa for running more sub-commands
โญ๏ธ node-which for finding executables
โญ๏ธ pluralize for manipulating strings

Node.js 12.0+ is required.

Community CLIs and Plugins

Here are a few community CLIs based on Gluegun plus some plugins you can use. Is yours missing? Send a PR to add it!

Community Supported

While Gluegun is no longer actively developed by Infinite Red, it has built a community that cares deeply about it. Infinite Red won't be building new features ourselves for Gluegun, but we encourage the community to continue to send high quality pull requests. We will try to review and merge them in a timely manner.

If you're looking for alternatives, here's a list:

  • Rust CLI -- Rust is a rapidly growing community and hot language, and has the benefit of speed and not needing to rely on a local Node engine.
  • oclif - oclif is used by some large CLIs and is very actively maintained
  • commander and yeoman - commander and yeoman have been around a long time and have very large communities. Keep in mind that we built Gluegun to avoid Commander and Yeoman, so YMMV
  • vorpal - unfortunately looks like it isn't actively maintained
  • just make your own - you don't need a framework to make a Node CLI. Check out this article from Twilio

And of course, check out your favorite React Native Consultants, Infinite Red!.

gluegun's People

Contributors

0xflotus avatar 0xnawara avatar abrophy avatar andyfleming avatar cmckni3 avatar danawoodman avatar ekryski avatar elonvolo avatar gantman avatar hurricaneinteractive avatar imranolas avatar jamonholmgren avatar jesswallin avatar jperasmus avatar justinnoel avatar kathawala avatar kavengagne avatar lordbabuino avatar markusguenther avatar mikeerickson avatar morgandonze avatar orta avatar plrdev avatar renovate[bot] avatar richicoder1 avatar ruddell avatar ryanlntn avatar semantic-release-bot avatar skellock avatar yordis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gluegun's Issues

Add a debug flag

When a plugin, extension, or command is in a bad state, there's no way of knowing. Let's provide a --debug flag people can run which will emit the errors somehow.

Load plugin with matching support.

Currently we have

  .load('one_plugin_dir') // loads a directory as plugin
  .loadAll('many_plugins_dir') // loads the immediate sub-directories as plugins

But what we could use this as well:

  .loadAll('node_modules', 'ignite-*') // same, but only ones that match a jetpack pattern

Add string extension

I'd like to see a string extension. These would be the things that are automatically placed on the filters list in nunjucks. Let's grow this slowly and start with the cases that we already put into the generate extension.

They're useful to many people, so let's hang them on context.

Create a contributing document

globals

brew install nodejs
npm i -g n
n 7.2
npm i -g yarn

monorepo setup

git clone [email protected]/skellock/gluegun
cd gluegun
npm i

gluegun setup

cd packages/gluegun
yarn
yarn test
yarn run lint
yarn run watch

adding a feature

git branch fun
# furious typing
git commit -m "Adds fun"
# submit a PR with an awesome gif
# win

Branding Header

For printing the header in the CLI, if we're in brand mode, we will do the first of this list:

  • execute the default function in brand/header.js
  • render brand/header.txt as straight up text
  • render nothing

We only show the gluegun header if we're not in branded mode.

Support argument naming

@GantMan pointed out that commander has a dsl that might work well for us.

We could use that in the front matter for the *.js files by including it:

@command name <thing> [otherThing]

Also, lets promote & clobber onto the context.parameters object the things the user names (e.g. thing and otherThing).

Loading extensions dynamically

We need a way to load the extensions dynamically from plugins. The sample way we do it with commands, but this time from an extensions directory.

Make askToOverwrite more generic

Let's make this askToOverwrite prompt be more like askYesOrNo or something like that.

We can pass in { message: 'something', yes: 'Yup', no: 'Newp' } or something like that.

@GantMan helped me clarify what I was after. ๐ŸŒฎ

Default commands have unpruned params

As violent delights have violent ends, so do default commands have unpruned params
-- Dolores

running ignite add ui gives parameters.first the value of "default"
image

This looks like some leakage.

๐Ÿ‘™ Bikini Bonus:
Would be helpful to have parameters.last - which is how I plan on fixing this for futureproof ways. But I'm not a fan of that method.

Allow a silent mode config setting

Inside the app .toml file, let's add:

[defaults]
silent = true

When true (default is false), it will suppress all print commands triggered through the print extension.

Restricted plugin namespaces

Prevent these namespaces from being defined in 3rd party plugins:

  • spork
  • project
  • gluegun
  • default

If we see those namespaces, we should just go into a badnamespace error state on the plugin.

Use apisauce for http

@GantMan convinced me to use apisauce over axios because of the response type opinions. I agree i guess.

This will be the extension that lives under context.http.

Clean Runtime and CLI

These are the gateway to the system. And they've become a bit messy now. Let's clean these up so people wanting to hack at the core aren't confused.

Sporkable templates

Allow templates to be pseudo-forked.

Provide some kind of directory we can copy the *.njk files to. When we then run a generate() call, if the template has been overridden, we'll call that one instead.

This configuration will be handled in the app's configuration file.

Selectively show help depending on user input

When invoking gluegun, it currently shows all commands. This could quickly spiral. Let's switch to this:

gluegun

# show a list of namespaces
gluegun something

# show a list of commands in the something namespace

Consider renaming namespace to plugin name.

Plugins have unique names. I call these namespaces. But there's nothing magical or special about them. I'm thinking for simplicity sake, change the name from "namespace" to "name".

Namespace seems to imply there's stuff to learn. But there isn't. It's just a name.

Then the description of the command line goes:

<cliname> <pluginname> <commandname>

Support default commands

Currently a command can't live on it's own. It needs to live under a namespace.

With spork, i made that name space. And since namespaces aren't commands, you can't just type it. So I created default as the command.

So now it's:

gluegun spork default

Which is lame.

I want:

gluegun spork.

So we need to build the concept of a default command. default.js would be fine, but I think index.js is a little nicer because of the convention on the web and React Native.

Coveralls

Let's setup coveralls. I know my tests coverage is slipping, but having an automated score will motivate me.

Repair default plugin

This seems to be broken after a batch of refactoring. The tests didn't seem to catch this.

Continuous Integration

Will need to setup CI to protect this code base from myself.

I've only used semaphore, but I'm open to anything really.

Default namespace

Allow a command line option to pass to the CLI which specifies a default namespace.

gluegun --gluegun-namespace ignite

This namespace then gets priority over all others. In fact, it will be checked even before the other namespace names.

This allows people to brand their own cli like: alias ignite="gluegun --gluegun-namespace ignite" or even in their package.json bin scripts.

Add testing to the CLI.

There's no tests in the CLI. It kinda just grew and grew until it started doing important things. Now it needs tests.

Hidden plugins

We would like support for hidden plugins & commands.

This is useful if CLIs want to have their own plugins in the gluegun plugin format, but prevent the end user from having to know of them.

You would still be able to call these from runtime.run({}).

I recommend adding an object as a 2nd parameter to:

.load('dir', { hidden: true })
.loadDefault('dir', { hidden: true })
.loadAll('dir', { hidden: true })

Problem is, loadAll already has an optional 2nd parameter for matching sub-directories, so let's upgrade that to:

.loadAll('dir', { hidden: true, matching: 'ignite-*' })`

This would be a breaking change, but now is the time!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.