Building TypeScript scaffolding for cli

This commit is contained in:
Kasra Bigdeli
2019-01-02 23:33:07 -08:00
parent 574d490c9e
commit caf6e6b574
45 changed files with 2146 additions and 40 deletions
+164
View File
@@ -0,0 +1,164 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var MainApi = require("./MainApi");
var MachineHelper = require("../helpers/MachineHelper");
var _a = require("../utils/constants"), DEFAULT_BRANCH_TO_PUSH = _a.DEFAULT_BRANCH_TO_PUSH, DEFAULT_APP_NAME = _a.DEFAULT_APP_NAME;
var DeployApi = /** @class */ (function () {
function DeployApi() {
this.machineToDeploy = {};
this.branchToPush = DEFAULT_BRANCH_TO_PUSH;
this.appName = DEFAULT_APP_NAME;
this.appUrl = "";
}
DeployApi.prototype.setMachineToDeploy = function (machineToDeploy) {
this.machineToDeploy = machineToDeploy;
};
DeployApi.prototype.updateMachineToDeploy = function (machineToDeploy) {
var possibleMachine = {};
// Look machine by host
if (machineToDeploy.startsWith("http")) {
possibleMachine = MachineHelper.machines.find(function (machine) { return machine.baseUrl === machineToDeploy; });
}
else {
// Look machine by name
possibleMachine = MachineHelper.machines.find(function (machine) { return machine.name === machineToDeploy; });
}
this.machineToDeploy = possibleMachine;
};
DeployApi.prototype.setBranchToPush = function (branchToPush) {
this.branchToPush = branchToPush;
};
DeployApi.prototype.setAppName = function (appName) {
this.appName = appName;
this.setAppUrl();
};
DeployApi.prototype.setAppUrl = function () {
this.appUrl = this.machineToDeploy.baseUrl
.replace("//captain.", "//" + this.appName + ".")
.replace("https://", "http://");
};
DeployApi.prototype.fetchBuildLogs = function () {
return __awaiter(this, void 0, void 0, function () {
var _a, authToken, baseUrl, customOptions, data, e_1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 2, , 3]);
_a = this.machineToDeploy, authToken = _a.authToken, baseUrl = _a.baseUrl;
customOptions = {
headers: {
"x-captain-auth": authToken
}
};
return [4 /*yield*/, MainApi.get(baseUrl + "/api/v1/user/appData/" + this.appName, customOptions)];
case 1:
data = _b.sent();
return [2 /*return*/, data];
case 2:
e_1 = _b.sent();
throw e_1;
case 3: return [2 /*return*/];
}
});
});
};
DeployApi.prototype.sendFile = function (sourceFile, gitHash) {
return __awaiter(this, void 0, void 0, function () {
var _a, authToken, baseUrl, url, form, options, data, e_2;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 2, , 3]);
_a = this.machineToDeploy, authToken = _a.authToken, baseUrl = _a.baseUrl;
url = baseUrl + "/api/v1/user/appData/" + this.appName + "/?detached=1";
form = {
sourceFile: sourceFile,
gitHash: gitHash
};
options = {
headers: {
"x-captain-auth": authToken
}
};
return [4 /*yield*/, MainApi.postWithFile(url, form, options)];
case 1:
data = _b.sent();
return [2 /*return*/, data];
case 2:
e_2 = _b.sent();
throw e_2;
case 3: return [2 /*return*/];
}
});
});
};
// This is not moved to LoginAPI since it's related only for machineToDeploy
DeployApi.prototype.isAuthTokenValid = function () {
return __awaiter(this, void 0, void 0, function () {
var url, currentToken, options, response, data, e_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
if (!this.machineToDeploy)
return [2 /*return*/, false];
url = this.machineToDeploy.baseUrl + "/api/v1/user/appDefinitions/";
currentToken = this.machineToDeploy.authToken;
options = {
headers: {
"x-captain-auth": currentToken
}
};
return [4 /*yield*/, MainApi.get(url, options)];
case 1:
response = _a.sent();
data = JSON.parse(response);
// Tolken is not valid
if (data.status === 1106 || data.status === 1105) {
return [2 /*return*/, false];
}
return [2 /*return*/, true];
case 2:
e_3 = _a.sent();
throw e_3;
case 3: return [2 /*return*/];
}
});
});
};
return DeployApi;
}());
module.exports = new DeployApi();
+105
View File
@@ -0,0 +1,105 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var MainApi = require("./MainApi");
var SystemApi = require("./SystemApi");
var DEFAULT_PASSWORD = require("../utils/constants").DEFAULT_PASSWORD;
var LoginApi = /** @class */ (function () {
function LoginApi() {
this.token = "";
this.oldPassword = DEFAULT_PASSWORD;
}
LoginApi.prototype.setOldPassword = function (newPassword) {
this.oldPassword = newPassword;
};
LoginApi.prototype.setToken = function (newToken) {
this.token = newToken;
};
LoginApi.prototype.loginMachine = function (baseUrl, password) {
return __awaiter(this, void 0, void 0, function () {
var data, dataAsObject, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, MainApi.post(baseUrl + "/api/v1/login", { password: password })];
case 1:
data = _a.sent();
dataAsObject = JSON.parse(data);
if (dataAsObject) {
this.setToken(dataAsObject.token);
}
return [2 /*return*/, data];
case 2:
e_1 = _a.sent();
throw e_1;
case 3: return [2 /*return*/];
}
});
});
};
LoginApi.prototype.changePass = function (baseUrl, newPassword) {
return __awaiter(this, void 0, void 0, function () {
var customOptions, form, data, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
customOptions = {
headers: {
"x-captain-auth": LoginApi.token
}
};
form = {
oldPassword: this.oldPassword,
newPassword: newPassword
};
return [4 /*yield*/, MainApi.post(baseUrl + "/api/v1/user/changepassword/", form, customOptions)];
case 1:
data = _a.sent();
this.setToken(data.token);
SystemApi.setIpAddressOfServer(baseUrl);
return [2 /*return*/, data];
case 2:
e_2 = _a.sent();
throw e_2;
case 3: return [2 /*return*/];
}
});
});
};
return LoginApi;
}());
module.exports = new LoginApi();
+61
View File
@@ -0,0 +1,61 @@
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var Request = require("request-promise");
var MainApi = /** @class */ (function () {
function MainApi() {
this.sharedOptions = {
headers: {
"x-namespace": "captain"
}
};
}
MainApi.prototype._buildOptions = function (options) {
if (!options)
return this.sharedOptions;
if (options.headers) {
options.headers = Object.assign({}, this.sharedOptions.headers, options.headers);
}
return Object.assign({}, this.sharedOptions, options);
};
MainApi.prototype.get = function (url, options) {
var overrideOptions = this._buildOptions(options);
var optionsToSend = __assign({}, overrideOptions, { url: url, method: "GET" });
return Request(optionsToSend);
};
MainApi.prototype.post = function (url, form, options) {
var overrideOptions = this._buildOptions(options);
var optionsToSend = __assign({}, overrideOptions, { url: url, method: "POST", form: form });
return Request(optionsToSend);
};
MainApi.prototype.postWithFile = function (url, formData, options) {
var overrideOptions = this._buildOptions(options);
var optionsToSend = __assign({}, overrideOptions, { url: url, method: "POST", formData: formData });
return Request(optionsToSend);
};
MainApi.prototype.put = function (url, form, options) {
var overrideOptions = this._buildOptions(options);
var optionsToSend = __assign({}, overrideOptions, { url: url, method: "PUT", form: form });
return Request(optionsToSend);
};
MainApi.prototype.patch = function (url, form, options) {
var overrideOptions = this._buildOptions(options);
var optionsToSend = __assign({}, overrideOptions, { url: url, method: "PATCH", form: form });
return Request(optionsToSend);
};
MainApi.prototype.delete = function (url, options) {
var overrideOptions = this._buildOptions(options);
var optionsToSend = __assign({}, overrideOptions, { url: url, method: "DELETE" });
return Request(optionsToSend);
};
return MainApi;
}());
module.exports = new MainApi();
+134
View File
@@ -0,0 +1,134 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var MainApi = require("./MainApi");
var LoginApi = require("./LoginApi");
// const spinnerUtil = require("../../utils/spinner")
var SystemApi = /** @class */ (function () {
function SystemApi() {
this.ipAddressOfServer = "";
this.customDomainFromUser = "";
this.newPasswordFirstTry = "";
}
SystemApi.prototype.setCustomDomainFromUser = function (newCustomDomainFromUser) {
this.customDomainFromUser = newCustomDomainFromUser;
};
SystemApi.prototype.setIpAddressOfServer = function (newIpAddress) {
this.ipAddressOfServer = newIpAddress.trim();
};
SystemApi.prototype.setCustomDomain = function (baseUrl, rootDomain) {
return __awaiter(this, void 0, void 0, function () {
var customOptions, data, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
customOptions = {
headers: {
"x-captain-auth": LoginApi.token
}
};
return [4 /*yield*/, MainApi.post(baseUrl + "/api/v1/user/system/changerootdomain/", {
rootDomain: rootDomain
}, customOptions)];
case 1:
data = _a.sent();
return [2 /*return*/, data];
case 2:
e_1 = _a.sent();
throw e_1;
case 3: return [2 /*return*/];
}
});
});
};
SystemApi.prototype.enableHttps = function (baseUrl, emailAddress) {
return __awaiter(this, void 0, void 0, function () {
var customOptions, data, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
customOptions = {
headers: {
"x-captain-auth": LoginApi.token
}
};
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, MainApi.post(baseUrl + "/api/v1/user/system/enablessl/", {
emailAddress: emailAddress
}, customOptions)];
case 2:
data = _a.sent();
return [2 /*return*/, data];
case 3:
e_2 = _a.sent();
throw e_2;
case 4: return [2 /*return*/];
}
});
});
};
SystemApi.prototype.forceHttps = function (baseUrl, isEnabled) {
if (isEnabled === void 0) { isEnabled = true; }
return __awaiter(this, void 0, void 0, function () {
var customOptions, data, e_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
customOptions = {
headers: {
"x-captain-auth": LoginApi.token
}
};
return [4 /*yield*/, MainApi.post(baseUrl + "/api/v1/user/system/forcessl/", {
isEnabled: isEnabled
}, customOptions)];
case 1:
data = _a.sent();
return [2 /*return*/, data];
case 2:
e_3 = _a.sent();
throw e_3;
case 3: return [2 /*return*/];
}
});
});
};
return SystemApi;
}());
module.exports = new SystemApi();
+59
View File
@@ -0,0 +1,59 @@
#!/usr/bin/env node
var printError = require("../utils/messageHandler").printError;
var packagejson = require("../../package.json");
var updateNotifier = require("update-notifier");
var program = require("commander");
updateNotifier({ pkg: packagejson }).notify({ isGlobal: true });
// Command actions
var serversetup = require("./serversetup");
var login = require("./login").login;
var logout = require("./logout");
var list = require("./list");
var deploy = require("./deploy");
// Setup
program.version(packagejson.version).description(packagejson.description);
// Commands
program
.command("serversetup")
.description("Performs necessary actions and prepares your Captain server.")
.action(function () {
serversetup();
});
program
.command("login")
.description("Login to a CaptainDuckDuck machine. You can be logged in to multiple machines simultaneously.")
.action(function () {
login();
});
program
.command("logout")
.description("Logout from a specific Captain machine.")
.action(function () {
logout();
});
program
.command("list")
.alias("ls")
.description("List all Captain machines currently logged in.")
.action(function () {
list();
});
program
.command("deploy")
.description("Deploy your app (current directory) to a specific Captain machine. You'll be prompted to choose your Captain machine.")
.option("-t, --tarFile <value>", "Specify file to be uploaded (rather than using git archive)")
.option("-d, --default", "Run with default options")
.option("-s, --stateless", "Run deploy stateless")
.option("-h, --host <value>", "Only for stateless mode: Host of the captain machine")
.option("-a, --appName <value>", "Only for stateless mode: Name of the app")
.option("-p, --pass <value>", "Only for stateless mode: Password for Captain")
.option("-b, --branch <value>", "Only for stateless mode: Branch name (default master)")
.action(function (options) {
deploy(options);
});
// Error on unknown commands
program.on("command:*", function () {
var wrongCommands = program.args.join(" ");
printError("\nInvalid command: " + wrongCommands + "\nSee --help for a list of available commands.", true);
});
program.parse(process.argv);
+254
View File
@@ -0,0 +1,254 @@
#!/usr/bin/env node
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var MachineHelper = require("../helpers/MachineHelper");
var DeployApi = require("../api/DeployApi");
var LoginApi = require("../api/LoginApi");
var _a = require("../utils/messageHandler"), printError = _a.printError, printMessage = _a.printMessage;
var _b = require("../utils/validationsHandler"), validateIsGitRepository = _b.validateIsGitRepository, validateDefinitionFile = _b.validateDefinitionFile, optionIsNotGiven = _b.optionIsNotGiven, validateAuthentication = _b.validateAuthentication;
var uploadFile = require("../utils/fileHelper").uploadFile;
var gitArchiveFile = require("../utils/fileHelper").gitArchiveFile;
var fs = require("fs-extra");
var path = require("path");
var inquirer = require("inquirer");
var commandExistsSync = require("command-exists").sync;
var initMachineFromLocalStorage = require("../utils/machineUtils").initMachineFromLocalStorage;
function deployAsDefaultValues() {
return __awaiter(this, void 0, void 0, function () {
var isValidAuthentication, appName, branchToPush, machineToDeploy, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, validateAuthentication()];
case 1:
isValidAuthentication = _a.sent();
if (isValidAuthentication) {
appName = DeployApi.appName, branchToPush = DeployApi.branchToPush, machineToDeploy = DeployApi.machineToDeploy;
if (!appName || !branchToPush || !machineToDeploy) {
printError("Default deploy failed. There are no default options selected.", true);
}
printMessage("Deploying to " + machineToDeploy.name);
deployFromGitProject();
}
else {
printError("Incorrect login details", true);
}
return [3 /*break*/, 3];
case 2:
e_1 = _a.sent();
printError(e_1.message, true);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
});
}
function deployAsStateless(host, appName, branch, pass) {
return __awaiter(this, void 0, void 0, function () {
var isStateless, name_1, response, data, newToken;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
isStateless = host && appName && branch && pass;
if (!isStateless) return [3 /*break*/, 2];
// login first
printMessage("Trying to login to " + host + "\n");
name_1 = DeployApi.machineToDeploy.name;
return [4 /*yield*/, LoginApi.loginMachine(host, pass)];
case 1:
response = _a.sent();
data = JSON.parse(response);
newToken = data.token;
// Update the token to the machine that corresponds (if needed)
MachineHelper.updateMachineAuthToken(name_1, newToken);
if (data) {
printMessage("Starting stateless deploy to\n" + host + "\n" + branch + "\n" + appName);
deployFromGitProject();
}
return [3 /*break*/, 3];
case 2:
printError("You are missing parameters for deploying on stateless. <host> <password> <app name> <branch>");
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
}
function deployFromTarFile(tarFile) {
return __awaiter(this, void 0, void 0, function () {
var isValidAuthentication, filePath, gitHash, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 5, , 6]);
return [4 /*yield*/, validateAuthentication()];
case 1:
isValidAuthentication = _a.sent();
if (!isValidAuthentication) return [3 /*break*/, 3];
filePath = tarFile;
gitHash = "sendviatarfile";
return [4 /*yield*/, uploadFile(filePath, gitHash)];
case 2:
_a.sent();
return [3 /*break*/, 4];
case 3:
printError("Incorrect login details", true);
_a.label = 4;
case 4: return [3 /*break*/, 6];
case 5:
e_2 = _a.sent();
printError(e_2.message, true);
return [3 /*break*/, 6];
case 6: return [2 /*return*/];
}
});
});
}
function deployFromGitProject() {
if (!commandExistsSync("git")) {
printError("'git' command not found...");
printError("Captain needs 'git' to create tar file of your source files...", true);
}
var zipFileNameToDeploy = "temporary-captain-to-deploy.tar";
var zipFileFullPath = path.join(process.cwd(), zipFileNameToDeploy);
printMessage("Saving tar file to:\n" + zipFileFullPath + "\n");
// Removes the temporarly file created
try {
var tempFileExists = fs.pathExistsSync(zipFileFullPath);
if (tempFileExists) {
fs.removeSync(zipFileFullPath);
}
}
catch (e) {
// IgnoreError
}
gitArchiveFile(zipFileFullPath, DeployApi.branchToPush);
}
function deploy(options) {
return __awaiter(this, void 0, void 0, function () {
var questions, answers, captainNameToDeploy, branchToPush, appName, isValidAuthentication, e_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
// Reads local storage and sets the machine if found
initMachineFromLocalStorage();
if (!options.tarFile || !options.stateless) {
validateIsGitRepository();
validateDefinitionFile();
}
printMessage("Preparing deployment to Captain...\n");
if (!options.default) return [3 /*break*/, 1];
deployAsDefaultValues();
return [3 /*break*/, 8];
case 1:
if (!options.stateless) return [3 /*break*/, 2];
deployAsStateless(options.host, options.appName, options.branch, options.pass);
return [3 /*break*/, 8];
case 2:
if (!options.tarFile) return [3 /*break*/, 3];
deployFromTarFile(options.tarFile);
return [3 /*break*/, 8];
case 3:
questions = [
{
type: "list",
name: "captainNameToDeploy",
default: DeployApi.machineToDeploy.name || "",
message: "Select the Captain Machine you want to deploy to:",
choices: MachineHelper.getMachinesAsOptions(),
when: function () { return optionIsNotGiven(options, "host"); }
},
{
type: "input",
default: DeployApi.branchToPush || "master",
name: "branchToPush",
message: "Enter the 'git' branch you would like to deploy:",
when: function () { return optionIsNotGiven(options, "branch"); }
},
{
type: "input",
default: DeployApi.appName,
name: "appName",
message: "Enter the Captain app name this directory will be deployed to:",
when: function () { return optionIsNotGiven(options, "appName"); }
},
{
type: "confirm",
name: "confirmedToDeploy",
message: "Note that uncommitted files and files in gitignore (if any) will not be pushed to server. Please confirm so that deployment process can start.",
default: true,
when: function () { return optionIsNotGiven(options, "stateless"); }
}
];
return [4 /*yield*/, inquirer.prompt(questions)];
case 4:
answers = _a.sent();
if (!answers.confirmedToDeploy && !options.stateless) {
printMessage("\nOperation cancelled by the user...\n");
process.exit(0);
}
captainNameToDeploy = answers.captainNameToDeploy;
branchToPush = answers.branchToPush || options.branch;
appName = answers.appName || options.appName;
DeployApi.updateMachineToDeploy(captainNameToDeploy || options.host);
DeployApi.setBranchToPush(branchToPush);
DeployApi.setAppName(appName);
printMessage("Deploying to " + DeployApi.machineToDeploy.name);
if (!answers.confirmedToDeploy) return [3 /*break*/, 8];
_a.label = 5;
case 5:
_a.trys.push([5, 7, , 8]);
return [4 /*yield*/, validateAuthentication()];
case 6:
isValidAuthentication = _a.sent();
if (isValidAuthentication) {
deployFromGitProject();
}
else {
printError("Incorrect login details", true);
}
return [3 /*break*/, 8];
case 7:
e_3 = _a.sent();
printError(e_3.message, true);
return [3 /*break*/, 8];
case 8: return [2 /*return*/];
}
});
});
}
module.exports = deploy;
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env node
var chalk = require("chalk");
var MachineHelper = require("../helpers/MachineHelper");
var printMessage = require("../utils/messageHandler").printMessage;
function _displayMachine(machine) {
console.log(">> " +
chalk.greenBright(machine.name) +
" at " +
chalk.cyan(machine.baseUrl));
}
function list() {
printMessage("\nLogged in Captain Machines:\n");
MachineHelper.machines.map(function (machine) {
_displayMachine(machine);
});
printMessage("");
}
module.exports = list;
+187
View File
@@ -0,0 +1,187 @@
#!/usr/bin/env node
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var MachineHelper = require("../helpers/MachineHelper");
var _a = require("../utils/messageHandler"), printMessage = _a.printMessage, printGreenMessage = _a.printGreenMessage, printError = _a.printError;
var inquirer = require("inquirer");
var DeployApi = require("../api/DeployApi");
var _b = require("../utils/loginHelpers"), cleanUpUrl = _b.cleanUpUrl, findDefaultCaptainName = _b.findDefaultCaptainName;
var SAMPLE_DOMAIN = require("../utils/constants").SAMPLE_DOMAIN;
var LoginApi = require("../api/LoginApi");
// In case the token is expired
function requestLogin() {
return __awaiter(this, void 0, void 0, function () {
var _a, baseUrl, name, questions, loginPassword, password, response, data, newToken;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = DeployApi.machineToDeploy, baseUrl = _a.baseUrl, name = _a.name;
printMessage("Your auth token is not valid anymore. Try to login again.");
questions = [
{
type: "password",
name: "captainPassword",
message: "Please enter your password for " + baseUrl,
validate: function (value) {
if (value && value.trim()) {
return true;
}
return "Please enter your password for " + baseUrl;
}
}
];
return [4 /*yield*/, inquirer.prompt(questions)];
case 1:
loginPassword = _b.sent();
password = loginPassword.captainPassword;
return [4 /*yield*/, LoginApi.loginMachine(baseUrl, password)];
case 2:
response = _b.sent();
data = JSON.parse(response);
newToken = data.token;
if (!newToken)
return [2 /*return*/, false
// Update the token to the machine that corresponds
];
// Update the token to the machine that corresponds
MachineHelper.updateMachineAuthToken(name, newToken);
return [2 /*return*/, true];
}
});
});
}
function login() {
return __awaiter(this, void 0, void 0, function () {
var questions, answers, captainHasRootSsl, captainPassword, captainAddress, captainName, handleHttp, baseUrl, data, response, newMachine, error_1, errorMessage;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
printMessage("Login to a Captain Machine");
questions = [
{
type: "input",
default: SAMPLE_DOMAIN,
name: "captainAddress",
message: "\nEnter address of the Captain machine. \nIt is captain.[your-captain-root-domain] :",
validate: function (value) {
if (value === SAMPLE_DOMAIN) {
return "Enter a valid URL";
}
if (!cleanUpUrl(value))
return "This is an invalid URL: " + value;
MachineHelper.machines.map(function (machine) {
if (cleanUpUrl(machine.baseUrl) === cleanUpUrl(value)) {
return value + " already exist as " + machine.name + ". If you want to replace the existing entry, you have to first use <logout> command, and then re-login.";
}
});
if (value && value.trim()) {
return true;
}
return "Please enter a valid address.";
}
},
{
type: "confirm",
name: "captainHasRootSsl",
message: "Is HTTPS activated for this Captain machine?",
default: true
},
{
type: "password",
name: "captainPassword",
message: "Enter your password:",
validate: function (value) {
if (value && value.trim()) {
return true;
}
return "Please enter your password.";
}
},
{
type: "input",
name: "captainName",
message: "Enter a name for this Captain machine:",
default: findDefaultCaptainName(),
validate: function (value) {
MachineHelper.machines.map(function (machine) {
if (machine.name === value) {
return value + " already exist. If you want to replace the existing entry, you have to first use <logout> command, and then re-login.";
}
});
if (value.match(/^[-\d\w]+$/i)) {
return true;
}
return "Please enter a Captain Name.";
}
}
];
return [4 /*yield*/, inquirer.prompt(questions)];
case 1:
answers = _a.sent();
captainHasRootSsl = answers.captainHasRootSsl, captainPassword = answers.captainPassword, captainAddress = answers.captainAddress, captainName = answers.captainName;
handleHttp = captainHasRootSsl ? "https://" : "http://";
baseUrl = "" + handleHttp + cleanUpUrl(captainAddress);
_a.label = 2;
case 2:
_a.trys.push([2, 4, , 5]);
return [4 /*yield*/, LoginApi.loginMachine(baseUrl, captainPassword)];
case 3:
data = _a.sent();
response = JSON.parse(data);
// TODO - This status should be 200 maybe?
if (response.status !== 100) {
throw new Error(JSON.stringify(response, null, 2));
}
newMachine = {
authToken: response.token,
baseUrl: baseUrl,
name: captainName
};
MachineHelper.addMachine(newMachine);
printGreenMessage("Logged in successfully to " + baseUrl);
printGreenMessage("Authorization token is now saved as " + captainName + " \n");
return [3 /*break*/, 5];
case 4:
error_1 = _a.sent();
errorMessage = error_1.message ? error_1.message : error_1;
printError("Something bad happened. Cannot save \"" + captainName + "\" \n" + errorMessage);
return [3 /*break*/, 5];
case 5: return [2 /*return*/];
}
});
});
}
module.exports = { login: login, requestLogin: requestLogin };
+79
View File
@@ -0,0 +1,79 @@
#!/usr/bin/env node
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var MachineHelper = require("../helpers/MachineHelper");
var printMessage = require("../utils/messageHandler").printMessage;
var inquirer = require("inquirer");
function generateQuestions() {
var listOfMachines = MachineHelper.getMachinesAsOptions();
return [
{
type: "list",
name: "captainNameToLogout",
message: "Select the Captain Machine you want to logout from:",
choices: listOfMachines
},
{
type: "confirm",
name: "confirmedToLogout",
message: "Are you sure you want to logout from this Captain machine?",
default: false,
when: function (answers) { return answers.captainNameToLogout; }
}
];
}
function logout() {
return __awaiter(this, void 0, void 0, function () {
var questions, answers, captainNameToLogout;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
questions = generateQuestions();
printMessage("Logout from a Captain Machine and clear auth info");
return [4 /*yield*/, inquirer.prompt(questions)];
case 1:
answers = _a.sent();
captainNameToLogout = answers.captainNameToLogout;
if (!captainNameToLogout) {
printMessage("\nOperation cancelled by the user...\n", true);
}
MachineHelper.logoutMachine(captainNameToLogout);
return [2 /*return*/];
}
});
});
}
module.exports = logout;
+279
View File
@@ -0,0 +1,279 @@
#!/usr/bin/env node
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var _this = this;
var MachineHelper = require("../helpers/MachineHelper");
var SystemApi = require("../api/SystemApi");
var LoginApi = require("../api/LoginApi");
var inquirer = require("inquirer");
var findDefaultCaptainName = require("../utils/loginHelpers").findDefaultCaptainName;
var isIpAddress = require("../utils/validationsHandler").isIpAddress;
var _a = require("../utils/constants"), SAMPLE_IP = _a.SAMPLE_IP, DEFAULT_PASSWORD = _a.DEFAULT_PASSWORD;
var _b = require("../utils/messageHandler"), printMessage = _b.printMessage, printError = _b.printError, printMessageAndExit = _b.printMessageAndExit, errorHandler = _b.errorHandler;
var newPasswordFirstTry = undefined;
var questions = [
{
type: "list",
name: "hasInstalledCaptain",
message: "Have you already installed Captain on your server by running the following line:" +
"\nmkdir /captain && docker run -p 80:80 -p 443:443 -p 3000:3000 -v /var/run/docker.sock:/var/run/docker.sock dockersaturn/captainduckduck ?",
default: "Yes",
choices: ["Yes", "No"],
filter: function (value) {
var answerFromUser = value.trim();
if (answerFromUser === "Yes")
return answerFromUser;
printMessage("\n\nCannot start the setup process if Captain is not installed.");
printMessageAndExit("Please read tutorial on CaptainDuckDuck.com to learn how to install CaptainDuckDuck on a server.");
}
},
{
type: "input",
default: SAMPLE_IP,
name: "captainAddress",
message: "Enter IP address of your captain server:",
filter: function (value) { return __awaiter(_this, void 0, void 0, function () {
var ipFromUser, data, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
ipFromUser = value.trim();
if (ipFromUser === SAMPLE_IP || !isIpAddress(ipFromUser)) {
printError("\nThis is an invalid IP Address: " + ipFromUser, true);
}
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, LoginApi.loginMachine("http://" + ipFromUser + ":3000", DEFAULT_PASSWORD)];
case 2:
data = _a.sent();
SystemApi.setIpAddressOfServer(ipFromUser);
// All went well
if (data)
return [2 /*return*/, ipFromUser];
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
errorHandler(e_1);
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
}); }
},
{
type: "password",
name: "captainOriginalPassword",
message: "Enter your current password:",
when: function () { return !LoginApi.token; },
filter: function (value) { return __awaiter(_this, void 0, void 0, function () {
var captainPasswordFromUser, data, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
captainPasswordFromUser = value.trim();
return [4 /*yield*/, LoginApi.loginMachine("http://" + SystemApi.ipAddressOfServer + ":3000", captainPasswordFromUser)];
case 1:
data = _a.sent();
if (data) {
SystemApi.setIpAddressOfServer(captainPasswordFromUser);
LoginApi.setOldPassword(captainPasswordFromUser);
}
return [3 /*break*/, 3];
case 2:
e_2 = _a.sent();
errorHandler(e_2);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); }
},
{
type: "input",
name: "captainRootDomain",
message: "Enter a root domain for this Captain server. For example, enter test.yourdomain.com if you" +
" setup your DNS to point *.test.yourdomain.com to ip address of your server" +
": ",
filter: function (value) { return __awaiter(_this, void 0, void 0, function () {
var captainRootDomainFromUser, data, newCustomDomainFromUser, e_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
captainRootDomainFromUser = value.trim();
return [4 /*yield*/, SystemApi.setCustomDomain("http://" + SystemApi.ipAddressOfServer + ":3000", captainRootDomainFromUser)];
case 1:
data = _a.sent();
if (data) {
newCustomDomainFromUser = "captain." + captainRootDomainFromUser;
SystemApi.setCustomDomainFromUser(newCustomDomainFromUser);
return [2 /*return*/, captainRootDomainFromUser];
}
return [3 /*break*/, 3];
case 2:
e_3 = _a.sent();
errorHandler(e_3);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); }
},
{
type: "input",
name: "emailAddress",
message: "Enter your 'valid' email address to enable HTTPS: ",
filter: function (value) { return __awaiter(_this, void 0, void 0, function () {
var emailAddressFromUser, customDomainFromUser, data, e_4;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 3, , 4]);
emailAddressFromUser = value.trim();
customDomainFromUser = SystemApi.customDomainFromUser;
return [4 /*yield*/, SystemApi.enableHttps("http://" + customDomainFromUser, emailAddressFromUser)];
case 1:
_a.sent();
return [4 /*yield*/, SystemApi.forceHttps("https://" + customDomainFromUser)];
case 2:
data = _a.sent();
if (data)
return [2 /*return*/, emailAddressFromUser];
return [3 /*break*/, 4];
case 3:
e_4 = _a.sent();
errorHandler(e_4);
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
}); }
},
{
type: "password",
name: "newPasswordFirstTry",
message: "Enter a new password:",
filter: function (value) {
newPasswordFirstTry = value;
return value;
}
},
{
type: "password",
name: "newPassword",
message: "Enter a new password:",
filter: function (value) { return __awaiter(_this, void 0, void 0, function () {
var customDomainFromUser, confirmPasswordValueFromUser, machineUrl, changePassData, loginData, e_5;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
customDomainFromUser = SystemApi.customDomainFromUser;
_a.label = 1;
case 1:
_a.trys.push([1, 5, , 6]);
confirmPasswordValueFromUser = value;
machineUrl = "https://" + customDomainFromUser;
if (newPasswordFirstTry !== confirmPasswordValueFromUser) {
printError("Passwords do not match", true);
}
return [4 /*yield*/, LoginApi.changePass(machineUrl, confirmPasswordValueFromUser)];
case 2:
changePassData = _a.sent();
if (!changePassData) return [3 /*break*/, 4];
return [4 /*yield*/, LoginApi.login(machineUrl, confirmPasswordValueFromUser)];
case 3:
loginData = _a.sent();
if (loginData)
return [2 /*return*/];
_a.label = 4;
case 4: return [3 /*break*/, 6];
case 5:
e_5 = _a.sent();
printError("\nIMPORTANT!! Server setup is completed by password is not changed.");
printError("\nYou CANNOT use serversetup anymore. To continue:");
printError("\n- Go to https://" + customDomainFromUser + " login with default password and change the password in settings.");
printError("\n- In terminal (here), type captainduckduck login and enter this as your root domain: " + customDomainFromUser, true);
return [3 /*break*/, 6];
case 6: return [2 /*return*/];
}
});
}); }
},
{
type: "input",
name: "captainName",
message: "Enter a name for this Captain machine:",
default: findDefaultCaptainName(),
validate: function (value) {
var newMachineName = value.trim();
MachineHelper.machines.map(function (machine) {
return machine.name === newMachineName &&
newMachineName + " already exist. If you want to replace the existing entry, you have to first use <logout> command, and then re-login.";
});
if (value.match(/^[-\d\w]+$/i)) {
return true;
}
return "Please enter a Captain Name.";
}
}
];
function serversetup() {
return __awaiter(this, void 0, void 0, function () {
var answers, captainAddress, newMachine;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
printMessage("\nSetup your Captain server\n");
return [4 /*yield*/, inquirer.prompt(questions)];
case 1:
answers = _a.sent();
captainAddress = "https://" + SystemApi.customDomainFromUser;
newMachine = {
authToken: LoginApi.token,
baseUrl: captainAddress,
name: answers.captainName
};
MachineHelper.addMachine(newMachine);
printMessage("\n\nCaptain is available at " + captainAddress);
printMessage("\nFor more details and docs see http://www.captainduckduck.com\n\n");
return [2 /*return*/];
}
});
});
}
module.exports = serversetup;
+86
View File
@@ -0,0 +1,86 @@
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var printMessage = require("../utils/messageHandler").printMessage;
var configstore = require("configstore");
var packagejson = require("../../package.json");
var configs = new configstore(packagejson.name, {
captainMachines: []
});
var MachineHelper = /** @class */ (function () {
function MachineHelper() {
this.machines = configs.get("captainMachines");
this.apps = configs.get("apps");
}
MachineHelper.prototype.getMachinesAsOptions = function () {
var firstItemInOption = [
{
name: "-- CANCEL --",
value: "",
short: ""
}
];
var listOfMachines = this.machines.map(function (machine) {
return {
name: machine.name + " at " + machine.baseUrl,
value: "" + machine.name,
short: machine.name + " at " + machine.baseUrl
};
});
return firstItemInOption.concat(listOfMachines);
};
MachineHelper.prototype.setMachines = function (newMachines) {
this.machines = newMachines;
configs.set("captainMachines", newMachines);
};
MachineHelper.prototype.updateMachineAuthToken = function (machineName, authToken) {
var updatedMachine = {};
var newMachines = this.machines.map(function (machine) {
if (machine.name === machineName) {
updatedMachine = __assign({}, machine, { authToken: authToken });
return updatedMachine;
}
return machine;
});
this.setMachines(newMachines);
this.updateAppsAuthToken(updatedMachine);
};
MachineHelper.prototype.updateAppsAuthToken = function (updatedMachine) {
if (!updatedMachine)
return;
var newApps = this.apps.map(function (app) {
if (app.machineToDeploy.name === updatedMachine.name) {
return __assign({}, app, { machineToDeploy: updatedMachine });
}
return app;
});
this.setApps(newApps);
};
MachineHelper.prototype.setApps = function (newApps) {
this.apps = newApps;
configs.set("apps", newApps);
};
MachineHelper.prototype.addMachine = function (newMachine) {
var tempMachines = this.machines;
var newMachines = tempMachines.concat([newMachine]);
// Add to local storage
configs.set("captainMachines", newMachines);
this.setMachines(configs.get("captainMachines"));
};
MachineHelper.prototype.logoutMachine = function (machineName) {
var removedMachine = this.machines.filter(function (machine) { return machine.name === machineName; })[0];
var newMachines = this.machines.filter(function (machine) { return machine.name !== machineName; });
this.setMachines(newMachines);
printMessage("You are now logged out from " + removedMachine.name + " at " + removedMachine.baseUrl + "...\n");
};
return MachineHelper;
}());
module.exports = new MachineHelper();
+23
View File
@@ -0,0 +1,23 @@
var ora = require("ora");
var SpinnerHelper = /** @class */ (function () {
function SpinnerHelper() {
this.spinner;
}
SpinnerHelper.prototype.setColor = function (color) {
this.spinner.color = color;
};
SpinnerHelper.prototype.start = function (message) {
this.spinner = ora(message).start();
};
SpinnerHelper.prototype.stop = function () {
this.spinner.stop();
};
SpinnerHelper.prototype.succeed = function () {
this.spinner.succeed();
};
SpinnerHelper.prototype.fail = function () {
this.spinner.fail();
};
return SpinnerHelper;
}());
module.exports = new SpinnerHelper();
+36
View File
@@ -0,0 +1,36 @@
var _a = require("../loginHelpers"), cleanUpUrl = _a.cleanUpUrl, findDefaultCaptainName = _a.findDefaultCaptainName, getCaptainFullName = _a.getCaptainFullName;
jest.mock("../../helpers/MachineHelper", function () {
return {
machines: [
{
baseUrl: "https://captain.myfirstmachine.com",
name: "machine-01",
authToken: "token1"
},
{
baseUrl: "https://captain.mysecondmachine.com",
name: "machine-02",
authToken: "token2"
}
]
};
});
describe("Login helpers", function () {
it("should clean a url", function () {
var mockUrl = "https://www.google.com";
var expectedResult = "www.google.com";
var result = cleanUpUrl(mockUrl);
expect(result).toBe(expectedResult);
});
it("should get a captain machine name", function () {
var result = getCaptainFullName(1);
var expectedResult = "captain-01";
expect(result).toBe(expectedResult);
});
it("should find an unused name for a possible new captain machine", function () {
// If machines are 2, then it should be with suffix 03
var result = findDefaultCaptainName();
var expectedResult = "captain-03";
expect(result).toBe(expectedResult);
});
});
+59
View File
@@ -0,0 +1,59 @@
var _a = require("../machineUtils"), initMachineFromLocalStorage = _a.initMachineFromLocalStorage, saveMachineToLocalStorage = _a.saveMachineToLocalStorage;
var DeployApi = require("../../api/DeployApi");
var MachineHelper = require("../../helpers/MachineHelper");
var mockUpdatedApps = [
{
cwd: process.cwd(),
appName: "captain-node-app-new-name",
branchToPush: "master",
machineToDeploy: {
baseUrl: "https://int-test.captainduckduck.com",
name: "int-test",
authToken: "token1"
}
}
];
jest.mock("../../helpers/MachineHelper", function () {
return {
apps: [
{
cwd: process.cwd(),
appName: "captain-node-app",
branchToPush: "master",
machineToDeploy: {
baseUrl: "https://int-test.captainduckduck.com",
name: "int-test",
authToken: "token1"
}
}
],
setApps: jest.fn()
};
});
jest.mock("../../api/DeployApi", function () {
return {
setMachineToDeploy: jest.fn(),
setAppName: jest.fn(),
setBranchToPush: jest.fn(),
appName: "captain-node-app-new-name",
branchToPush: "master",
machineToDeploy: {
baseUrl: "https://int-test.captainduckduck.com",
name: "int-test",
authToken: "token1"
}
};
});
describe("Machine utils", function () {
it("should init machine from localStorage", function () {
initMachineFromLocalStorage();
expect(DeployApi.setMachineToDeploy).toHaveBeenCalledTimes(1);
expect(DeployApi.setAppName).toHaveBeenCalledTimes(1);
expect(DeployApi.setBranchToPush).toHaveBeenCalledTimes(1);
});
it("should update an app from localstorage", function () {
saveMachineToLocalStorage();
var updatedApps = mockUpdatedApps;
expect(MachineHelper.setApps).toBeCalledWith(updatedApps);
});
});
+109
View File
@@ -0,0 +1,109 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var _this = this;
var _a = require("../validationsHandler"), validateIsGitRepository = _a.validateIsGitRepository, validateDefinitionFile = _a.validateDefinitionFile, optionIsNotGiven = _a.optionIsNotGiven, isIpAddress = _a.isIpAddress, validateAuthentication = _a.validateAuthentication;
var printError = require("../messageHandler").printError;
var requestLogin = require("../../commands/login").requestLogin;
var initMachineFromLocalStorage = require("../machineUtils").initMachineFromLocalStorage;
jest.mock("fs");
jest.mock("../messageHandler", function () {
return {
printError: jest.fn()
};
});
jest.mock("../../api/DeployApi", function () {
return {
isAuthTokenValid: jest.fn(function () { return false; }) // Simulates it's not authenticated
};
});
jest.mock("../../commands/login", function () {
return {
requestLogin: jest.fn()
};
});
jest.mock("../machineUtils", function () {
return {
initMachineFromLocalStorage: jest.fn()
};
});
describe("Validations handler", function () {
it("should printError if not on a git repository", function () {
validateIsGitRepository();
expect(printError).toHaveBeenCalledTimes(1);
});
it("should printError if there is no captain definition file", function () {
validateDefinitionFile();
// 2nd time because file was not found
// 3rd time because it tried to read from a file and was not valid json
expect(printError).toHaveBeenCalledTimes(3);
});
it("should return false if the option is included", function () {
var options = {
branch: "master"
};
var result = optionIsNotGiven(options, "branch");
expect(result).toBe(false);
});
it("should return true if the option is not given", function () {
var options = {
test: "something"
};
var result = optionIsNotGiven(options, "branch");
expect(result).toBe(true);
});
it("should be a valid IP Address", function () {
var validIpAddress = "192.168.1.1";
var result = isIpAddress(validIpAddress);
expect(result).toBe(true);
});
it("should be an invalid IP Address", function () {
var validIpAddress = "192.168.1";
var result = isIpAddress(validIpAddress);
expect(result).toBe(false);
});
it("should promt the login option and initialize from the machine in localstorage", function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, validateAuthentication()];
case 1:
_a.sent();
expect(requestLogin).toBeCalledTimes(1);
expect(initMachineFromLocalStorage).toBeCalledTimes(1);
return [2 /*return*/];
}
});
}); });
});
+14
View File
@@ -0,0 +1,14 @@
var SAMPLE_DOMAIN = "captain.captainroot.yourdomain.com";
var SAMPLE_IP = "123.123.123.123";
var DEFAULT_PASSWORD = "captain42";
var DEFAULT_BRANCH_TO_PUSH = "branchToPush";
var DEFAULT_APP_NAME = "appName";
var EMPTY_STRING = "";
module.exports = {
SAMPLE_DOMAIN: SAMPLE_DOMAIN,
SAMPLE_IP: SAMPLE_IP,
DEFAULT_PASSWORD: DEFAULT_PASSWORD,
DEFAULT_BRANCH_TO_PUSH: DEFAULT_BRANCH_TO_PUSH,
DEFAULT_APP_NAME: DEFAULT_APP_NAME,
EMPTY_STRING: EMPTY_STRING
};
+190
View File
@@ -0,0 +1,190 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var fs = require("fs-extra");
var _a = require("./messageHandler"), printMessage = _a.printMessage, printError = _a.printError, printGreenMessage = _a.printGreenMessage, printMagentaMessage = _a.printMagentaMessage;
var SpinnerHelper = require("../helpers/SpinnerHelper");
var exec = require("child_process").exec;
var ProgressBar = require("progress");
var DeployApi = require("../api/DeployApi");
var saveMachineToLocalStorage = require("../utils/machineUtils").saveMachineToLocalStorage;
var lastLineNumberPrinted = -10000; // we want to show all lines to begin with!
function gitArchiveFile(zipFileFullPath, branchToPush) {
exec("git archive --format tar --output \"" + zipFileFullPath + "\" " + branchToPush, function (err, stdout, stderr) {
if (err) {
printError("TAR file failed\n" + err + "\n");
fs.removeSync(zipFileFullPath);
return;
}
exec("git rev-parse " + branchToPush, function (err, stdout, stderr) {
var gitHash = (stdout || "").trim();
if (err || !/^[a-f0-9]{40}$/.test(gitHash)) {
printError("Cannot find hash of last commit on this branch: " + branchToPush + "\n" + gitHash + "\n" + err + "\n");
return;
}
printMessage("Pushing last commit on " + branchToPush + ": " + gitHash);
uploadFile(zipFileFullPath, gitHash);
});
});
}
function onLogRetrieved(data) {
if (data) {
var lines = data.logs.lines;
var firstLineNumberOfLogs = data.logs.firstLineNumber;
var firstLinesToPrint = 0;
if (firstLineNumberOfLogs > lastLineNumberPrinted) {
if (firstLineNumberOfLogs < 0) {
// This is the very first fetch, probably firstLineNumberOfLogs is around -50
firstLinesToPrint = -firstLineNumberOfLogs;
}
else {
printMessage("[[ TRUNCATED ]]");
}
}
else {
firstLinesToPrint = lastLineNumberPrinted - firstLineNumberOfLogs;
}
lastLineNumberPrinted = firstLineNumberOfLogs + lines.length;
for (var i = firstLinesToPrint; i < lines.length; i++) {
printMessage((lines[i] || "").trim());
}
}
var finishedBuilding = data && !data.isAppBuilding;
if (finishedBuilding) {
if (!data.isBuildFailed) {
printGreenMessage("Deployed successfully: " + DeployApi.appName);
printMagentaMessage("App is available at " + DeployApi.appUrl + "\n", true);
}
else {
printError("\nSomething bad happened. Cannot deploy \"" + DeployApi.appName + "\"\n", true);
}
}
setTimeout(function () {
startFetchingBuildLogs();
}, 2000);
}
function startFetchingBuildLogs() {
return __awaiter(this, void 0, void 0, function () {
var data, response, error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, DeployApi.fetchBuildLogs()];
case 1:
data = _a.sent();
response = JSON.parse(data);
if (response.status !== 100) {
throw new Error(JSON.stringify(response, null, 2));
}
onLogRetrieved(response.data);
return [3 /*break*/, 3];
case 2:
error_1 = _a.sent();
printError("\nSomething while retrieving app build logs.. " + error_1 + "\n");
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
});
}
function getFileStream(zipFileFullPath) {
var fileSize = fs.statSync(zipFileFullPath).size;
var fileStream = fs.createReadStream(zipFileFullPath);
var barOpts = {
width: 20,
total: fileSize,
clear: true
};
var bar = new ProgressBar(" uploading [:bar] :percent (ETA :etas)", barOpts);
fileStream.on("data", function (chunk) {
bar.tick(chunk.length);
});
fileStream.on("end", function () {
printMessage("This might take several minutes. PLEASE BE PATIENT...");
SpinnerHelper.start("Building your source code...");
SpinnerHelper.setColor("yellow");
});
return fileStream;
}
function uploadFile(filePath, gitHash) {
return __awaiter(this, void 0, void 0, function () {
var fileStream, response, data, somethingWentWrong, isDeployedAndBuilding, isDeployedSuccessfully, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
printMessage("Uploading file to " + DeployApi.machineToDeploy.baseUrl);
fileStream = getFileStream(filePath);
return [4 /*yield*/, DeployApi.sendFile(fileStream, gitHash)];
case 1:
response = _a.sent();
data = JSON.parse(response);
somethingWentWrong = data.status !== 100 && data.status !== 101;
isDeployedAndBuilding = data.status === 101;
isDeployedSuccessfully = data.status === 100;
if (somethingWentWrong) {
throw new Error(JSON.stringify(data, null, 2));
}
deleteFileFromDisk(filePath); // Uncomment this
// Save app to local storage
saveMachineToLocalStorage();
if (isDeployedAndBuilding) {
startFetchingBuildLogs();
}
if (isDeployedSuccessfully) {
printGreenMessage("Deployed successfully: " + DeployApi.appName + "\n", true);
}
return [3 /*break*/, 3];
case 2:
e_1 = _a.sent();
printError(e_1.message, true);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
});
}
function deleteFileFromDisk(filePath) {
if (fs.pathExistsSync(filePath)) {
fs.removeSync(filePath);
}
}
module.exports = {
gitArchiveFile: gitArchiveFile,
getFileStream: getFileStream,
uploadFile: uploadFile,
startFetchingBuildLogs: startFetchingBuildLogs
};
+37
View File
@@ -0,0 +1,37 @@
var MachineHelper = require("../helpers/MachineHelper");
function cleanUpUrl(url) {
if (!url || !url.length)
return null;
var cleanedUrl = url;
var hasSlashAtTheEnd = url.substr(url.length - 1, 1) === "/";
if (hasSlashAtTheEnd) {
// Remove the slash at the end
cleanedUrl = url.substr(0, url.length - 1);
}
return cleanedUrl
.replace("http://", "")
.replace("https://", "")
.trim();
}
function findDefaultCaptainName() {
var currentSuffix = MachineHelper.machines.length + 1;
while (!isSuffixValid(currentSuffix)) {
currentSuffix++;
}
return getCaptainFullName(currentSuffix);
}
function getCaptainFullName(suffix) {
var formatSuffix = suffix < 10 ? "0" + suffix : suffix;
return "captain-" + formatSuffix;
}
var isSuffixValid = function (suffixNumber) {
return MachineHelper.machines.map(function (machine) {
machine.name !== getCaptainFullName(suffixNumber);
});
};
module.exports = {
cleanUpUrl: cleanUpUrl,
findDefaultCaptainName: findDefaultCaptainName,
isSuffixValid: isSuffixValid,
getCaptainFullName: getCaptainFullName
};
+44
View File
@@ -0,0 +1,44 @@
var DeployApi = require("../api/DeployApi");
var MachineHelper = require("../helpers/MachineHelper");
function initMachineFromLocalStorage() {
var possibleApp = MachineHelper.apps.find(function (app) { return app.cwd === process.cwd(); });
if (possibleApp) {
DeployApi.setMachineToDeploy(possibleApp.machineToDeploy);
DeployApi.setAppName(possibleApp.appName);
DeployApi.setBranchToPush(possibleApp.branchToPush);
}
}
// Saves the app directory into local storage
function saveMachineToLocalStorage() {
var apps = MachineHelper.apps;
var currentDirectory = process.cwd();
var appExists = false;
// Update app
var updatedApps = apps.map(function (app) {
if (app.cwd === currentDirectory) {
appExists = true;
return {
cwd: app.cwd,
appName: DeployApi.appName,
branchToPush: DeployApi.branchToPush,
machineToDeploy: DeployApi.machineToDeploy
};
}
return app;
});
MachineHelper.setApps(updatedApps);
if (!appExists) {
var newApp = {
cwd: process.cwd(),
appName: DeployApi.appName,
branchToPush: DeployApi.branchToPush,
machineToDeploy: DeployApi.machineToDeploy
};
updatedApps.push(newApp);
MachineHelper.setApps(apps);
}
}
module.exports = {
initMachineFromLocalStorage: initMachineFromLocalStorage,
saveMachineToLocalStorage: saveMachineToLocalStorage
};
+39
View File
@@ -0,0 +1,39 @@
var chalk = require("chalk");
function printMessage(message) {
console.log(message);
}
function printMessageAndExit(message) {
console.log(message);
process.exit(0);
}
function printGreenMessage(message, exit) {
if (exit === void 0) { exit = false; }
console.log("" + chalk.green(message));
exit && process.exit(0);
}
function printMagentaMessage(message, exit) {
if (exit === void 0) { exit = false; }
console.log("" + chalk.magenta(message));
exit && process.exit(0);
}
function printError(error, exit) {
if (exit === void 0) { exit = false; }
console.log("" + chalk.bold.red(error));
exit && process.exit(0);
}
function errorHandler(error) {
if (error.status) {
printError("\nError: " + error.status + "\nError: " + error.description, true);
}
else {
printError("\nError: " + error, true);
}
}
module.exports = {
printMessage: printMessage,
printMessageAndExit: printMessageAndExit,
printError: printError,
printGreenMessage: printGreenMessage,
printMagentaMessage: printMagentaMessage,
errorHandler: errorHandler
};
+118
View File
@@ -0,0 +1,118 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var fs = require("fs-extra");
var DeployApi = require("../api/DeployApi");
var printError = require("./messageHandler").printError;
var requestLogin = require("../commands/login").requestLogin;
var initMachineFromLocalStorage = require("../utils/machineUtils").initMachineFromLocalStorage;
function validateIsGitRepository() {
var gitFolderExists = fs.pathExistsSync("./.git");
if (!gitFolderExists) {
printError("\n**** ERROR: You are not in a git root directory. This command will only deploys the current directory ****\n", true);
}
}
function validateDefinitionFile() {
var captainDefinitionExists = fs.pathExistsSync("./captain-definition");
if (!captainDefinitionExists) {
printError("\n**** ERROR: captain-definition file cannot be found. Please see docs! ****\n", true);
}
var contents = fs.readFileSync("./captain-definition", "utf8");
var contentsJson = null;
try {
contentsJson = JSON.parse(contents);
}
catch (e) {
printError("**** ERROR: captain-definition file is not a valid JSON! ****\n Error:" + e, true);
}
if (contentsJson) {
if (!contentsJson.schemaVersion) {
printError("**** ERROR: captain-definition needs schemaVersion. Please see docs! ****", true);
}
if (!contentsJson.templateId && !contentsJson.dockerfileLines) {
printError("**** ERROR: captain-definition needs templateId or dockerfileLines. Please see docs! ****", true);
}
if (contentsJson.templateId && contentsJson.dockerfileLines) {
printError("**** ERROR: captain-definition needs templateId or dockerfileLines, NOT BOTH! Please see docs! ****", true);
}
}
}
// Only show that question if there is no option given as argument
function optionIsNotGiven(allOptions, option) {
// console.log(allOptions)
if (allOptions[option]) {
return false;
}
return true;
}
function isIpAddress(ipaddress) {
if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ipaddress)) {
return true;
}
return false;
}
function validateAuthentication() {
return __awaiter(this, void 0, void 0, function () {
var isAuthenticated, loggedInStatus;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, DeployApi.isAuthTokenValid()
// 2. Request login
// 3. Login
// 4. Update token
];
case 1:
isAuthenticated = _a.sent();
if (!!isAuthenticated) return [3 /*break*/, 3];
return [4 /*yield*/, requestLogin()
// Refresh token in DeployApi
];
case 2:
loggedInStatus = _a.sent();
// Refresh token in DeployApi
initMachineFromLocalStorage();
return [2 /*return*/, loggedInStatus];
case 3: return [2 /*return*/, Boolean(isAuthenticated)];
}
});
});
}
module.exports = {
validateAuthentication: validateAuthentication,
validateIsGitRepository: validateIsGitRepository,
validateDefinitionFile: validateDefinitionFile,
isIpAddress: isIpAddress,
optionIsNotGiven: optionIsNotGiven
};
+18 -21
View File
@@ -24,6 +24,12 @@
"js-tokens": "^4.0.0"
}
},
"@types/node": {
"version": "10.12.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
"integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==",
"dev": true
},
"abab": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz",
@@ -1979,14 +1985,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -2001,20 +2005,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -2131,8 +2132,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@@ -2144,7 +2144,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -2159,7 +2158,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -2167,14 +2165,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -2193,7 +2189,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -2274,8 +2269,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -2287,7 +2281,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@@ -2409,7 +2402,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -5909,6 +5901,11 @@
"prelude-ls": "~1.1.2"
}
},
"typescript": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz",
"integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg=="
},
"uglify-js": {
"version": "3.4.9",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
+11 -8
View File
@@ -4,15 +4,16 @@
"description": "CLI tool for CaptainDuckDuck. See CaptainDuckDuck.com for more details.",
"main": "captainduckduck.js",
"scripts": {
"test": "jest"
"test": "jest",
"build": "npx tsc"
},
"bin": {
"captainduckduck": "./captainduckduck.js",
"captainduckduck-deploy": "./lib/deploy.js",
"captainduckduck-list": "./lib/list.js",
"captainduckduck-login": "./lib/login.js",
"captainduckduck-logout": "./lib/logout.js",
"captainduckduck-serversetup": "./lib/serversetup.js"
"captainduckduck": "./built/commands/captainduckduck.js",
"captainduckduck-deploy": "./built/commands/deploy.js",
"captainduckduck-list": "./built/commands/list.js",
"captainduckduck-login": "./built/commands/login.js",
"captainduckduck-logout": "./built/commands/logout.js",
"captainduckduck-serversetup": "./built/commands/serversetup.js"
},
"repository": {
"type": "git",
@@ -50,12 +51,14 @@
"progress": "^2.0.3",
"request": "^2.88.0",
"request-promise": "^4.2.2",
"typescript": "^3.2.2",
"update-notifier": "^2.5.0"
},
"devDependencies": {
"@types/node": "^10.12.18",
"eslint": "^5.11.1",
"eslint-plugin-jest": "^21.27.2",
"jest": "^23.6.0",
"prettier": "^1.15.3"
}
}
}
@@ -1,18 +1,18 @@
#!/usr/bin/env node
const { printError } = require("./utils/messageHandler")
const packagejson = require("./package.json")
const { printError } = require("../utils/messageHandler")
const packagejson = require("../../package.json")
const updateNotifier = require("update-notifier")
const program = require("commander")
updateNotifier({ pkg: packagejson }).notify({ isGlobal: true })
// Command actions
const serversetup = require("./lib/serversetup")
const { login } = require("./lib/login")
const logout = require("./lib/logout")
const list = require("./lib/list")
const deploy = require("./lib/deploy")
const serversetup = require("./serversetup")
const { login } = require("./login")
const logout = require("./logout")
const list = require("./list")
const deploy = require("./deploy")
// Setup
program.version(packagejson.version).description(packagejson.description)
@@ -1,6 +1,6 @@
const { printMessage } = require("../utils/messageHandler")
const configstore = require("configstore")
const packagejson = require("../package.json")
const packagejson = require("../../package.json")
const configs = new configstore(packagejson.name, {
captainMachines: []
})
@@ -6,7 +6,7 @@ const {
validateAuthentication
} = require("../validationsHandler")
const { printError } = require("../messageHandler")
const { requestLogin } = require("../../lib/login")
const { requestLogin } = require("../../commands/login")
const { initMachineFromLocalStorage } = require("../machineUtils")
jest.mock("fs")
@@ -23,7 +23,7 @@ jest.mock("../../api/DeployApi", () => {
}
})
jest.mock("../../lib/login", () => {
jest.mock("../../commands/login", () => {
return {
requestLogin: jest.fn()
}
@@ -1,7 +1,7 @@
const fs = require("fs-extra")
const DeployApi = require("../api/DeployApi")
const { printError } = require("./messageHandler")
const { requestLogin } = require("../lib/login")
const { requestLogin } = require("../commands/login")
const { initMachineFromLocalStorage } = require("../utils/machineUtils")
function validateIsGitRepository() {
+11
View File
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"outDir": "./built",
"allowJs": true,
"target": "es5",
"noImplicitReturns": false
},
"include": [
"./src/**/*"
]
}