UNPKG

hpal

Version:
188 lines (134 loc) 11 kB
# hpal hapi pal CLI [![Build Status](https://travis-ci.org/hapipal/hpal.svg?branch=master)](https://travis-ci.org/hapipal/hpal) [![Coverage Status](https://coveralls.io/repos/hapipal/hpal/badge.svg?branch=master&service=github)](https://coveralls.io/github/hapipal/hpal?branch=master) Lead Maintainer - [Devin Ivy](https://github.com/devinivy) `hpal` was designed to help you, - :sparkles: create new hapi projects from the [pal boilerplate](https://github.com/hapipal/boilerplate) - :bouquet: generate files for routes, extensions, [models](https://github.com/hapipal/schwifty), [services](https://github.com/hapipal/schmervice), etc. via [`haute-couture`](https://github.com/hapipal/haute-couture) - :books: search the [hapi docs](https://github.com/hapijs/hapi/blob/master/API.md) from the command line– plus many others such as [joi](https://github.com/hapijs/joi/blob/master/API.md) and [toys](https://github.com/hapipal/toys/blob/master/API.md) - :honeybee: run custom commands defined by your server's hapi plugins ## Installation > Note, the hpal CLI is designed for use with **hapi v17+** and **nodejs v8+**. We recommend installing the hpal CLI as a dev dependency within your project, then invoking it using [npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b). ``` npm install --save-dev hpal npx hpal --help ``` If you want to try the hpal CLI right now, just copy and paste this right into your terminal! ``` npx hpal docs --ver 18.1.0 h.response ``` ## Usage ``` Usage: hpal <command> <options> Commands: hpal new <new-project-directory> e.g. hpal new ~/node-projects/new-pal-project hpal make [--asDir|--asFile] <haute-couture-item> [<item-name>] e.g. hpal make route create-user hpal docs[:<package-name>] [--ver x.y.z|ref] <docs-section> [<config-item>] e.g. hpal docs --ver 17.2.0 h.continue hpal run [--list] <cmd> [<cmd-options>] e.g. hpal run plugin-name:command-name Options: -h, --help show usage options -v, --version show version information -d, --asDir [make] creates new haute-couture item in a directory index file -f, --asFile [make] creates new haute-couture item in a file -V, --ver [docs] specifies the version/ref of the API docs to search for the given package -l, --list [run] lists all available commands on your server ``` ### Commands #### `hpal new` > ``` > hpal new <new-project-directory> > e.g. hpal new ~/node-projects/new-pal-project > ``` Clones the [pal boilerplate](https://github.com/hapipal/boilerplate), helps you fill-in initial details with [`npm init`](https://docs.npmjs.com/cli/init), pulls down the [pal flavors](https://github.com/hapipal/boilerplate#flavors), and leaves you prepared to make the first commit to your new project. #### `hpal make` > ``` > hpal make [--asDir|--asFile] <haute-couture-item> [<item-name>] > e.g. hpal make route create-user > ``` Creates a new file for a [`haute-couture` item](https://github.com/hapipal/haute-couture/blob/master/API.md#files-and-directories) with details ready to be filled-in. This is the best way to add a route, plugin, model, service, etc. to any project that uses haute-couture. Relies on the presence of a [`.hc.js`](https://github.com/hapipal/haute-couture/blob/master/API.md#specifying-amendments-with-hcjs) file in the project, even if it's empty, in order to determine the base directory of the plugin in which to write the file. If `.hc.js` contains amendments then those will be respected– in this way you can customize the behavior of `hpal make` per project. Projects created with [`hpal new`](#hpal-new) are already configured to work with `hpal make`. The `--asDir` and `--asFile` flags can be used to determine where the file is written. For a list item like `routes`, specifying `--asFile` (`hpal make route --asFile`) will create `routes.js` rather than `routes/index.js`. For a single item like `auth/default`, specifying `--asDir` (`hpal make auth/default --asDir`) will create `auth/default/index.js` rather than `auth/default.js`. When an optional `<item-name>` is specified then that will always place a file in the relevant directory with the name `<item-name>.js`. For example, `hpal make route create-user` will write the file `routes/create-user.js`. In order to omit the statement to enable [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) to the top of the generated files (per the hapi style guide), you may specify `exampleUseStrict` as `false` inside the `meta` property of the relevant haute-couture manifest items. #### `hpal docs` > ``` > hpal docs[:<package-name>] [--ver x.y.z|ref] <docs-section> [<config-item>] > e.g. hpal docs --ver 17.2.0 h.continue > ``` Searches the [hapi API reference](https://github.com/hapijs/hapi/blob/master/API.md) for the relevant section or configuration item then prints it formatted to the console. :dizzy: This command can also search the API reference for any package within the pal and hapijs ecosystems by specifying `<package-name>`, e.g. [`hpal docs:toys noop`](https://github.com/hapipal/toys/blob/master/API.md#toysnoop) or [`hpal docs:joi any.strip`](https://github.com/hapijs/joi/blob/master/API.md#anystrip). `<docs-section>` can be, - the name of any haute-couture item (e.g. `route`, `plugins`, `auth/default`) when in a haute-couture project - e.g. [`hpal docs auth/scheme`](https://github.com/hapijs/hapi/blob/master/API.md#server.auth.scheme()) - the name of any server, request, toolkit, etc. method - e.g. [`hpal docs request.setUrl`](https://github.com/hapijs/hapi/blob/master/API.md#request.setUrl()) - a substring of any heading from the docs - e.g. [`hpal docs router`](https://github.com/hapijs/hapi/blob/master/API.md#server.options.router) - an anchor seen anywhere in the docs - e.g. [`hpal docs '#catch-all-route'`](https://github.com/hapijs/hapi/blob/master/API.md#catch-all-route) When `<config-item>` is also specified, the first list item within the matched `<docs-section>` that matches text from `<config-item>` will be displayed on its own. For example, `hpal docs request.setUrl` is a long section of the docs but `hpal docs request.setUrl stripTrailingSlash` contains only information relevant to the `stripTrailingSlash` argument. All searches are case-insensitive. When `--ver` is specified as a semver version or a git ref (branch, tag, or commit), then that version of the docs will be searched. Otherwise, when inside a project the docs for the currently installed version of the given package will be searched. When not in a project and `--ver` is not specified, the master branch of the package's docs will be searched. #### `hpal run` > ``` > hpal run [--list] <cmd> [<cmd-options>] > e.g. hpal run plugin-name:command-name > ``` Runs the command `<cmd>` defined by some plugin on your hapi server. If the plugin `my-plugin` defines a command `do-the-thing`, then that command can be run with `hpal run my-plugin:do-the-thing`. If the plugin's name is prefixed with `hpal-`, then `hpal-` may be omitted when running the command. Plugins may also have a "default" command that can be run as `hpal run my-plugin`. A list of commands available on the server and their descriptions may be viewed with `hpal run --list`. Upon running a command hpal will initialize the server if it is not already initialized, then stop the server when the command exits successfully. ##### Requirements In order to use `hpal run`, hpal must be able to find your hapi server. It will look in `server.js` and `server/index.js` relative to the root of your project. That file should export a property `deployment` which contains a function that returns a hapi server, or a promise for a hapi server (for example, an `async` function). If you're using the [pal boilerplate](https://github.com/hapipal/boilerplate) then you should already be all set! Here is a very basic example, ```js // server/index.js const Hapi = require('hapi'); const AppPlugin = require('../app'); exports.deployment = async (start) => { const server = Hapi.server(); await server.register(AppPlugin); if (start) { await server.start(); } return server; }; // Start the server only when this file is // run directly from the CLI, i.e. "node ./server" if (!module.parent) { exports.deployment(true); } ``` ##### Creating your own commands Any hapi plugin can create commands that are runnable with `hpal run`! Commands are exposed to hpal using hapi's [`server.expose()`](https://github.com/hapijs/hapi/blob/master/API.md#server.expose()). Inside your plugin `my-plugin` simply call `server.expose('commands', commands)`, where `commands` is an object, - whose keys are command names. The name `default` is reserved for the command `hpal run my-plugin`. Camel-cased command names are converted to kebab-case, so if the key is `someCommand` then it is run using `hpal run my-plugin:some-command`. - whose values are either objects `{ command, description }` or functions `command` where, - `command` - a function with the signature `async function(server, args, root, ctx)`. - `server` - the initialized hapi server. - `args` - an array of all the command's CLI arguments. For example, running `hpal run my-plugin --custom-flag value` will result in `args` being `['--custom-flag', 'value']`. - `root` - an absolute path to the project's root directory. - `ctx` - a context object containing some hpal internals that may be useful during testing, plus some public helpers. The following are public: - `colors` - an object with functions for basic formatting of CLI output with colors and styles: `colors.green(str)`, `colors.yellow(str)`, `colors.red(str)`, `colors.grey(str)`, and `colors.bold(str)`. When the CLI does not support color, these functions take no effect. - `DisplayError` - a class that can be used to indicate a "safe" failure to hpal. Throwing a `DisplayError` will output the error's `message` and exit the process with code `1`, but not display a stack trace as would happen with an unexpected error. - `description` - a string description of the command displayed by `hpal run --list`. May alternatively be a function with signature `function (ctx)` that receives `ctx` as described above and returns a string description. For example, here is a plugin that creates a command to display the server's route table, ```js // hpal run route-table:show module.exports = { name: 'hpal-route-table', // The hpal- prefix is ignored when running the command register(server) { server.expose('commands', { show(srv) { console.log('Route table:'); srv.table().forEach(({ method, path }) => { console.log(` ${method} ${path}`); }); } }); } }; ```