Skip to content

Commit

Permalink
feat(cli): add support for export plugins in cli
Browse files Browse the repository at this point in the history
  • Loading branch information
RyuuGan committed May 24, 2020
1 parent 4553fb7 commit 663bb8a
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 16 deletions.
73 changes: 73 additions & 0 deletions bin/pluginsLoader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import Debug from 'debug';
import path from 'path';
import { ExportPluginCtor, ExportPluginModule } from '../lib/types';
import { Utils } from '../lib/utils';

const info = Debug('sol-merger:info');
const error = Debug('sol-merger:error');

export class PluginLoadError extends Error {
constructor(message: string) {
super(message);
}
}

export class PluginsLoader {
#pluginPaths: string[];
#npmRoot: string;

constructor(pluginPaths: string[], npmRoot: string) {
this.#pluginPaths = pluginPaths;
this.#npmRoot = npmRoot;
}

async getPlugins(): Promise<ExportPluginCtor[]> {
const result: ExportPluginCtor[] = [];
for (const pluginPath of this.#pluginPaths) {
const fullPluginPath = this.getPluginPath(pluginPath);
if (!fullPluginPath) {
continue;
}
try {
const plugin = await this.tryLoadPlugin(fullPluginPath);
result.push(plugin);
} catch (e) {
if (e instanceof Error) {
error(e.message);
} else {
error(e);
}
}
}
return result;
}

private getPluginPath(pluginPath: string): string | null {
if (!this.#npmRoot && !Utils.isRelative(pluginPath)) {
info(
`[PluginsLoader] SKIP: Unable to load plugin '${pluginPath}' because npmRoot is not found.`,
);
return null;
}

if (Utils.isRelative(pluginPath)) {
return path.join(process.cwd(), pluginPath);
}
return path.join(this.#npmRoot, pluginPath);
}

private async tryLoadPlugin(modulePath: string): Promise<ExportPluginCtor> {
const resolvedPath = path.resolve(modulePath);
const pluginModule: Partial<ExportPluginModule> = await import(
resolvedPath
).catch((e) => {
throw new PluginLoadError(`Can not import plugin ${resolvedPath}`);
});
if (pluginModule.ExportPlugin) {
return pluginModule.ExportPlugin;
}
throw new PluginLoadError(
`Plugin ${resolvedPath} does not have exported member ExportPlugin`,
);
}
}
34 changes: 29 additions & 5 deletions bin/sol-merger.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
#!/usr/bin/env node

import fs from 'fs-extra';
import path from 'path';
import glob from 'glob';
import colors from 'cli-color';
import program from 'commander';
import Debug from 'debug';
import fs from 'fs-extra';
import glob from 'glob';
import path from 'path';
import { Merger } from '../lib/merger';
import { ExportPluginCtor } from '../lib/types';
import { Utils } from '../lib/utils';
import { done } from '../utils/done';
import program from 'commander';
import { PluginsLoader } from './pluginsLoader';

const debug = Debug('sol-merger:debug');

Expand All @@ -18,6 +21,12 @@ let append = '';
program
.option('-a, --append [append]', '', /^([a-zA-Z_]+)$/)
.option('-c, --remove-comments', `Remove comment from exports`, false)
.option(
'-p, --export-plugin [pathToPlugin]',
`Add post processor for exports`,
collectExportPluginOption,
[],
)
.arguments('<glob> [outputDir]')
.action((_glob, _outputDir) => {
inputGlob = _glob;
Expand All @@ -41,6 +50,7 @@ if (outputDir) {

debug('Output directory', outputDir);
debug('RemoveComments?', program.removeComments);
debug('ExportPlugins?', program.exportPlugin);

glob(
inputGlob,
Expand All @@ -59,14 +69,16 @@ async function execute(err: Error, files: string[]) {
debug(files);

if (files.length === 0) {
// eslint-disable-next-line
console.log(colors.yellow('No files found for merge'));
}

const exportPlugins = await getExportPlugins(program.exportPlugin);

const promises = files.map(async (file) => {
const merger = new Merger({
delimeter: '\n\n',
removeComments: program.removeComments,
exportPlugins,
});
let result: string;
result = await merger.processFile(file, true);
Expand All @@ -88,3 +100,15 @@ async function execute(err: Error, files: string[]) {
.then(() => done())
.catch(done);
}

function collectExportPluginOption(value: string, previousValue: string[]) {
return previousValue.concat([value]);
}

async function getExportPlugins(
plugins: string[],
): Promise<ExportPluginCtor[]> {
const npmRoot = await Utils.getNodeModulesPath(process.cwd());
const loader = new PluginsLoader(plugins, npmRoot);
return loader.getPlugins();
}
12 changes: 1 addition & 11 deletions lib/merger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,7 @@ export class Merger {
}

async getNodeModulesPath(file: string): Promise<string> {
return new Promise((resolve, reject) => {
exec('npm root', { cwd: path.dirname(file) }, (err, stdout) => {
if (err) {
error(
'Unable to find npm root directory. Make sure contract is inside npm package.',
);
return reject(err);
}
resolve(stdout.trim());
});
});
return Utils.getNodeModulesPath(file);
}

private isComment(str: string) {
Expand Down
4 changes: 4 additions & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ export interface ExportPluginProcessor {
export type ExportPluginCtor<
T extends ExportPluginProcessor = ExportPluginProcessor
> = new () => T;

export interface ExportPluginModule {
ExportPlugin: ExportPluginCtor
}
20 changes: 20 additions & 0 deletions lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
import { exec } from 'child_process';
import Debug from 'debug';
import path from 'path';

const error = Debug('sol-merger:error');

export class Utils {
static isRelative(file: string) {
return file.startsWith('.');
}

static async getNodeModulesPath(file: string): Promise<string> {
return new Promise((resolve, reject) => {
exec('npm root', { cwd: path.dirname(file) }, (err, stdout) => {
if (err) {
error(
'Unable to find npm root directory. Make sure contract is inside npm package.',
);
return reject(err);
}
resolve(stdout.trim());
});
});
}
}

0 comments on commit 663bb8a

Please sign in to comment.