UNPKG

cloudcms-cli

Version:
1,551 lines (1,231 loc) 145 kB
var prompt = require("prompt"); var program = require("commander"); var async = require("async"); var path = require("path"); var fs = require("fs"); var request = require("./util/request"); const url = require("url"); var opn = require("opn"); var mime = require("mime"); var Gitana = require("gitana"); var util = require("./util"); // start prompt prompt.message = null; prompt.delimiter = ""; prompt.start(); var exports = module.exports = function() { var r = {}; r.processOptions = function(schema, opts, command, callback) { if (!schema) { schema = {}; } if (!schema.properties) { schema.properties = []; } var options = {}; var fns = []; for (var i = 0; i < schema.properties.length; i++) { var val = undefined; if (schema.properties[i].args) { for (var j = 0; j < schema.properties[i].args.length; j++) { if (opts[schema.properties[i].args[j]]) { val = opts[schema.properties[i].args[j]]; break; } } } if (typeof(val) !== "undefined") { options[schema.properties[i].name] = val; } else { if (typeof(schema.properties[i].default) !== "undefined") { options[schema.properties[i].name] = schema.properties[i].default; // } else { // if (schema.properties[i].type === "boolean") { // options[schema.properties[i].name] = false; // } } if (schema.properties[i].required) { var fn = function (property) { return function (done) { if (property.prompt === "choice") { if (property.description) { console.log(property.description); } else if (property.helper) { console.log(property.helper); } program.choose(property.choiceTitles, function (i) { options[property.name] = property.choiceValues[i]; done(); }); } else { prompt.get([property], function (err, result) { if (err) { return done(err); } options[property.name] = result[property.name]; done(); }); } } }(schema.properties[i]); fns.push(fn); } } } async.series(fns, function(err) { callback(err, options); }); }; r.generateSchemaSummary = function(schema) { var summary = ""; if (schema && schema.properties) { for (var propertyName in schema.properties) { var property = schema.properties[propertyName]; if (property.args && property.args.length > 0) { summary += " "; if (!property.required) { summary += "["; } summary += "--" + property.args[0]; if (property.type === "boolean" && !property.required) { // skip } else { summary += " <" + property.name + ">"; } if (!property.required) { summary += "]"; } } } } return summary; }; var homeDirectory = r.homeDirectory = function() { return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME']; }; /** * Connects to Cloud CMS using a pre-established .cloudcms credentials file. * * @param credentials * @param callback */ var connect = r.connect = function(credentials, callback) { if (typeof(credentials) === "function") { callback = credentials; credentials = null; } if (!credentials) { credentials = readCredentials(); } if (!credentials) { return callback({ "message": "Unable to locate credentials.json file" }); } if (process.authenticator_code) { if (!Gitana.OAUTH2_TOKEN_REQUEST_HEADERS) { Gitana.OAUTH2_TOKEN_REQUEST_HEADERS = {}; } Gitana.OAUTH2_TOKEN_REQUEST_HEADERS["authenticator_code"] = process.authenticator_code; } Gitana.connect(credentials, function(err) { delete Gitana.OAUTH2_TOKEN_REQUEST_HEADERS["authenticator_code"]; callback.call(this, err); }); }; /** * Finds and hands back the credentials file. */ var readCredentials = r.readCredentials = function() { var text = null; if (process.cloudcms_profile) { if (fs.existsSync(path.join(homeDirectory(), ".cloudcms", "credentials", process.cloudcms_profile + ".json"))) { text = fs.readFileSync(path.join(homeDirectory(), ".cloudcms", "credentials", process.cloudcms_profile + ".json")); } } if (!text) { if (fs.existsSync(path.join(homeDirectory(), ".cloudcms", "credentials.json"))) { text = fs.readFileSync(path.join(homeDirectory(), ".cloudcms", "credentials.json")); } } var credentials = null; if (text) { credentials = JSON.parse(text); } if (credentials) { credentials.key = "credentials"; } return credentials; }; var appConnect = r.appConnect = function(callback) { var credentials = readCredentials(); if (!credentials) { return callback({ "message": "Unable to find credentials file" }); } var gitanaJson = { "clientKey": credentials.clientKey, "clientSecret": credentials.clientSecret, "username": credentials.username, "password": credentials.password, "baseURL": credentials.baseURL, "_apiURL": credentials._apiURL, "_uiURL": credentials._uiURL }; connect(gitanaJson, function (err) { if (err) { console.log("Unable to connect to Cloud CMS"); return callback(err); } callback.call(this, null, gitanaJson); }); }; var downloadArchive = r.downloadArchive = function(vaultId, group, artifact, version, callback) { appConnect(function(err, _gitanaJson) { if (err) { return callback(err); } var gitana = this; Chain(this).trap(function(e) { // failed to find vault? callback(e); return false; }).readVault(vaultId).then(function() { // NOTE: this = vault this.lookupArchive(group, artifact, version).then(function() { // NOTE: this = archive var packageFilePath = path.join(".", group + "-" + artifact + "-" + version + ".zip"); var downloadUri = _gitanaJson.baseURL + this.getUri() + "/download"; // headers var headers = {}; //headers["Content-Type"] = "application/zip"; // add "authorization" for OAuth2 bearer token var headers2 = gitana.getDriver().getHttpHeaders(); headers["Authorization"] = headers2["Authorization"]; var progressBar = createProgressBar(); request({ "method": "GET", "url": downloadUri, "qs": {}, "headers": headers, "responseType": "stream", "timeout": pickTimeout(120 * 1000) // 2 minutes }, function (err, httpResponse, fromStream) { if (err) { return callback(err); } if (httpResponse.status >= 200 && httpResponse.status <= 204) { // ok } else { console.log("Download failed"); return callback({ "message": "Status: " + httpResponse.status + ", Message: " + body }); } // set progress bar length var contentLength = httpResponse.headers["content-length"]; if (contentLength) { contentLength = parseInt("" + contentLength); progressBar.setTotal(contentLength); } // track progress var callbackTriggered = false; var progressCurrent = 0; fromStream.on("data", function(data) { if (data && data.length) { progressCurrent += data.length; progressBar.update(progressCurrent); } }); fromStream.on("end", function() { progressBar.stop(); if (!callbackTriggered) { callbackTriggered = true; callback(); } }); fromStream.on("error", function(err) { console.log("Caught error on stream", err); progressBar.stop(); if (!callbackTriggered) { callbackTriggered = true; callback(err); } }); // pipe streams from->to var toStream = fs.createWriteStream(packageFilePath); fromStream.pipe(toStream); }); }); }); }); }; var uploadArchive = r.uploadArchive = function(vaultId, group, artifact, version, callback) { appConnect(function(err, _gitanaJson) { if (err) { return callback(err); } var gitana = this; Chain(this).trap(function(e) { // failed to find vault? callback(e); return false; }).readVault(vaultId).then(function() { // NOTE: this = vault var vault = this; var doUpload = function(archiveGroup, archiveName, archiveVersion, type, completionCallback) { var packageFilePath = path.join(".", archiveGroup + "-" + archiveName + "-" + archiveVersion + ".zip"); var uploadUri = _gitanaJson.baseURL + vault.getUri() + "/archives?group=" + archiveGroup + "&artifact=" + archiveName + "&version=" + archiveVersion + "&type=branch"; // headers var headers = {}; headers["Content-Type"] = "application/zip"; // add "authorization" for OAuth2 bearer token var headers2 = gitana.getDriver().getHttpHeaders(); headers["Authorization"] = headers2["Authorization"]; var progressBar = createProgressBar(); var fromLength = fs.statSync(packageFilePath).size; progressBar.setTotal(fromLength); var fromStream = fs.createReadStream(packageFilePath); request({ "method": "POST", "url": uploadUri, "qs": {}, "headers": headers, "responseType": "stream", "timeout": pickTimeout(120 * 1000) // 2 minutes }, function (err, httpResponse, toStream) { if (err) { return completionCallback(err); } if (httpResponse.status >= 200 && httpResponse.status <= 204) { // ok //console.log("Upload complete: " + packageFilePath); //completionCallback(); } else { console.log("Upload failed for: " + packageFilePath); return completionCallback({ "message": "Status: " + httpResponse.status + ", Message: " + body }); } // track progress var callbackTriggered = false; var progressCurrent = 0; fromStream.on("data", function(data) { if (data && data.length) { progressCurrent += data.length; progressBar.update(progressCurrent); } }); fromStream.on("end", function() { progressBar.stop(); if (!callbackTriggered) { callbackTriggered = true; callback(); } }); fromStream.on("error", function(err) { console.log("Caught error on stream", err); progressBar.stop(); if (!callbackTriggered) { callbackTriggered = true; callback(err); } }); // pipe streams from->to fromStream.pipe(toStream); }); }; var fns = []; // upload parts if they exist var i = 0; var partsDone = false; do { var packageFilePath = path.join(".", "archives/" + group + "-" + artifact + "_part" + i + "-" + version + ".zip"); if (fs.existsSync(packageFilePath)) { var fn = function(partIndex) { return function(done) { doUpload(group, artifact + "_part" + partIndex, version, "branch", function(err) { done(err); }); }; }(i); fns.push(fn); } else { partsDone = true; } i++; } while (!partsDone); // upload the main archive itself var fn = function() { return function(done) { doUpload(group, artifact, version, "branch", function(err) { done(err); }); }; }(); fns.push(fn); // run all functions in serial async.series(fns, function(err) { callback(err); }); }); }); }; var importArchiveToBranch = r.importArchiveToBranch = function(repositoryId, branchId, group, artifact, version, callback) { appConnect(function(err, _gitanaJson) { if (err) { return callback(err); } this.readRepository(repositoryId).readBranch(branchId).then(function() { var branch = this; // import the branch archive into the repository this.importArchive({ "vault": "primary", "group": group, "artifact": artifact, "version": version, "configuration": { "childrenOnly": true } }, function(job) { console.log("Import progress: " + job.progressCurrent + " / " + job.progressMax); }).then(function() { if (this.getState() === "ERROR") { console.log("Job Failed"); console.log(JSON.stringify(this, null, " ")); callback({ "message": JSON.stringify(this) }); } else { Chain(branch).reload().then(function () { console.log("Successfully imported archive onto changeset: " + this.getTip()); callback(); }); } }); }); }); }; var exportBranchToArchive = r.exportBranchToArchive = function(repositoryId, branchId, group, artifact, version, callback) { appConnect(function(err, _gitanaJson) { if (err) { return callback(err); } this.readRepository(repositoryId).readBranch(branchId).then(function() { var branch = this; // export the archive this.exportArchive({ "vault": "primary", "group": group, "artifact": artifact, "version": version, "configuration": { "tipChangesetOnly": true } }).then(function() { if (this.getState() === "ERROR") { console.log("Job Failed"); console.log(JSON.stringify(this, null, " ")); callback({ "message": JSON.stringify(this) }); } else { Chain(branch).reload().then(function () { console.log("Successfully exported archive: " + this.getId()); callback(); }); } }); }); }); }; var registerModule = r.registerModule = function(id, sourceType, sourceUrl, sourcePath, sourceBranch, callback) { var source = { "type": sourceType, "uri": sourceUrl }; if (sourcePath) { source.path = sourcePath; } if (sourceBranch) { source.branch = sourceBranch; } var json = { "modules": [{ "id": id, "source": source }] }; _handleGitanaPost("/oneteam/modules/register", null, json, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var unregisterModule = r.unregisterModule = function(id, callback) { _handleGitanaPost("/oneteam/modules/unregister", { "id": id }, null, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var deployModule = r.deployModule = function(id, callback) { _handleGitanaPost("/oneteam/modules/deploy", { "id": id }, null, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var undeployModule = r.undeployModule = function(id, callback) { _handleGitanaPost("/oneteam/modules/undeploy", { "id": id }, null, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var redeployModule = r.redeployModule = function(id, callback) { _handleGitanaPost("/oneteam/modules/redeploy", { "id": id }, null, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var listModules = r.listModules = function(callback) { _handleGitanaGet("/oneteam/modules", {}, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var fixBranchTip = r.fixBranchTip = function(repositoryId, branchId, commit, forceToTip, buildView, callback) { _handleGitanaGet("/repositories/" + repositoryId + "/branches/" + branchId, {}, function(err, branch) { var branchTipId = branch.tip; console.log("TIP: " + branchTipId); // query the changesets to find the actual tip var p1 = {}; p1.sort = { "revision": -1 }; p1.limit = 1; _handleGitanaPost("/repositories/" + repositoryId + "/changesets/query", p1, { "branch": branchId }, function(err, results) { var topChangesetId = null; if (results && results.rows && results.rows.length > 0) { topChangesetId = results.rows[0]._doc; } if (forceToTip) { //topChangesetId = "5067:ce8fda435b9ebea67256"; topChangesetId = forceToTip; } var resp = { "branchTip": branchTipId, "topChangeset": topChangesetId }; if (!commit) { resp.commit = false; return _handleJsonResponse(err, resp, function() {}); } //console.log("Moving tip"); resp.commit = true; _handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/admin/reset", { "tip": topChangesetId }, {}, function(err, response) { if (buildView) { return buildBranchView(repositoryId, branchId, function(err) { resp.buildView = true; _handleJsonResponse(err, resp, callback); }); } resp.buildView = false; _handleJsonResponse(err, response, callback); }); }); }); }; var repairBranch = r.repairBranch = function(repositoryId, branchId, operations, commit, username, password, config, callback) { var params = {}; if (commit) { params.commit = true; } // payload (optional support for operations) var payload = {}; if (operations) { payload.operations = operations; } if (config) { payload.configuration = config; } // console.log("Payload: " + JSON.stringify(payload, null, 2)); _handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/repair/start", params, payload, function(err, jsonResponse) { var jobId = jsonResponse["_doc"]; waitForCompletionWithProgressBar(jobId, function(err, job) { console.log(""); job.attachment("default").download(function(data) { var result = JSON.parse(data); _handleJsonResponse(null, result, callback); }); }); }); }; var validateBranch = r.validateBranch = function(repositoryId, branchId, username, password, config, callback) { var params = {}; if (config.repair) { params.repair = true; } var body = {}; if (config.typeQNames) { body.typeQNames = config.typeQNames; } _handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/validate/start", params, body, function(err, jsonResponse) { var jobId = jsonResponse["_doc"]; waitForCompletionWithProgressBar(jobId, function(err, job) { console.log(""); if (err) { _handleJsonResponse(err, null, callback); return; } job.attachment("default").download(function(data) { var result = JSON.parse(data); if (result.errors) { result.errorLength = result.errors.length; var nodes = result.nodes = {}; for (var i = 0; i < result.errors.length; i++) { var error = result.errors[i]; var nodeId = error.node; var d = nodes[nodeId]; if (!d) { d = nodes[nodeId] = { "definitionPaths": [] }; } var definitionPropertyPath = error.definitionPropertyPath; if (definitionPropertyPath) { if (d.definitionPaths.indexOf(definitionPropertyPath) === -1) { d.definitionPaths.push(definitionPropertyPath); } } } result.nodesLength = 0; for (var k in result.nodes) { result.nodesLength++; } } if (config.nodeList) { var array = []; for (var nodeId in result.nodes) { array.push(nodeId); } _handleJsonResponse(null, array, callback); } else { _handleJsonResponse(null, result, callback); } }); }); }); }; var syncRepositoryAnchorSnapshots = r.syncRepositoryAnchorSnapshots = function(repositoryId, username, password, callback) { _handleGitanaPost("/repositories/" + repositoryId + "/admin/syncanchors", {}, null, function(err, jsonResponse) { if (err) { return _handleJsonResponse(err, jsonResponse, callback); } _waitForAdminJobCompletion(jsonResponse._doc, username, password, function(err, job) { if (err) { return _handleJsonResponse(err, job, callback); } if (job.state === "ERROR") { return _handleJsonResponse(err, job, callback); } callback(err, job); }); }); }; var rebuildDatastoreIndexes = r.rebuildDatastoreIndexes = function(datastoreTypeId, datastoreId, children, username, password, callback) { var qs = { "type": datastoreTypeId, "id": datastoreId, "recursive": (children ? "true": "false") }; _handleAdminGitanaPost("/maint/datastore/reindex", qs, null, username, password, function(err, jsonResponse) { if (err) { return _handleJsonResponse(err, jsonResponse, callback); } console.log(jsonResponse); _waitForAdminJobCompletion(jsonResponse._doc, username, password, function(err, job) { if (err) { return _handleJsonResponse(err, job, callback); } if (job.state === "ERROR") { return _handleJsonResponse(err, job, callback); } callback(err, job); }); }); }; var listPatches = r.listPatches = function(username, password, callback) { _handleAdminGitanaGet("/maint/patches/all", {}, username, password, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var applyPatches = r.applyPatches = function(datastoreTypeId, datastoreId, patchIds, force, username, password, callback) { _handleAdminGitanaPost("/maint/patches/apply", { "type": datastoreTypeId, "id": datastoreId }, { "patchIds": patchIds, "force": (force ? "true": "false") }, username, password, function(err, jsonResponse) { if (err) { return _handleJsonResponse(err, jsonResponse, callback); } var jobId = jsonResponse._doc; waitForAdminCompletionWithProgressBar(jobId, username, password, function(err, job) { if (err) { return _handleJsonResponse(err, job, callback); } if (job.state === "ERROR") { return _handleJsonResponse(err, job, callback); } callback(err, job); }); }); }; var listJobs = r.listJobs = function(state, callback) { var pagination = { "limit": 20, "options": { "countTotal": false } }; var json = {}; if (state) { json.state = state; } _handleGitanaPost("/jobs/query", pagination, json, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var getActiveJobsSummary = r.getJobsSummary = function(callback) { _handleGitanaPost("/jobs/summary", {}, {}, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var watchJob = r.watchJob = function(jobId, callback) { waitForCompletionWithProgressBar(jobId, function(err, job) { if (err) { return _handleJsonResponse(err, job, callback); } if (job.state === "ERROR") { return _handleJsonResponse(err, job, callback); } callback(err, job); }); }; var readJob = r.readJob = function(jobId, callback) { _handleGitanaGet("/jobs/" + jobId, {}, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var readNode = r.readNode = function(repositoryId, branchId, nodeId, nodePath, callback) { var params = {}; if (process.metadata) { params["metadata"] = "true"; } if (nodePath) { params["path"] = nodePath; } if (!nodeId) { nodeId = "root"; } _handleGitanaGet("/repositories/" + repositoryId + "/branches/" + branchId + "/nodes/" + nodeId, params, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var readBranch = r.readBranch = function(repositoryId, branchId, callback) { var params = {}; if (process.metadata) { params["metadata"] = "true"; } _handleGitanaGet("/repositories/" + repositoryId + "/branches/" + branchId, params, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var deleteBranch = r.deleteBranch = function(repositoryId, branchId, callback) { var params = {}; _handleGitanaDelete("/repositories/" + repositoryId + "/branches/" + branchId, params, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var deleteSnapshot = r.deleteSnapshot = function(repositoryId, branchId, callback) { var params = {}; _handleGitanaDelete("/repositories/" + repositoryId + "/branches/" + branchId, params, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var readChangeset = r.readChangeset = function(repositoryId, changesetId, callback) { var params = {}; if (process.metadata) { params["metadata"] = "true"; } _handleGitanaGet("/repositories/" + repositoryId + "/changesets/" + changesetId, params, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var createNode = r.createNode = function(repositoryId, branchId, objectString, callback) { var object = {}; if (objectString) { objectString = objectString.replace(/'/g, '"'); object = JSON.parse(objectString); } var params = {}; _handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/nodes", params, object, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var ingest = r.ingest = function(repositoryId, branchId, filePath, config, cb) { var callback = function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, cb); }; if (!config) { config = {}; } appConnect(function(err, _gitanaJson) { var gitana = this; var uploadUri = _gitanaJson.baseURL + "/repositories/" + repositoryId + "/branches/" + branchId + "/nodes/ingest"; // determine content type from file path? var contentType = lookupMimeType(filePath); // headers var headers = {}; headers["Content-Type"] = contentType; // add "authorization" for OAuth2 bearer token var headers2 = gitana.getDriver().getHttpHeaders(); headers["Authorization"] = headers2["Authorization"]; var fromStream = fs.createReadStream(filePath); var fromLength = fs.statSync(filePath).size; // build progress bar var progressBar = createProgressBar(); progressBar.setTotal(fromLength); // track progress var progressCurrent = 0; fromStream.on("data", function(data) { if (data && data.length) { progressCurrent += data.length; progressBar.update(progressCurrent); } }); fromStream.on("end", function() { progressBar.stop(); }); fromStream.on("error", function(err) { console.log("Caught error on stream", err); progressBar.stop(); }); request({ "method": "POST", "url": uploadUri, "qs": {}, "headers": headers, "data": fromStream, "responseType": "json", "timeout": pickTimeout(120 * 1000) // 2 minutes }, function (err, httpResponse, data) { progressBar.stop(); if (err) { return callback(err); } if (httpResponse.status >= 200 && httpResponse.status <= 204) { return callback(null, data); } else { console.log("Upload failed for: " + filePath); return callback({ "message": "Status: " + httpResponse.status + ", Message: " + body }); } }); }); }; var createSnapshot = r.createSnapshot = function(repositoryId, rootChangesetId, callback) { var params = { "changeset": rootChangesetId }; _handleGitanaPost("/repositories/" + repositoryId + "/snapshots/start", params, {}, function(err, jsonResponse) { if (err) { return _handleJsonResponse(err, jsonResponse, callback); } var jobId = jsonResponse["_doc"]; waitForCompletionWithProgressBar(jobId, function(err, job) { console.log(""); _handleJsonResponse(null, job, callback); }); }); }; var revertBranch = r.revertBranch = function(repositoryId, branchId, tipChangesetId, callback) { var params = { "id": tipChangesetId }; _handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/revert/start", params, null, function(err, jsonResponse) { var jobId = jsonResponse["_doc"]; waitForCompletionWithProgressBar(jobId, function(err, job) { console.log(""); _handleJsonResponse(null, job, callback); }); }); }; var resetBranch = r.resetBranch = function(repositoryId, branchId, tipChangesetId, callback) { var params = { "id": tipChangesetId }; _handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/reset/start", params, null, function(err, jsonResponse) { var jobId = jsonResponse["_doc"]; waitForCompletionWithProgressBar(jobId, function(err, job) { console.log(""); _handleJsonResponse(err, job, callback); }); }); }; var rebaseBranch = r.rebaseBranch = function(repositoryId, branchId, rootChangesetId, callback) { var params = { "id": rootChangesetId }; _handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/rebase/start", params, null, function(err, jsonResponse) { var jobId = jsonResponse["_doc"]; waitForCompletionWithProgressBar(jobId, function(err, job) { console.log(""); _handleJsonResponse(err, job, callback); }); }); }; var waitForCompletion = r.waitForCompletion = function(jobId, completeFn, progressFn) { appConnect(function(err) { if (err) { return completeFn(err); } var platform = this; // wait for the job to finish Chain(platform.getCluster()).waitForJobCompletion(jobId, function(job) { completeFn(null, job); }, function(job){ // progress progressFn(job); }); }); }; var waitForAdminCompletionWithProgressBar = r.waitForAdminCompletionWithProgressBar = function(jobId, username, password, completeFn, title) { var progressBar = createProgressBar(-1, -1, title); _waitForAdminJobCompletion(jobId, username, password, function(err, job) { progressBar.stop(); completeFn(err, job); }, function(job) { var progressCurrent = job.progressCurrent || 0; var progressMax = job.progressMax || 100; progressBar.setTotal(progressMax); progressBar.update(progressCurrent); }); }; var waitForCompletionWithProgressBar = r.waitForCompletionWithProgressBar = function(jobId, completeFn) { var progressBar = createProgressBar(); waitForCompletion(jobId, function(err, job) { progressBar.stop(); completeFn(err, job); }, function(job) { var progressCurrent = job.progressCurrent || 0; var progressMax = job.progressMax || 100; progressBar.setTotal(progressMax); progressBar.update(progressCurrent); }); }; var createProgressBar = r.createProgressBar = function(max, current, title) { var _cliProgress = require('cli-progress'); var format = "{bar} {percentage}% | Duration: {duration_formatted} | ETA: {eta_formatted} | {value}/{total}"; if (title) { format = title + " " + format; } // create a new progress bar instance and use shades_classic theme var bar1 = new _cliProgress.Bar({ format: format }, _cliProgress.Presets.shades_classic); if (!max) { max = 100; } if (!current) { current = 0; } bar1.start(max, 0); return bar1; }; var queryChangesets = r.queryChangesets = function(repositoryId, queryString, skipString, limitString, sortString, callback) { var query = {}; if (queryString) { queryString = queryString.replace(/'/g, '"'); query = JSON.parse(queryString); } var pagination = {}; if (skipString) { pagination.skip = parseInt(skipString); } if (limitString) { pagination.limit = parseInt(limitString); } if (sortString) { sortString = sortString.replace(/'/g, '"'); pagination.sort = JSON.parse(sortString); } appConnect(function(err) { if (err) { return callback(err); } this.readRepository(repositoryId).then(function() { this.queryChangesets(query, pagination).then(function() { var jsonResponse = toResultMap(this); _handleJsonResponse(err, jsonResponse, callback); }); }); }); }; var listChangesets = r.listChangesets = function(repositoryId, skipString, limitString, sortString, callback) { return queryChangesets(repositoryId, "{}", skipString, limitString, sortString, callback); }; var queryNodes = r.queryNodes = function(repositoryId, branchId, queryString, skipString, limitString, sortString, callback) { var query = {}; if (queryString) { queryString = queryString.replace(/'/g, '"'); query = JSON.parse(queryString); } var params = {}; if (skipString) { params.skip = parseInt(skipString); } if (limitString) { params.limit = parseInt(limitString); } if (sortString) { sortString = sortString.replace(/'/g, '"'); params.sort = JSON.parse(sortString); } _handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/nodes/query", params, query, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var searchNodes = r.searchNodes = function(repositoryId, branchId, queryString, text, skipString, limitString, sortString, callback) { var query = null; if (queryString) { queryString = queryString.replace(/'/g, '"'); query = JSON.parse(queryString); } if (text) { query = { search: { query_string: { query: text } } } } var params = {}; if (skipString) { params.skip = parseInt(skipString); } if (limitString) { params.limit = parseInt(limitString); } if (sortString) { sortString = sortString.replace(/'/g, '"'); params.sort = JSON.parse(sortString); } _handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/nodes/search", params, query, function(err, jsonResponse) { _handleJsonResponse(err, jsonResponse, callback); }); }; var startServer = r.startServer = function(appServerBasePath, callback) { // tries to connect using a local gitana.json and, if not found, uses credentials.json var connect = function(callback) { var exists = fs.existsSync("./gitana.json"); if (exists) { var _gitanaJson = JSON.parse("" + fs.readFileSync("./gitana.json")); return callback(null, _gitanaJson); } return appConnect(function(err, _gitanaJson) { callback(err, _gitanaJson); }); }; connect(function(err, _gitanaJson) { if (err) { return callback(err); } var myURL = url.parse(_gitanaJson.baseURL); // assume CONFIG1 // set environment variables to inform the app server of how our local stuff is configured process.env.CLOUDCMS_APPSERVER_BASE_PATH = appServerBasePath; process.env.GITANA_PROXY_HOST = myURL.hostname; if (myURL.protocol === "https:") { process.env.GITANA_PROXY_SCHEME = "https"; } else if (myURL.protocol === "http:") { process.env.GITANA_PROXY_SCHEME = "http"; } if (myURL.port) { process.env.GITANA_PROXY_PORT = myURL.port; } process.env.CLOUDCMS_STORE_CONFIGURATION = "default"; // allow WCM page cache to operate if we're in production mode process.env.FORCE_CLOUDCMS_WCM_PAGE_CACHE = true; var port = process.env.PORT || 2999; var cpuCount = require('os').cpus().length; console.log(""); console.log("Starting Cloud CMS Application Server (Command Line)..."); console.log(""); var appJsPath = path.join(__dirname, "..", "node_modules", "cloudcms-server", "server"); var spawn = function(command, errorHandler) { var active = true; var child = require('child_process').spawn("" + command, ["standalone.js"], { "cwd": appJsPath }); child.stdout.on('data', function (data) { if (active) { process.stdout.write("" + data); } }); child.stderr.on('data', function (data) { if (active) { console.log('ERROR: ' + "" + data); } }); child.on('error', function (err) { active = false; if (errorHandler) { errorHandler(err); } else { console.log('spawn error', err); } }); child.on('close', function (code) { }); }; if (!process.env.CLOUDCMS_NODE_EXEC) { process.env.CLOUDCMS_NODE_EXEC = "node"; } // yes they have node-dev, so we'll use that spawn(process.env.CLOUDCMS_NODE_EXEC, function(err) { console.log("Failed to launch with node executable: " + process.env.CLOUDCMS_NODE_EXEC); console.log(err); }); // NOTE: don't call back because we want to leave this running //callback(); }); }; var toResultMap = function(col) { var map = {}; map.rows = col.asArray(); map.total_rows = col.__totalRows(); map.offset = col.__offset(); map.size = col.__size(); return map; }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var print = r.print = function(text, newline) { if (n