Skip to content

Commit

Permalink
#25: Ministrapper for CLI bootstrap config
Browse files Browse the repository at this point in the history
  • Loading branch information
pirog committed Sep 27, 2021
1 parent 6edd925 commit db2820e
Show file tree
Hide file tree
Showing 16 changed files with 189 additions and 122 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": "oclif",
"rules": {
"no-console": ["warn"],
"semi": ["error", "always"],
"semi-style": ["error", "last"],
"space-before-function-paren": ["error", {
Expand Down
2 changes: 1 addition & 1 deletion bin/hyperdrive.cmd
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
@echo off

node "%~dp0\run" %*
node "%~dp0\hyperdrive" %*
1 change: 0 additions & 1 deletion cli/commands/bye.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ class GoodbyeCommand extends Command {
async run() {
const {flags} = this.parse(GoodbyeCommand);
const name = flags.name || 'world';
console.log(flags);
this.log(`goodbye ${name} from ./src/commands/hello.js`);
}
}
Expand Down
1 change: 0 additions & 1 deletion cli/commands/hello.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ class HelloCommand extends Command {
async run() {
const {flags} = this.parse(HelloCommand);
const name = flags.name || 'world';
console.log(flags);
this.log(`hello ${name} from ./src/commands/hello.js`);
}
}
Expand Down
5 changes: 2 additions & 3 deletions cli/hooks/cnt.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
module.exports = async options => {
console.log(`example cnt hook running before ${options.id}`)
}

module.exports = async() => {};
137 changes: 62 additions & 75 deletions cli/hooks/init.js
Original file line number Diff line number Diff line change
@@ -1,81 +1,62 @@
const { Command } = require('@oclif/config');
const {flags} = require('@oclif/command');
const Config = require('@oclif/config');

class DynamicPlugin extends Config.Plugin {
get hooks() { return {} }
get topics() {
return []
}
get commandIDs() {
return ['mydynamiccommand']
}

get commands() {
const cmd = require('./../more/bye');
cmd.id = 'bye';
cmd.load = () => cmd;
return [cmd];
}
}

/*
* New plugin types:
* HyperdrivePlugin extends Config.Plugin
* 1. accepts a list of commands and an optional selector function for a "parent"
*
*
*/

module.exports = async (options) => {
// commands = [require('./../more/bye')];
// config.plugins.push(new DynamicPlugin(config))
// console.log(config.plugins);
// config.plugins[0].commands[0].flags.stuff = flags.string({char: 'z', description: 'name to print'});
console.log(options); // {id, argv, conf}
'use strict';

// Set DEBUG=* when -vvv is set?
// @NOTE: We use LET so we can rename the debugger as needed
const createDebugger = require('./../../lib/debug');
const path = require('path');
const Ministrapper = require('./../../lib/ministrapper');

// Load in bootstrap config from configDir
/*
bootstrap:
bootstrapper: ./lib/bootstrap.js
envPrefix:
- HYPERDRIVE_
configSources:
- config.yml
mode: 'cli',
packaged: _.has(process, 'pkg'),
channel: stable?
leia: _.has(process, 'env.LEIA_PARSER_RUNNING')
pluginDirs: _.compact(pluginDirs.concat(process.landoAppPluginDirs))
plugins: ,
product: 'lando',
userAgent: `Lando/${version}`,
//
channel: 'stable',
landoFile: '.lando.yml',
logLevelConsole: (this.argv().verbose) ? this.argv().verbose + 1 : this.logLevel,
logDir: path.join(this.userConfRoot, 'logs'),
mode: 'cli',
packaged: _.has(process, 'pkg'),
pluginDirs: _.compact(pluginDirs.concat(process.landoAppPluginDirs)),
preLandoFiles: ['.lando.base.yml', '.lando.dist.yml', '.lando.upstream.yml'],
postLandoFiles: ['.lando.local.yml'],
userConfRoot: this.userConfRoot,
version,
module.exports = async({id, argv, config}) => {
let debug = createDebugger(config.dirname, 'hooks', 'init');
const sourceConfig = path.join(__dirname, '..', '..', 'config.yml');
const userConfig = path.join(config.configDir, 'config.yml');

*/
// @TODO: set this based on some options (--debug?). if boolean/null should set * if string should set as if DEBUG
// envvar was set.
// @NOTE: this shows all debug right now for dev purposes. see @TODO above.
require('debug').enable('*'); // eslint-disable-line node/no-extraneous-require
debug('cli init start with id=%s, argv=%O', id, argv);

// Get config vars
const ENV_PREFIX = process.env.HYPERDRIVE_BOOTSTRAP_ENV_PREFIX || 'HYPERDRIVE';
const ENV_SEPARATOR = process.env.HYPERDRIVE_BOOTSTRAP_ENV_SEPARATOR || '_';

// Build up hyperdrive/product config from various sources
const bootstrapConf = new Ministrapper([config.name, 'lib', 'ministrapper']);

// @NOTE: do we want to accept some hidden args for this eg `hyperdrive --config bootstrap.module=something?`
// ENVARS are highest priority
bootstrapConf.env(ENV_PREFIX, ENV_SEPARATOR);
debug('get config from %s%s* envvars done', ENV_PREFIX, ENV_SEPARATOR);

// Then user config if it exists
bootstrapConf.file('user', {file: userConfig, format: require('nconf-yaml')});
debug('get config from file %s done', userConfig);

// run bootstrap
// 1. merge in more config
// 2. go through plugins and build manifest of components/config/whatever
// 3. traverse plugins to find commands
// 4. what do commandIDs do?
// 5. install defaults eg desktop -> lando-desktop
/*
// Then source config
bootstrapConf.file('source', {file: sourceConfig, format: require('nconf-yaml')});
debug('get config from file %s done', sourceConfig);

// Then defaults
bootstrapConf.defaults({
mode: 'cli',
leia: Object.prototype.hasOwnProperty.call(process.env, 'LEIA_PARSER_RUNNING'),
packaged: Object.prototype.hasOwnProperty.call(process, 'pkg'),
product: 'hyperdrive',
});
debug('get config from defaults');

// Reset debugger to indicate product status
debug = createDebugger(bootstrapConf.get('product'), 'hooks', 'init');
debug('bootstrap config set to %O', bootstrapConf.get());

// Set DEBUG=* when -vvv is set?
// run bootstrap
// 1. merge in more config
// 2. go through plugins and build manifest of components/config/whatever
// 3. traverse plugins to find commands
// 4. what do commandIDs do?
// 5. install defaults eg desktop -> lando-desktop
/*
hyperdrive:
// list of installers
installers:
Expand All @@ -91,5 +72,11 @@ module.exports = async (options) => {
mods: (?)
- {id: 'install', path: }
// commands = [require('./../more/bye')];
// config.plugins.push(new DynamicPlugin(config))
// console.log(config.plugins);
// config.plugins[0].commands[0].flags.stuff = flags.string({char: 'z', description: 'name to print'});
// console.log(id, argv, config); // {id, argv, conf}
*/
}
};
4 changes: 1 addition & 3 deletions cli/hooks/postrun.js
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
module.exports = async options => {
console.log(`example postrun hook running before ${options.id}`)
}
module.exports = async() => {};
11 changes: 1 addition & 10 deletions cli/hooks/prerun.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,2 @@
const _ = require('lodash');
const {flags} = require('@oclif/command');

module.exports = async options => {
// options.Command = require('./../commands/hello2');
// console.log(options);
// options.Command.flags.name2 = flags.string({char: 'z', description: 'name to print'}),


console.log(`example prerun hook running before ${options.id}`)
}
module.exports = async() => {};
23 changes: 0 additions & 23 deletions cli/more/bye.js

This file was deleted.

5 changes: 5 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
bootstrap:
module: ./lib/bootstrap.js
env:
separator: _
prefix: HYPERDRIVE
20 changes: 20 additions & 0 deletions lib/debug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* eslint-disable no-console */
let debug;
try {
debug = require('debug'); // eslint-disable-line node/no-extraneous-require
} catch (error) {}

const displayWarnings = () => {
if (process.listenerCount('warning') > 1) return;
process.on('warning', warning => {
console.error(warning.stack);
if (warning.detail) console.error(warning.detail);
});
};

module.exports = (...namespacers) => {
if (!debug) return (..._) => {};
const bug = debug([...namespacers].join(':'));
if (bug.enabled) displayWarnings();
return (...args) => bug(...args);
};
32 changes: 32 additions & 0 deletions lib/ministrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const Provider = require('nconf').Provider;

/*
* Just a lite wrapper around nconf to make things a bit easier
*/
class Ministrapper extends Provider {
constructor(namespace = 'ministrapper') {
super();
this.namespace = namespace;
}

// Ministrapper only cares about merging in some env namespace
env(namespace = 'HYPERDRIVE', separator = '_', overrides = {}) {
const debug = require('./debug')(...this.namespace, 'env');
const starter = `${namespace.toLowerCase()}${separator}`;
const defaults = {
parseValues: true,
lowerCase: true,
separator,
transform: obj => {
if (obj.key.startsWith(starter)) {
obj.key = obj.key.replace(starter, '');
debug('set %s=%s from environment', obj.key.split(separator).join(':'), obj.value);
return obj;
}
},
};
super.env({...defaults, ...overrides});
}
}

module.exports = Ministrapper;
27 changes: 27 additions & 0 deletions lib/plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* New plugin types:
* HyperdrivePlugin extends Config.Plugin
* 1. accepts a list of commands and an optional selector function for a "parent"
*
*
*/
/*
const Config = require('@oclif/config');
class DynamicPlugin extends Config.Plugin {
get hooks() { return {} }
get topics() {
return []
}
get commandIDs() {
return ['mydynamiccommand']
}
get commands() {
const cmd = require('../more/bye');
cmd.id = 'bye';
cmd.load = () => cmd;
return [cmd];
}
}
*/
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"dependencies": {
"@oclif/command": "^1",
"@oclif/config": "^1",
"@oclif/plugin-help": "^3"
"@oclif/plugin-help": "^3",
"nconf": "^0.11.3",
"nconf-yaml": "^1.0.2"
},
"devDependencies": {
"@oclif/errors": "^1.3.5",
Expand Down
2 changes: 0 additions & 2 deletions scripts/dev-version.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
* in json files with a "dev" version generated with `git describe`
*/

'use strict';

// Grab needed modules
const _ = require('lodash');
const {cli} = require('cli-ux');
Expand Down
Loading

0 comments on commit db2820e

Please sign in to comment.