Enable plugins to inject new commands to be available for use with the Gasket CLI.
This is a default plugin in the Gasket CLI and is always available for use.
Gasket commands extend the oclif command, with methods allowing interaction
with the Gasket engine. To create a new Gasket command, you must extend the base
GasketCommand, and implement the gasketRun
method.
class MyCommand extends GasketCommand {
/**
* Method requires implementation
* @override
*/
async gasketRun() {
const { special } = this.parsed.flags;
await this.gasket.exec('example', { special })
}
/**
* Method can optionally overridden to adjust config
* @param {Object} gasketConfig
* @returns {Promise<Object>} modified config
* @override
*/
async gasketConfigure(gasketConfig) {
return {
...gasketConfig,
extra: true
}
}
}
MyCommand.id = 'my-cmd';
MyCommand.description = 'My first command which executes the `example` lifecycle';
MyCommand.flags = {
special: flags.boolean({
default: false,
description: 'Is this run particularly special'
})
};
While the gasketRun
method must be implemented, the gasketConfigure
method
can be optionally overridden and is available for commands to adjust the Gasket
config.
The static id
property, is the name of the command which will be used with the
Gasket CLI in your app. For example npx gasket my-cmd
. The description
property will show up during npx gasket help
.
In the above example, you can see we are adding a "special" flag which can be
used with this command. Flags are described using the oclif flags utility made
available to the getCommands lifecycle as described below. GasketCommand
instances will have the the parsed arguments available as this.parsed
.
To make your command available to the CLI, it needs to be returned during the getCommands lifecycle.
This lifecycle allows plugins to add commands to the CLI. This hook should
return an extended GasketCommand
or array of such.
// gasket-plugin-example.js
module.exports = {
name: 'example',
hooks: {
/**
* Adds my-cmd to the Gasket CLI
*
* @param {Gasket} gasket - Gasket
* @param {GasketCommand} GasketCommand - Base Gasket command to extend
* @param {Object} flags - oclif flag types utility
* @returns {GasketCommand|GasketCommand[]} command(s)
*/
getCommands(gasket, { GasketCommand, flags }) {
class MyCommand extends GasketCommand {
async gasketRun() {
const { special } = this.parsed.flags;
await this.gasket.exec('example', { special });
}
}
MyCommand.id = 'my-cmd';
MyCommand.description = 'My first command which executes the `example` lifecycle';
MyCommand.flags = {
special: flags.boolean({
default: false,
description: 'Is this run particularly special'
})
};
return [MyCommand];
}
}
};
In a lifecycle hook, command details can be referenced from the Gasket
instance, allowing plugins to response to how the lifecycle was invoked. For
example, lets make another plugin that hooks our example
lifecycle from the
above command.
// gasket-plugin-another.js
module.exports = {
name: 'another-example',
hooks: {
async example(gasket, { special }) {
if(special) {
// do something special
}
if(gasket.command.id !== 'my-cmd') {
// this lifecycle was invoked by some other command
}
}
}
};
Signals the start of any Gasket command and allows running of code immediately
before other gasket
lifecycles. If it errors, the command will exit early.
// gasket-plugin-another.js
module.exports = {
name: 'another-example',
hooks: {
async init(gasket) {
console.log('init called for command:', gasket.command.id)
}
}
};
Because this lifecycle runs before for the configure lifecycle, only the partial Gasket config is available (see step 5 below).
The configure
lifecycle executes for each Gasket command.
Configuration for a Gasket session goes through a series of steps:
- Config file loaded by CLI
- Environment is set
- Overrides are applied
- Default plugins (including this) are added
- Commands adjust config by implementing
gasketConfigure
- -
init
lifecycle is executed - Plugins adjust config by hooking
configure
lifecycle
When the CLI starts up, it attempts to load the gasket.config
in its default
expected location, or as specified with command flags. Plugins then have the
opportunity in the configure
lifecycle.
// gasket-plugin-example.js
const fetch = require('@gasket/fetch');
module.exports = {
name: 'example',
hooks: {
async configure(gasket, gasketConfig) {
const { some: { serviceUrl } } = gasketConfig;
const response = await fetch(serviceUrl);
const remoteConfig = response.ok ? await response.json() : {};
return {
...gasketConfig,
...remoteConfig
};
}
}
};
In this example, the plugin hooks the configure
lifecycle, in order to add
config from a remote service. The configure
lifecycle is executed with the
execWaterfall method, so returning the modified config is necessary.