Skip to content

Commit

Permalink
Use relative command paths to fix distributed CLIs
Browse files Browse the repository at this point in the history
Fixes #12
  • Loading branch information
Vadim Demedes committed Jun 1, 2019
1 parent b4175d1 commit 305937b
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 14 deletions.
5 changes: 3 additions & 2 deletions boot.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
'use strict';
const path = require('path');
const camelcaseKeys = require('camelcase-keys');
const decamelize = require('decamelize');
const yargs = require('yargs');

module.exports = (React, Ink, commands) => {
module.exports = (dirname, React, Ink, commands) => {
const addCommand = (command, yargs) => {
// Yargs expects a special format for positional args when defining a command
// in order to correctly parse them, e.g. "<first-arg> <second-arg>"
Expand Down Expand Up @@ -55,7 +56,7 @@ module.exports = (React, Ink, commands) => {
inputArgs: argv._
};

const UI = require(command.buildPath).default;
const UI = require(path.join(dirname, 'commands', command.path)).default;
const {waitUntilExit} = Ink.render(React.createElement(UI, props));

waitUntilExit().catch(error => {
Expand Down
2 changes: 1 addition & 1 deletion entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ const {commands} = require('./commands.json'); // eslint-disable-line import/no-
// This file is an entrypoint of CLI applications based on Pastel
// This file is copied to "build" directory of the CLI and "bin" field
// in package.json must point to it
boot(React, Ink, commands);
boot(__dirname, React, Ink, commands);
6 changes: 3 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Pastel extends EventEmitter {
}

async scanCommands() {
const commands = await readCommands(this.commandsPath, path.join(this.buildPath, 'commands'));
const commands = await readCommands(this.commandsPath, this.commandsPath);
await writeFile(path.join(this.buildPath, 'commands.json'), JSON.stringify({commands}, null, '\t'));

return commands;
Expand Down Expand Up @@ -65,7 +65,7 @@ class Pastel extends EventEmitter {
await this.createBuildDir();
await this.saveEntrypoint();
const commands = await this.scanCommands();
const bundler = this.createBundler(getEntrypointPaths(commands), {watch: false});
const bundler = this.createBundler(getEntrypointPaths(this.commandsPath, commands), {watch: false});

return bundler.bundle();
}
Expand Down Expand Up @@ -107,7 +107,7 @@ class Pastel extends EventEmitter {

const commands = await this.scanCommands();

bundler = this.createBundler(getEntrypointPaths(commands), {watch: true});
bundler = this.createBundler(getEntrypointPaths(this.commandsPath, commands), {watch: true});
bundler.on('buildStart', onStart);

bundler.on('bundled', handleAsyncErrors(async () => {
Expand Down
7 changes: 4 additions & 3 deletions lib/get-entrypoint-paths.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
'use strict';
const path = require('path');

// This function extracts all command paths into a flat array
const getEntrypointPaths = commands => {
const getEntrypointPaths = (commandsPath, commands) => {
const entrypointPaths = [];

for (const command of commands) {
entrypointPaths.push(command.path);
entrypointPaths.push(...getEntrypointPaths(command.subCommands));
entrypointPaths.push(path.join(commandsPath, command.path));
entrypointPaths.push(...getEntrypointPaths(commandsPath, command.subCommands));
}

return entrypointPaths;
Expand Down
9 changes: 4 additions & 5 deletions lib/read-commands.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';
const {promisify} = require('util');
const {join, basename} = require('path');
const {join, basename, relative} = require('path');
const fs = require('fs');
const parseCommand = require('./parse-command');

Expand All @@ -10,7 +10,7 @@ const isIndexCommand = command => command.path.endsWith('index.js');

// `dirPath` is a path in source `commands` folder
// `buildDirPath` is a path to the same folder, but in `build` folder
const readCommands = async (dirPath, buildDirPath) => {
const readCommands = async (commandsPath, dirPath) => {
const paths = fs.readdirSync(dirPath);
const commands = [];

Expand All @@ -20,7 +20,7 @@ const readCommands = async (dirPath, buildDirPath) => {
const stats = await stat(fullPath);

if (stats.isDirectory()) {
const subCommands = await readCommands(fullPath, join(buildDirPath, path));
const subCommands = await readCommands(commandsPath, fullPath);
const indexCommand = subCommands.find(isIndexCommand);

commands.push({
Expand All @@ -34,8 +34,7 @@ const readCommands = async (dirPath, buildDirPath) => {
const {description, args} = await parseCommand(fullPath);

commands.push({
path: fullPath,
buildPath: join(buildDirPath, path),
path: relative(commandsPath, fullPath),
name: basename(fullPath, '.js'),
description,
args,
Expand Down

0 comments on commit 305937b

Please sign in to comment.