jive-sdk
Version:
Node.js SDK for Jive Software to assist with the development of add-ons
886 lines (797 loc) • 37.2 kB
JavaScript
/*
* Copyright 2013 Jive Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @module extensions
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var fs = require('fs-extra'),
q = require('q'),
jive = require('../../api'),
_ = require("underscore");
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// public
/**
* @returns {Promise} Promise
*/
exports.find = function() {
return jive.service.persistence().find( 'jiveExtension', { 'id' : 'jiveExtension' } ).then( function( records ) {
if ( records && records.length > 0 ) {
return records[0];
}
return null;
});
};
/**
* @param record
* @returns {Promise} Promise
*/
exports.save = function(record) {
return jive.service.persistence().save('jiveExtension', 'jiveExtension', record);
};
/**
* @param rootDir
* @param tilesDir
* @param appsDir
* @param cartridgesDir
* @param storagesDir
* @param servicesDir
* @param packageApps
* @returns {Promise} Promise
*/
exports.prepare = function (rootDir, tilesDir, appsDir, cartridgesDir, storagesDir, servicesDir, packageApps) {
var extensionSrcDir = ( rootDir ? rootDir + '/' : '' ) + 'extension_src';
var extensionPublicDir = extensionSrcDir + '/public';
var svrPublicDir = ( rootDir ? rootDir + '/' : '' ) + 'public';
var extensionZipDir = ( rootDir ? rootDir + '/' : '' ) + 'extension.zip';
return jive.util.fsexists(extensionSrcDir).then(function( exists ) {
if ( !exists ) jive.util.fsmkdir( extensionSrcDir)
}).then( function() {
if ( packageApps ) {
// create the public directory if doesn't exist, since we're packaging apps
return jive.util.fsexists(extensionPublicDir).then( function(exists ) {
return !exists ? jive.util.fsmkdir( extensionPublicDir) : q.resolve();
}).then( function() {
// create the public/apps directory if doesn't exist
return jive.util.fsexists(svrPublicDir + '/apps').then( function(exists ) {
return !exists ? jive.util.fsmkdir( extensionPublicDir + '/apps') : q.resolve();
})
.then( function () {
// create the public/tiles directory if doesn't exist
return jive.util.fsexists(svrPublicDir + '/tiles').then( function(exists ) {
return !exists ? jive.util.fsmkdir( extensionPublicDir + '/tiles') : q.resolve();
});
})
.then( function () {
// recursively copy the server's public directory
return jive.util.fscopy(svrPublicDir, extensionPublicDir );
})
}).then( function() {
// create the public/services directory if doesn't exist
return jive.util.fsexists(svrPublicDir + '/services').then( function(exists ) {
return !exists ? jive.util.fsmkdir( extensionPublicDir + '/services') : q.resolve();
})
}).then( function() {
// copy over the server public directory TODO - should this be configurable? or done based on dependency analysis?
return jive.util.fsexists(svrPublicDir).then( function(exists ) {
return !exists ? jive.util.fsmkdir( extensionPublicDir) : q.resolve();
}).then( function () {
return jive.util.fscopy(svrPublicDir, extensionPublicDir );
})
});
} else {
// REMOVING FUNCTIONALITY AS THIS CAN DAMAGE AN UNPACKED ADD-ON - RR 08/25/2015
// // destroy the extension public directory if it exists since we're not packaging apps
// return jive.util.fsexists(extensionPublicDir).then( function(exists ) {
// return exists ? jive.util.fsrmdir( extensionPublicDir) : q.resolve();
// });
}
}).then( function() {
return getPersistedExtensionInfo(jive.service.options['extensionInfo'] || {});
}).then( function(extensionInfo) {
return jive.util.recursiveCopy( __dirname + "/template", extensionSrcDir)
.then( function() {
return getTileDefinitions(extensionPublicDir, tilesDir, packageApps);
}).then( function(definitions) {
return setupExtensionDefinitionJson(
tilesDir,
appsDir,
cartridgesDir,
storagesDir,
servicesDir,
extensionSrcDir,
extensionPublicDir,
extensionInfo,
definitions,
packageApps
).then( function(definitionsJson) {
// persist the extension metadata
return getCartridges(cartridgesDir, extensionSrcDir)
.then(function (cartridges) {
var meta = fillExtensionMetadata(extensionInfo, definitionsJson, packageApps, cartridges);
return copyExtensionIcons(meta, extensionSrcDir);
}).then( function(meta) {
var stringifiedMeta = JSON.stringify(meta, null, 4);
jive.logger.debug("Extension meta: \n" + stringifiedMeta);
return jive.util.fswrite( stringifiedMeta, extensionSrcDir + '/meta.json');
});
});
});
}).then( function() {
// zip it all
return jive.util.zipFolder( extensionSrcDir, extensionZipDir );
}).catch( function(e) {
var error = new Error(e);
var stack = error.stack;
jive.logger.error( stack );
throw error;
});
};
function copyIcon(meta, iconAttr, to ) {
var icon = meta[iconAttr];
var fileName = require('path').basename(icon);
var dest = to + '/' + fileName;
return jive.util.fsexists(icon).then( function( exists ) {
if ( !exists ) {
return q.resolve();
}
return jive.util.fsexists(dest)
.then( function(toExists){
if ( toExists ) {
// remove it if it already exists
return jive.util.fsdelete(dest);
} else {
return q.resolve();
}
})
.then( function () {
return jive.util.fscopy( icon, dest );
})
.then( function() {
// update meta to point to the *filename*, not its source path
meta[iconAttr] = fileName;
return q.resolve();
});
});
}
function copyExtensionIcons( meta, extensionSrcDir ) {
var target = extensionSrcDir + '/data';
var icons = [];
icons.push( copyIcon(meta, 'icon_16', target ) );
icons.push( copyIcon(meta, 'icon_48', target ) );
icons.push( copyIcon(meta, 'icon_128', target ) );
return q.all(icons).then( function(){
return q.resolve(meta);
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// private
function isValid(file ) {
return !(file.indexOf('.') == 0)
}
function limit(str, chars) {
return str.substring(0, str.length > chars ? chars : str.length );
}
function cartridgeIsNotConfigured(type) {
return type != 'jab-cartridges-app';
}
function fillExtensionMetadata(extensionInfo, definitions, packageApps, cartridges) {
var description = extensionInfo['description'];
var name = extensionInfo['name'];
var type = extensionInfo['type'] || 'client-app'; // by default
var id = extensionInfo['uuid'];
var hasCartridges = cartridges && cartridges.length > 0;
var hasOsapps = definitions['osapps'] && definitions['osapps'].length > 0;
var hasTiles = definitions['tiles'] && definitions['tiles'].length > 0;
var hasTemplates = definitions['templates'] && definitions['templates'].length > 0;
if (hasCartridges && cartridgeIsNotConfigured(type)) {
jive.logger.warn('***********************\n' +
'This add-on contains cartridges, ' +
'but it is not configured to package them. '+
'To enable this, add "type": "jab-cartridges-app" ' +
'to the extensionInfo field of jiveclientconfiguration.json\n' +
'**********************');
}
if (!name) {
// synthesize a reasonable name
name = "Add-on containing ";
var c = [];
if ( hasCartridges ) {
c.push('cartridge(s)');
}
if ( hasOsapps ) {
c.push('apps(s)');
}
if ( hasTiles ) {
c.push('tiles(s)');
}
name += c.join(', ').trim();
}
if (!description) {
description = '';
// synthesize a reasonable description
if ( hasCartridges ) {
var c = [];
var jabCartridges = definitions['jabCartridges'];
if ( jabCartridges ) {
jabCartridges.forEach( function(cartridge) {
c.push(cartridge['name']);
});
description += 'Cartridges: [';
description += c.join(', ').trim();
description += '] ';
}
}
if ( hasTiles ) {
var c = [];
definitions['tiles'].forEach( function(tile) {
c.push(tile['name']);
});
description += 'Tiles: [';
description += c.join(', ').trim();
description += '] ';
}
if ( hasOsapps ) {
var c = [];
definitions['osapps'].forEach( function(osapp) {
c.push(osapp['name']);
});
description += 'Apps: [';
description += c.join(', ').trim();
description += '] ';
}
description = description.trim();
description = limit(description, 255);
}
var defaultMinimumVersion = '0070300000';
if ( packageApps ) {
// minimum version is 8c4
defaultMinimumVersion = '0080300000';
}
var extensionMeta = _.defaults({
"package_version": extensionInfo['packageVersion'] || extensionInfo['package_version'] || '1.0',
"id": id,
"type": type,
"name": name,
"description": description,
"minimum_version": extensionInfo['minimum_version'] || extensionInfo['minJiveVersion'] || defaultMinimumVersion,
"icon_16": extensionInfo['icon_16'] || extensionInfo['icon16'] || "extension-16.png",
"icon_48": extensionInfo['icon_48'] || extensionInfo['icon48'] || "extension-48.png",
"icon_128": extensionInfo['icon_128'] || extensionInfo['icon128'] || "extension-128.png",
"register_url": extensionInfo['register_url'] || extensionInfo['registerURL'] || "%serviceURL%/jive/oauth/register",
"unregister_url": extensionInfo['unregister_url'] || extensionInfo['unregisterURL'] || "%serviceURL%/jive/oauth/unregister",
"redirect_url": extensionInfo['redirect_url'] || extensionInfo['redirectURL'] || "%serviceURL%",
"released_on": extensionInfo['released_on'] || extensionInfo['releasedOn'] || new Date().toISOString(),
"service_url": jive.service.serviceURL()
},
/*** NOTE: _.omit is used to transition away from older properties in favor of new ones ****/
_.omit(extensionInfo,"redirectURL","registerURL","unregisterURL","releasedOn")
);
if (extensionInfo['author']) {
extensionMeta["author"] = extensionInfo['author'];
extensionMeta["author_affiliation"] = extensionInfo['author_affiliation'];
extensionMeta["author_email"] = extensionInfo['author_email'];
} // end if
[
'minimum_edition','config_url','health_url','website_url','community_url','support_info','info_email',
'tags','overview','install_instructions','eula_filename','privacy_policy','screen_shots','solution_categories',
'target_integrations','key_features','jive_technology_partner_id'
].forEach(
function(extMeta) {
if (extensionInfo[extMeta]) {
extensionMeta[extMeta] = extensionInfo[extMeta];
} // end if
} // end function
); // end forEach
// these should never be there
delete extensionMeta['uuid'];
delete extensionMeta['jiveServiceSignature'];
/*** ADDING IN PACKAGED APPS LOGIC FOR config_url IN meta.json ***/
if (packageApps && jive.service.options["packageAddOnConfigure"] && extensionMeta['config_url']) {
var cfgPackageDir = '/public';
if (typeof jive.service.options["packageAddOnConfigure"] === 'string') {
cfgPackageDir += jive.service.options["packageAddOnConfigure"]
} //end if
extensionMeta['config_url'] = extensionMeta['config_url'].replace("%serviceURL%",cfgPackageDir).replace(jive.service.serviceURL(),cfgPackageDir);
} // end if
// suppress the register and unregister URLs if configured to do so
if ( (jive.service.options['suppressAddonRegistration'] === true ) ||
// assuming that if clientUrl is still localhost that we shouldn't initiate a register event
// In the event this causes issue, clientUrl can be set to 127.0.0.1 to bring back original behavior
(jive.service.options['clientUrl'] && jive.service.options['clientUrl'].indexOf('localhost') > -1)
) {
delete extensionMeta['register_url'];
delete extensionMeta['unregister_url'];
}
return extensionMeta;
}
function getTileDefinitions(extensionPublicDir, tilesRootDir, packageApps) {
var finalizeRequest = function (allDefinitions) {
var toReturn = [];
allDefinitions.forEach(function (batch) {
toReturn = toReturn.concat(batch);
});
return q.resolve(jive.service.getExpandedTileDefinitions(toReturn));
};
return q.all([ jive.tiles.definitions.findAll(), jive.extstreams.definitions.findAll() ]).then(finalizeRequest)
.then( function(definitions) {
if ( !packageApps) {
definitions.forEach( function(definition) {
delete definition['id'];
delete definition['definitionDirName'];
});
return definitions.filter(
function(definition) {
return (!definition["suppressTileDefinition"]);
} // end function
);
} else {
var proms = [];
var host = jive.service.serviceURL();
definitions.forEach( function(definition) {
var name = definition['name'];
var view = definition['view'];
var action = definition['action'];
var config = definition['config'];
delete definition['id'];
definition['view'] = !view ? view : view.replace(host, '/public/tiles');
definition['action'] = !action ? action : action.replace(host, '/public/tiles');
definition['config'] = !config ? config : config.replace(host, '/public/tiles');
//*** NEEDED TO PREVENT SDK FROM ADDING IN REGISTER URLS ***
if (definition['transform']) {
definition['config'] = definition['config'].substring(definition['config'].indexOf('/public/configuration'));
delete definition['unregister'];
delete definition['register'];
} // end if
/*** NEED TO REMOVE register/unregister IF IT IS A JIVE HOSTED APP ***/
if (!definition['registerTileWhenPackaged']) {
if (definition['config'] && definition['config'].indexOf('/public') == 0) {
delete definition['register'];
delete definition['unregister'];
} // end if
} else {
delete definition['registerTileWhenPackaged'];
} // end if
delete definition['definitionDirName'];
// post-process
var tileDir = tilesRootDir + '/' + name;
var copyTileDirToPublic = function(tile) {
return packageApps ? jive.util.fscopy(tileDir + '/public', extensionPublicDir + '/tiles/' + name).then( function() {
return sanitizeReferences(extensionPublicDir, extensionPublicDir + '/tiles/' + name, '/' + name + '/' )(tile);
}) : q.resolve(tile);
};
proms.push( copyTileDirToPublic(definition) );
});
return q.all(proms).then( function() {
return definitions.filter(
function(definition) {
return (!definition["suppressTileDefinition"]);
} // end function
);
});
}
});
}
function addCacheBuster(definitions) {
if (definitions) {
var ts = new Date().getTime();
for (x in definitions) {
["action","view","config","url"].forEach(
function(key) {
if (definitions[x][key]) {
if (key !== "url" || definitions[x][key].indexOf("/public") !== 0) {
definitions[x][key] += (definitions[x][key].indexOf("?") > -1) ? "&" : "?";
definitions[x][key] += "ts="+ts;
} // end if
} // end if
}
);
} // end for item
} // end if
return definitions;
} // end addCacheBuster
function setupExtensionDefinitionJson(tilesDir, appsDir, cartridgesDir, storagesDir, servicesDir, extensionSrcDir, extensionPublicDir,
extensionInfo, definitions, packageApps) {
return getTemplates(tilesDir).then(function (templates) {
return getApps(appsDir, extensionPublicDir, extensionInfo, packageApps).then(function (apps) {
return getServices(servicesDir, extensionPublicDir, extensionInfo, packageApps).then(function (services) {
return getStorages(storagesDir, extensionInfo).then(function (storages) {
return getCartridges(cartridgesDir, extensionSrcDir).then(function (cartridges) {
if(cartridgeIsNotConfigured(extensionInfo["type"])){
cartridges = [];
}
cartridges.forEach(function (cartridge) {
cartridge.zipUp().then(function () {
delete cartridge.zipUp;
});
});
jive.logger.debug("definitions:\n" + JSON.stringify(definitions, null, 4));
jive.logger.debug("templates:\n" + JSON.stringify(templates, null, 4));
jive.logger.debug("apps:\n" + JSON.stringify(apps, null, 4));
jive.logger.debug("storageDefinitions:\n" + JSON.stringify(storages, null, 4));
jive.logger.debug("cartridges:\n" + JSON.stringify(cartridges, null, 4));
var definitionsJson = {
'integrationUser': {
'systemAdmin': extensionInfo['jiveServiceSignature'] ? true : false,
'jiveServiceSignature': extensionInfo['jiveServiceSignature'],
'runAsStrategy': extensionInfo['runAsStrategy']
},
'tiles': (definitions && definitions.length > 0) ? addCacheBuster(definitions) : undefined,
'templates': (templates && templates.length > 0) ? templates : undefined,
'osapps': (apps && apps.length > 0) ? addCacheBuster(apps) : undefined,
'storageDefinitions':(storages && storages.length > 0) ? storages : undefined,
'jabCartridges': cartridges
};
// Remove cartridge element if empty
if (cartridges == null || cartridges.length == 0) {
delete definitionsJson.jabCartridges;
}
var definitionJsonPath = extensionSrcDir + '/definition.json';
var stringifiedDefinitionJson = JSON.stringify(definitionsJson, null, 4);
return jive.util.fswrite(stringifiedDefinitionJson, definitionJsonPath).then( function() {
return definitionsJson;
})
});
});
});
});
});
}
function getStorages(storagesDir, extensionInfo) {
var storages = [];
return jive.util.fsexists( storagesDir).then( function(exists) {
if ( exists ) {
return q.nfcall(fs.readdir, storagesDir).then(function(dirContents){
var proms = [];
dirContents.forEach(function(item) {
if ( isValid(item) ) {
var definitionDir = storagesDir + '/' + item + '/definition.json';
proms.push( jive.util.fsreadJson(definitionDir).then(function(storage){
if ( !storage['name'] ) {
// generate a storage name if one is not provided
storage['name'] = jive.util.guid(extensionInfo['uuid']);
}
return storage;
}) );
}
});
return q.all(proms);
});
} else {
return storages;
}
});
}
function isDirectory(path){
return fs.statSync(path).isDirectory();
}
var truncateTagSrc = function(html, toTruncate) {
var fn = function(all, tag, attrString) {
var matchAttr = /(\w+)\s*=\s*"(.*?)"/g;
var lookFor = (tag == "a" || tag == 'link') ? "href" : "src";
var newAttrs = attrString.replace(matchAttr, function(oneAttr, name, value, offset) {
if (name == lookFor && value.indexOf(toTruncate) == 0) {
oneAttr = oneAttr.replace('"' + toTruncate, '"');
}
return oneAttr;
});
return all.replace(attrString, newAttrs);
};
var re = /<(script|img|a|link)\s+(.*?)\/?>/gi;
return html.replace(re, fn);
};
function sanitizeReferences(extensionPublicDir, dirToProcess, tagValueToTruncate) {
var processOneFile = function(target) {
var deferred = q.defer();
var t = target.replace( 'public' + '/', '');
var depth = (t.split("/").length - 1);
var publicReplacement = '';
for ( var i = 0; i < depth; i++ ) {
publicReplacement += '../';
}
jive.util.fsread( extensionPublicDir + '/' + t).then( function(data) {
var raw = data.toString();
var processed = raw.replace(/\/__public__\//g, publicReplacement);
if ( tagValueToTruncate ) {
processed = truncateTagSrc(processed, tagValueToTruncate);
}
jive.util.fswrite( processed, extensionPublicDir + '/' + t).then( function() {
deferred.resolve();
});
});
return deferred.promise;
};
return function(app) {
return jive.util.recursiveDirectoryProcessor(dirToProcess, dirToProcess, '/tmp', true,function (type, currentFsItem) {
return q.fcall(function () {
var proms = [];
var lowercased = currentFsItem.toLowerCase();
var ext = lowercased.substring(currentFsItem.lastIndexOf('.') + 1, lowercased.length);
var validType = ext === 'xml' || ext === 'html' || ext === 'css' || ext === 'js';
if (type === 'file' && validType) {
var target = currentFsItem.substring(currentFsItem.indexOf('/') + 1, currentFsItem.length);
proms.push(processOneFile(target));
}
return q.all(proms);
})
}).then(function () {
return q.resolve(app);
});
};
}
function getApps(appsRootDir, extensionPublicDir, extensionInfo, packageApps) {
var apps = [];
return jive.util.fsexists( appsRootDir).then( function(exists) {
if ( exists ) {
return q.nfcall(fs.readdir, appsRootDir).then(function(dirContents){
var proms = [];
dirContents.forEach(function(item) {
var appDir = appsRootDir + '/' + item;
if ( isDirectory(appDir) ) {
var copyAppDirToPublic = function(app) {
return packageApps ? jive.util.fscopy(appDir + '/public', extensionPublicDir + '/apps/' + item).then( function() {
return sanitizeReferences(extensionPublicDir, extensionPublicDir + '/apps/' + item )(app);
}) : q.resolve(app);
};
var definitionDir = appDir + '/definition.json';
proms.push( jive.util.fsreadJson(definitionDir).then(function(app) {
if ( !app['name'] ) {
app['name'] = item;
}
if ( !app['id'] ) {
app['id'] = jive.util.guid(app['name'] + extensionInfo['uuid']);
}
if ( !app['appPath'] ) {
// generate an app path if one is not provided
var temp = app['id'];
temp = temp.replace(/[^a-zA-Z 0-9]+/g,'');
app['appPath'] = temp;
}
if ( packageApps ) {
app['url'] = '/public/apps/' + item + '/app.xml';
} else {
app['url'] = '%serviceURL%/osapp/' + item + '/app.xml';
}
return copyAppDirToPublic(app);
}) );
}
});
return q.all(proms);
});
} else {
return apps;
}
});
}
function getServices(servicesRootDir, extensionPublicDir, extensionInfo, packageServices) {
var services = [];
return jive.util.fsexists( servicesRootDir).then( function(exists) {
if ( exists ) {
return q.nfcall(fs.readdir, servicesRootDir).then(function(dirContents){
var proms = [];
dirContents.forEach(function(item) {
var serviceDir = servicesRootDir + '/' + item;
if ( fs.existsSync(serviceDir + '/public') && isDirectory(serviceDir) ) {
proms.push( function() {
return packageServices ? jive.util.fscopy(serviceDir + '/public', extensionPublicDir + '/services/' + item).then( function() {
return sanitizeReferences(extensionPublicDir, extensionPublicDir + '/services/' + item )(serviceDir);
}) : q.resolve();
}() );
}
});
return q.all(proms);
});
} else {
return services;
}
});
}
function getCartridges(cartridgesRootDir, extensionSrcDir) {
var cartridges = [];
return jive.util.fsexists( cartridgesRootDir).then( function(exists) {
if ( exists ) {
return q.nfcall(fs.readdir, cartridgesRootDir).then(function(dirContents){
var proms = [];
dirContents.forEach(function(item) {
var appDir = cartridgesRootDir + '/' + item;
if ( isDirectory(appDir) ) {
var definitionDir = appDir + '/definition.json';
var contentDir = cartridgesRootDir + '/' + item + '/content';
proms.push( jive.util.fsreadJson(definitionDir).then(function(cartridge) {
if ( !cartridge['name'] ) {
// generate an cartidge name if one is not provided
cartridge['name'] = jive.util.guid(item);
}
cartridge.zipUp = function(){
var zipFileName = cartridge['zipFileName'];
if ( !zipFileName ) {
zipFileName = cartridge['name'];
zipFileName = zipFileName.replace(/[^\S]+/, '');
zipFileName = zipFileName.replace(/[^a-zA-Z0-9]/, '-');
zipFileName += '.zip';
}
var zipFile = extensionSrcDir + '/data/' + zipFileName;
return jive.util.zipFolder( contentDir, zipFile, true).then( function() {
return q.resolve(cartridge);
});
};
return cartridge;
}) );
}
});
return q.all(proms);
});
} else {
return cartridges;
}
});
}
function getTemplates(tilesDir) {
var templatesPath = tilesDir + '/templates.json';
var toTemplateArray = function(allDefinitions, templates) {
if ( !allDefinitions || allDefinitions.length < 1) {
return null;
}
if ( !templates ) {
return null;
}
var templateArray = [];
for (var key in templates) {
if (templates.hasOwnProperty(key)) {
var template = templates[key];
var templateTiles = template['tiles'];
var filteredTiles = [];
if ( templateTiles ) {
templateTiles.forEach( function(tileName) {
if ( allDefinitions.indexOf(tileName) > -1 ) {
filteredTiles.push(tileName);
}
});
}
template['tiles'] = filteredTiles;
templateArray.push(template);
}
}
return templateArray;
};
return getAllDefinitions().then( function(allDefinitions) {
return jive.util.fsexists(tilesDir).then(function(exists) {
if ( !exists ) {
return q.resolve([]);
} else {
return jive.service.extensions().find().then(function (extension) {
return jive.util.fsexists(templatesPath.trim()).then(function (exists) {
if (!exists) {
// create it
return buildDefaultTemplate(allDefinitions, extension).then(
function(defaultTemplate) {
if (!defaultTemplate) {
return toTemplateArray(allDefinitions, null);
} else {
var templates = {};
templates['default'] = defaultTemplate;
return jive.util.fswrite(
JSON.stringify(templates, null, 4), tilesDir + '/templates.json'
).then(
function () {
return toTemplateArray(allDefinitions, templates);
}
);
} // end if
});
} else {
// make sure there is a default template
return jive.util.fsread(templatesPath).then( function(data) {
var templates = JSON.parse( new Buffer(data).toString() );
jive.logger.debug(templates);
if ( !templates['default'] ) {
return buildDefaultTemplate(allDefinitions, extension).then( function(defaultTemplate) {
templates['default'] = defaultTemplate;
return jive.util.fswrite(JSON.stringify(templates, null, 4), tilesDir + '/templates.json').then( function() {
return toTemplateArray(allDefinitions, templates);
})
});
} else {
return toTemplateArray(allDefinitions, templates);
}
});
}
});
});
}
})
});
}
function getAllDefinitions() {
return q.all([ jive.tiles.definitions.findAll(), jive.extstreams.definitions.findAll() ]).then(
function (allDefinitions) {
var tiles = [];
allDefinitions.forEach(function (batch) {
batch.forEach(function (b) {
tiles.push(b['name']);
});
});
return tiles;
});
}
function buildDefaultTemplate(allDefinitions, extension) {
if (!extension) {
return q.resolve(null);
} // end if
var extensionName = extension['name'];
var extensionDescription = extension['description'];
if ( !extensionName ) {
if ( allDefinitions ) {
var c = [];
extensionName = '';
extensionName += 'Contains: [';
extensionName += allDefinitions.join(', ').trim();
extensionName += '] ';
extensionName = limit(extensionName, 127);
} else {
extensionName = extension['uuid'];
}
}
if ( !extensionDescription ) {
extensionDescription = 'Extension UUID ' + extension['uuid'] + ' ' + extensionName;
}
var defaultTemplate = {
"name": "defaultTemplate",
"displayName": extensionName,
"description": extensionDescription,
"tiles": allDefinitions
};
return q.resolve( defaultTemplate );
}
function getPersistedExtensionInfo(config) {
return exports.find().then( function( record ) {
if ( record ) {
for (var key in config) {
if (config.hasOwnProperty(key)) {
// update
if ( !record[key] ) {
record[key] = config[key];
if ( key == 'uuid') {
record[key] = jive.util.guid();
}
} else if ( config[key] && config[key] !== record[key] ) {
record[key] = config[key];
}
}
}
return exports.save(record);
} else {
// create it
record = {
'id' : 'jiveExtension',
'uuid' : jive.util.guid()
};
for (var key in config) {
if (config.hasOwnProperty(key)) {
// update
if ( !record[key] ) {
record[key] = config[key];
if ( key == 'uuid') {
record[key] = jive.util.guid();
}
} else if ( config[key] && config[key] !== record[key] ) {
record[key] = config[key];
}
}
}
return exports.save(record);
}
});
}