ac-node-hipchat
Version:
A common module plugin for building Atlassian Connect add-ons for HipChat
324 lines (270 loc) • 7.8 kB
JavaScript
var _ = require('lodash');
var check = require('check-types');
var verify = check.verify;
var rsvp = require('rsvp');
function Builder(descriptor, callbacks) {
verify.object(descriptor);
// poor man's deep copy
descriptor = JSON.parse(JSON.stringify(descriptor));
var capabilities = descriptor.capabilities = descriptor.capabilities || {};
var consumer = capabilities.hipchatApiConsumer = capabilities.hipchatApiConsumer || {};
var scopes = consumer.scopes = consumer.scopes || [];
var installable = capabilities.installable = capabilities.installable || {};
var webhooks = capabilities.webhook = capabilities.webhook || [];
var frozen = false;
function checkMutable() {
if (frozen) throw new Error('Builder API is frozen');
}
// clients of this builder api only get one turn of the event loop to complete
// building operations; after that, the builder freezes and informs its client
// that it's ready by emitting the ready event
process.nextTick(function () {
frozen = true;
callbacks.ready(descriptor);
});
return {
key: function (key) {
checkMutable();
verify.string(key);
descriptor.key = key;
return this;
},
name: function (name) {
checkMutable();
verify.string(name);
descriptor.name = name;
return this;
},
description: function (description) {
checkMutable();
verify.string(description);
descriptor.description = description;
return this;
},
version: function (version) {
checkMutable();
verify.string(version);
descriptor.version = version;
return this;
},
vendor: function (vendor) {
checkMutable();
verify.object(vendor);
if (vendor.name) {
this.vendorName(vendor.name);
}
if (vendor.url) {
this.vendorUrl(vendor.url);
}
return this;
},
vendorName: function (vendorName) {
checkMutable();
verify.string(vendorName);
descriptor.vendor = descriptor.vendor || {};
descriptor.vendor.name = vendorName;
return this;
},
vendorUrl: function (vendorUrl) {
checkMutable();
verify.string(vendorUrl);
descriptor.vendor = descriptor.vendor || {};
descriptor.vendor.url = vendorUrl;
return this;
},
fromName: function (fromName) {
checkMutable();
verify.string(fromName);
consumer.fromName = fromName;
return this;
},
avatar: function(avatarUrl) {
checkMutable();
verify.string(avatarUrl);
consumer.avatar = {
"url": avatarUrl,
"url@2x": avatarUrl
};
return this;
},
scopes: function (scopeOrScopes) {
checkMutable();
if (_.isArray(scopeOrScopes)) {
consumer.scopes = scopes.concat(scopeOrScopes);
} else if (_.isString(scopeOrScopes)) {
consumer.scopes = scopes.concat([].slice.call(arguments));
} else {
throw Error('Unexpected scope type: ' + typeof scopeOrScopes);
}
return this;
},
allowRoom: function (value) {
checkMutable();
installable.allowRoom = !!value;
return this;
},
allowGlobal: function (value) {
checkMutable();
installable.allowGlobal = !!value;
return this;
},
// event, url
// event, callback
// event, patternRe, url
// event, patternRe, callback
// event, name, url
// event, name, callback
// event, name, patternRe, url
// event, name, patternRe, callback
// object
// object, callback (callback only used when no url given)
webhook: function () {
checkMutable();
var args = [].slice.call(arguments);
if (args[0] == null) {
return this;
}
var webhook = {}, callback, patternRe;
var objectMode;
function fail() {
throw new Error('Unexpected argument list: ' + args.join(', '));
}
function isUrl(str) {
return str && (check.webUrl(str) || (_.isString(str) && str.charAt(0) === '/'));
}
if (_.isString(args[0])) {
webhook.event = args[0];
} else if (_.isObject(args[0])) {
objectMode = true;
webhook = args[0];
callback = !webhook.url && args[1];
} else {
fail();
}
args.shift();
if (_.isString(args[0]) && !isUrl(args[0])) {
webhook.name = args[0];
args.shift();
}
if (_.isRegExp(args[0])) {
patternRe = args[0];
webhook.pattern = patternRe;
args.shift();
}
if (!objectMode) {
if (isUrl(args[0])) {
webhook.url = args[0];
} else if (_.isFunction(args[0])) {
callback = args[0];
} else {
fail();
}
}
if (webhook.event !== 'room_message' && webhook.pattern) {
throw new Error('Webhook pattern not supported for event type ' + webhook.event);
}
webhooks.push(webhook);
callbacks.addWebhook(webhook, callback);
return this;
},
// path
// path, allowAccessToRoomAdmins
configurable: function (path, allowAccessToRoomAdmins) {
checkMutable();
verify.string(path);
capabilities.configurable = capabilities.configurable || {};
capabilities.configurable.url = path;
capabilities.configurable.allowAccessToRoomAdmins = !!allowAccessToRoomAdmins;
return this;
},
glance: function (key, name, icon, target, path) {
checkMutable();
verify.string(key);
check.webUrl(path);
if (_.isString(name)) {
name = { value : name };
}
if (_.isString(icon)) {
icon = { url: icon, "url@2x": icon };
}
var glance = {
key: key,
name: name,
target: target,
icon: icon,
queryUrl: path
};
capabilities.glance = callbacks.glance || [];
capabilities.glance.push(glance);
return this;
},
webPanel: function(key, name, location, path) {
checkMutable();
verify.string(key);
check.webUrl(path);
if (_.isString(name)) {
name = { value : name };
}
var webPanel = {
key: key,
name: name,
location: location,
url: path
};
capabilities.webPanel = capabilities.webPanel || [];
capabilities.webPanel.push(webPanel);
return this;
},
action: function(key, name, location, target) {
checkMutable();
verify.string(key);
verify.string(target);
if (_.isString(name)) {
name = { value : name };
}
var action = {
key: key,
name: name,
location: location,
target: target
};
capabilities.action = capabilities.action || [];
capabilities.action.push(action);
return this;
},
externalPage: function(key, name, path) {
checkMutable();
verify.string(key);
check.webUrl(path);
if (_.isString(name)) {
name = { value : name };
}
var externalPage = {
key: key,
name: name,
url: path
};
capabilities.externalPage = capabilities.externalPage || [];
capabilities.externalPage.push(externalPage);
return this;
},
dialog: function(key, title, path, options) {
checkMutable();
verify.string(key);
check.webUrl(path);
if (_.isString(title)) {
title = { value : title };
}
var dialog = {
key: key,
title: title,
url: path,
options: options || {}
};
capabilities.dialog = capabilities.dialog || [];
capabilities.dialog.push(dialog);
return this;
}
};
};
module.exports = Builder;