Skip to content

feat: allow plugins to use the userConfig object to set arbitrary data #118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 13, 2021
18 changes: 17 additions & 1 deletion src/base-commands/base-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { CLIError } = require('@oclif/errors');

const pkg = require('../../package.json');
const MessageTemplates = require('../services/messaging/templates');
const { Config, ConfigData } = require('../services/config');
const { Config, ConfigData, PluginConfig } = require('../services/config');
const { TwilioCliError } = require('../services/error');
const { logger, LoggingLevel } = require('../services/messaging/logging');
const { OutputFormats } = require('../services/output-formats');
Expand Down Expand Up @@ -170,6 +170,22 @@ class BaseCommand extends Command {
async install(name) {
return requireInstall(name, this);
}

get pluginConfig() {
if (!this._pluginConfig) {
const pluginName = getCommandPlugin(this);
this._pluginConfig = new PluginConfig(this.config.configDir, pluginName);
}
return this._pluginConfig;
}

async getPluginConfig() {
return this.pluginConfig.getConfig();
}

async setPluginConfig(config) {
return this.pluginConfig.setConfig(config);
}
}

BaseCommand.flags = {
Expand Down
24 changes: 24 additions & 0 deletions src/services/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,32 @@ class Config {
}
}

class PluginConfig {
constructor(configDir, pluginName) {
this.filePath = path.join(configDir, 'plugins', pluginName, 'config.json');
}

async getConfig() {
try {
return await fs.readJSON(this.filePath, { encoding: 'utf-8' });
} catch (error) {
return {};
}
}

async setConfig(config) {
try {
await fs.writeJSON(this.filePath, config);
} catch (error) {
await fs.mkdir(path.dirname(this.filePath), { recursive: true });
await fs.writeJSON(this.filePath, config);
}
}
}

module.exports = {
CLI_NAME,
Config,
ConfigData,
PluginConfig,
};
32 changes: 31 additions & 1 deletion test/services/config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const path = require('path');
const tmp = require('tmp');
const { expect, test, constants } = require('@twilio/cli-test');

const { Config, ConfigData } = require('../../src/services/config');
const { Config, ConfigData, PluginConfig } = require('../../src/services/config');

const FAKE_AUTH_TOKEN = '1234567890abcdefghijklmnopqrstuvwxyz';

Expand Down Expand Up @@ -231,5 +231,35 @@ describe('services', () => {
expect(saveMessage).to.contain(`${nestedConfig}${path.sep}config.json`);
});
});

describe('PluginConfig', () => {
let tempConfigDir;
beforeEach(() => {
tempConfigDir = tmp.dirSync({ unsafeCleanup: true });
});
afterEach(() => {
tempConfigDir.removeCallback();
});

test.it("loads an empty object when the plugin directory doesn't exist", async () => {
const pluginConfig = new PluginConfig(tempConfigDir.name, 'test-plugin');
expect(await pluginConfig.getConfig()).to.deep.equal({});
});

test.it("saves config to the plugin directory when it doesn't exist", async () => {
const pluginConfig = new PluginConfig(tempConfigDir.name, 'test-plugin');
await pluginConfig.setConfig({ foo: 'bar' });
expect(await pluginConfig.getConfig()).to.deep.equal({ foo: 'bar' });
});

test.it('overwrites config when it already exists', async () => {
const pluginConfig = new PluginConfig(tempConfigDir.name, 'test-plugin');
await pluginConfig.setConfig({ hello: 'world' });

const pluginConfig2 = new PluginConfig(tempConfigDir.name, 'test-plugin');
await pluginConfig2.setConfig({ foo: 'bar' });
expect(await pluginConfig2.getConfig()).to.deep.equal({ foo: 'bar' });
});
});
});
});