Skip to content

Commit

Permalink
Added config to Docpub
Browse files Browse the repository at this point in the history
Integrated config to uploaders. Also slight uploaders tests refactoring.
Resolves #6
  • Loading branch information
SwinX committed Mar 22, 2017
1 parent c933ff4 commit 01e84cf
Show file tree
Hide file tree
Showing 22 changed files with 977 additions and 462 deletions.
11 changes: 6 additions & 5 deletions bin/docpub.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,19 @@

const program = require('commander');
const pkg = require('../package.json');
const DocpubPipeline = require('../lib/docpub');
const Docpub = require('../lib/docpub');

program
.version(pkg.version)
.option('-v --verbose', 'verbose output')
.option('-p --path <path>', 'path to documents directory (defaults to process directory)');
.option('--doc-path <docPath>', 'path to documents directory (defaults to process directory)')
.option('--config-path <configPath>', 'path for the config')
.option('-v --verbose', 'verbose output');

program.parse(process.argv);

const docpubPipeline = new DocpubPipeline(program);
const docpub = new Docpub(program);

docpubPipeline
docpub
.uploadCategory()
.catch(() => {
process.exit(1);
Expand Down
48 changes: 48 additions & 0 deletions lib/config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const fs = require('fs');
const path = require('path');
const applyScheme = require('./scheme');
const defineGetters = require('../metadata/utils').defineGetters;

const DEFAULT_CONFIG_NAME = 'docpub.conf';

module.exports = class Config {
constructor(configPath, docPath) {
if (!docPath && !configPath) {
throw new Error('No config path and no doc path provided');
}

this._configPath = path.resolve(configPath || path.join(docPath, DEFAULT_CONFIG_NAME));

this._load();
}

_load() {
const raw = this._read();
const parsed = this._parse(raw);

defineGetters(this, parsed);
}

_read() {
try {
return fs.readFileSync(this._configPath, 'utf-8');
} catch (e) {
if (e.code === 'ENOENT') {
throw new Error(`Config file does not exist: ${this._configPath}`);
}
throw e;
}
}

_parse(raw) {
const json = JSON.parse(raw);
const env = process.env;
const argv = process.argv;

return applyScheme({
options: json,
env,
argv
});
}
};
24 changes: 24 additions & 0 deletions lib/config/scheme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const configParser = require('gemini-configparser');

const root = configParser.root;
const section = configParser.section;
const option = configParser.option;

const shouldBeString = require('../metadata/validation-utils').shouldBeString;

const ENV_PREFIX = `${require('../../package').name}_`;

module.exports = root(
section({
username: option({
validate: shouldBeString
}),

apiToken: option({
validate: shouldBeString
}),

url: option({
validate: shouldBeString
})
}), {envPrefix: ENV_PREFIX});
14 changes: 8 additions & 6 deletions lib/docpub.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Promise = require('bluebird');
const path = require('path');
const _ = require('lodash');
const Config = require('./config');
const Category = require('./category');
const CategoryUploader = require('./zendesk-uploader/category-uploader');
const ZendeskDeleter = require('./zendesk-uploader/deleter');
Expand All @@ -9,11 +10,11 @@ const logger = require('./logger');
const chalk = require('chalk');

/**
* DocpubPipeline represents interface to utility. It is used as entry point for all operations.
* Docpub represents interface to utility. It is used as entry point for all operations.
* It's interface methods represent a command utility support.
* Must be initialised with args received from user.
*/
module.exports = class DocpubPipeline {
module.exports = class Docpub {
/**
* Creates DocpubPipeline instance
* Options, received from user, must be passed to this constructor
Expand All @@ -23,13 +24,14 @@ module.exports = class DocpubPipeline {
*/
constructor(opts) {
opts = _.defaults(opts || {}, {
path: process.cwd(),
docPath: process.cwd(),
verbose: false
});

logger.setup(opts);

this._path = path.resolve(opts.path);
this._path = path.resolve(opts.docPath);
this._config = new Config(opts.configPath, this._path);
}

/**
Expand All @@ -49,8 +51,8 @@ module.exports = class DocpubPipeline {

return category.read()
.then(() => {
const categoryUploader = new CategoryUploader(category);
const zendeskDeleter = new ZendeskDeleter(category);
const categoryUploader = new CategoryUploader(category, this._config);
const zendeskDeleter = new ZendeskDeleter(category, this._config);

return categoryUploader.upload()
.then(() => zendeskDeleter.delete());
Expand Down
37 changes: 18 additions & 19 deletions lib/zendesk-uploader/api-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,27 @@ const constants = require('./constants');

/**
* Creates and returns a zendesk API client
*
* @param {Config} config - global docpub configuraion
*
* @returns {Object} instance of the created zendesk API client
* @throws {Error} Will throw an error if the environment variables for the api client are not set
* @throws {Error} Will throw an error if config is missing
*/
const getClient = function() {
if (!process.env.ZENDESK_API_USERNAME) {
throw (new Error('Environment variable for Zendesk Username is undefined'));
const getClient = function(config) {
if (!config) {
throw new Error('Unable to configure ZenDesk client without a config');
}
if (!process.env.ZENDESK_API_TOKEN) {
throw (new Error('Environment variable for Zendesk Token is undefined'));
}
if (!process.env.ZENDESK_URL) {
throw (new Error('Environment variable for Zendesk Url is undefined'));
}
return new ZendeskClientWrapper(
zendesk.createClient({
username: process.env.ZENDESK_API_USERNAME,
token: process.env.ZENDESK_API_TOKEN,
remoteUri: buildHelpCenterUri(process.env.ZENDESK_URL),
helpcenter: true, // In order to use Help Center APIs, this varialbe must be set to `true` AND `remoteUri` must be set to the Help Center endpoint
disableGlobalState: true // Run as Library only - not scriptrunner
})
);

const options = {
username: config.username,
token: config.token,
remoteUri: buildHelpCenterUri(config.url),
helpcenter: true, // In order to use Help Center APIs, this varialbe must be set to `true` AND `remoteUri` must be set to the Help Center endpoint
disableGlobalState: true // Run as Library only - not scriptrunner
};
const client = zendesk.createClient(options);

return new ZendeskClientWrapper(client);
};

function buildHelpCenterUri(zendeskUrl) {
Expand Down
6 changes: 4 additions & 2 deletions lib/zendesk-uploader/article-uploader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ module.exports = class ArticleUploader extends Uploader {
/**
* Creates an ArticleUploader
* @param {object} article - contains `meta` object with metadata and `section` reference to parent section
* @param {Config} config - global docpub configuraion
* @param {object} [zendeskClient] - optional instance of the node-zendesk api client
*/
constructor(article, zendeskClient) {
super(article, zendeskClient);
constructor(article, config, zendeskClient) {
super(article, config, zendeskClient);
this._article = article;
this._config = config;
this._html = null;
}

Expand Down
12 changes: 7 additions & 5 deletions lib/zendesk-uploader/category-uploader.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ module.exports = class CategoryUploader extends Uploader {
/**
* Creates a CategoryUploader
* @param {object} category - contains `meta` object with metadata
* @param {object} [zendeskClient] - optional instance of the node-zendesk api client
* @param {Config} config - global docpub configuraion
* @param {Object} [zendeskClient] - optional instance of the node-zendesk api client
*/
constructor(category, zendeskClient) {
super(category, zendeskClient);
constructor(category, config, zendeskClient) {
super(category, config, zendeskClient);
this._category = category;
this._config = config;
}

/**
Expand Down Expand Up @@ -85,13 +87,13 @@ module.exports = class CategoryUploader extends Uploader {

_createSections() {
return Promise.all(this._category.sections.map((section) => {
return new SectionUploader(section, this._client).create();
return new SectionUploader(section, this._config, this._client).create();
}));
}

_syncSections() {
return Promise.all(this._category.sections.map((section) => {
return new SectionUploader(section, this._client).sync();
return new SectionUploader(section, this._config, this._client).sync();
}));
}

Expand Down
4 changes: 4 additions & 0 deletions lib/zendesk-uploader/client-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ module.exports = class ZendeskClientWrapper {
* @param {object} client - the node-zendesk client to wrap (object returned by zendesk::createClient() )
*/
constructor(client) {
if (!client) {
throw new Error('No ZenDesk client to wrap provided!');
}

this._client = client;
const endpoints = [
'articles',
Expand Down
7 changes: 4 additions & 3 deletions lib/zendesk-uploader/deleter.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ module.exports = class ZendeskDeleter {
/**
* Creates a ZendeskDeleter
* @param {object} category - Category instance to compare against
* @param {object} [zendeskClient] - optional instance of the node-zendesk api client
* @param {Config} config - global docpub configuraion
* @param {Object} zendeskClient - optional instance of the node-zendesk api client
*/
constructor(category, zendeskClient) {
this._client = zendeskClient || apiUtils.getClient();
constructor(category, config, zendeskClient) {
this._client = zendeskClient || apiUtils.getClient(config);
this._category = category;
this._documents = this._category.flatTree();
}
Expand Down
10 changes: 6 additions & 4 deletions lib/zendesk-uploader/section-uploader.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ module.exports = class SectionUploader extends Uploader {
/**
* Creates a SectionUploader
* @param {object} section - contains `meta` object with metadata and `category` reference to parent category
* @param {Config} config - global docpub configuraion
* @param {object} [zendeskClient] - optional instance of the node-zendesk api client
*/
constructor(section, zendeskClient) {
super(section, zendeskClient);
constructor(section, config, zendeskClient) {
super(section, config, zendeskClient);
this._section = section;
this._config = config;
}

/**
Expand Down Expand Up @@ -81,7 +83,7 @@ module.exports = class SectionUploader extends Uploader {
return;
}
return Promise.all(articles.map((article) => {
return new ArticleUploader(article, this._client).create();
return new ArticleUploader(article, this._config, this._client).create();
}));
}

Expand All @@ -90,7 +92,7 @@ module.exports = class SectionUploader extends Uploader {
return;
}
return Promise.all(articles.map((article) => {
return new ArticleUploader(article, this._client).sync();
return new ArticleUploader(article, this._config, this._client).sync();
}));
}

Expand Down
16 changes: 12 additions & 4 deletions lib/zendesk-uploader/uploader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,19 @@ module.exports = class Uploader {
/**
* Creates an Uploader
* @param {Object} document - document object containing metadata
* @param {Object} [zendeskClient] - optional instance of the node-zendesk api client
* @throws {Error} Will throw an error if the environment variables for the api client are not set
* @param {Config} config - docpub config
* @param {Object} zendeskClient - optional instance of the node-zendesk api client
*/
constructor(document, zendeskClient) {
this._client = zendeskClient || apiUtils.getClient();
constructor(document, config, zendeskClient) {
if (!document) {
throw new Error('No document for uploading provided');
}

if (!config) {
throw new Error('No config provided');
}

this._client = zendeskClient || apiUtils.getClient(config);
this._document = document;
this._meta = document.meta;
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"chalk": "1.1.3",
"commander": "2.9.0",
"fs-promise": "2.0.0",
"gemini-configparser": "0.3.0",
"highlight.js": "9.10.0",
"lodash": "4.17.4",
"markdown-it": "8.3.1",
Expand Down

0 comments on commit 01e84cf

Please sign in to comment.