diff --git a/packages/bolt/build/actions/deploy/deploy.d.ts b/packages/bolt/build/actions/deploy/deploy.d.ts index 46d7227..3692319 100644 --- a/packages/bolt/build/actions/deploy/deploy.d.ts +++ b/packages/bolt/build/actions/deploy/deploy.d.ts @@ -7,10 +7,19 @@ export default class DeployClass { constructor(); setStore(): Promise; saveStore(): Promise; - getSealContent(): Promise; + getBoltFileContent(): Promise; setServices(): Promise; createZip(): Promise; - auth(doAuth: boolean): Promise; - upload(): Promise; + auth(doAuth: boolean): Promise<{ + user: any; + projects: any; + } | undefined>; + setProject(projects: any[]): Promise; + upload(): Promise; + submit({ projectId, fileId, userId, }: { + projectId: number; + fileId: number; + userId: number; + }): Promise; watch(): Promise; } diff --git a/packages/bolt/build/actions/deploy/deploy.js b/packages/bolt/build/actions/deploy/deploy.js index 3476a60..2532bdc 100644 --- a/packages/bolt/build/actions/deploy/deploy.js +++ b/packages/bolt/build/actions/deploy/deploy.js @@ -23,13 +23,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) { if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { - define(["require", "exports", "../../helpers/get-store", "../../helpers/deploy/deploy", "../../common"], factory); + define(["require", "exports", "../../helpers/get-store", "../../helpers/deploy/deployment", "../../common"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const get_store_1 = __importDefault(require("../../helpers/get-store")); - const deploy_1 = require("../../helpers/deploy/deploy"); + const deployment_1 = require("../../helpers/deploy/deployment"); const common_1 = __importDefault(require("../../common")); class DeployClass { constructor() { @@ -48,7 +48,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { this.store.save(); }); } - getSealContent() { + getBoltFileContent() { return __awaiter(this, void 0, void 0, function* () { const _yamlContent = yield common_1.default.getAndValidateBoltYaml(); return _yamlContent; @@ -59,7 +59,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { var _a, e_1, _b, _c; return __awaiter(this, void 0, void 0, function* () { const services = this.services; - const _yamlContent = yield this.getSealContent(); + const _yamlContent = yield this.getBoltFileContent(); try { // Gather all the availables services for (var _d = true, _e = __asyncValues(Object.entries(_yamlContent.services)), _f; _f = yield _e.next(), _a = _f.done, !_a;) { @@ -89,28 +89,40 @@ var __importDefault = (this && this.__importDefault) || function (mod) { createZip() { return __awaiter(this, void 0, void 0, function* () { const cwd = this.cwd; - const { zipPath } = yield (0, deploy_1.zip)(cwd); + const { zipPath } = yield (0, deployment_1.zip)(cwd); this.zipPath = zipPath; return Promise.resolve(zipPath); }); } - // Authenticates users credentials and - // stores the details into the project's store auth(doAuth) { return __awaiter(this, void 0, void 0, function* () { - yield (0, deploy_1.auth)(doAuth, this.store); + return yield (0, deployment_1.auth)(doAuth, this.store); + }); + } + setProject(projects) { + return __awaiter(this, void 0, void 0, function* () { + return yield (0, deployment_1.setProject)(projects); }); } // uploads the zip into minio upload() { return __awaiter(this, void 0, void 0, function* () { - yield (0, deploy_1.upload)(this.zipPath, this.store); + return yield (0, deployment_1.upload)(this.zipPath, this.store); + }); + } + submit({ projectId, fileId, userId, }) { + return __awaiter(this, void 0, void 0, function* () { + return yield (0, deployment_1.deploy)({ + projectId, + fileId, + userId, + }); }); } // watches the deployment steps watch() { return __awaiter(this, void 0, void 0, function* () { - yield (0, deploy_1.watch)(this.store); + yield (0, deployment_1.watch)(this.store); }); } } diff --git a/packages/bolt/build/actions/deploy/index.js b/packages/bolt/build/actions/deploy/index.js index cab379c..39b47b1 100644 --- a/packages/bolt/build/actions/deploy/index.js +++ b/packages/bolt/build/actions/deploy/index.js @@ -28,20 +28,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) { const route_generate_1 = __importDefault(require("../route-generate")); const deploy_1 = __importDefault(require("./deploy")); exports.default = (options, isWatch = false) => __awaiter(void 0, void 0, void 0, function* () { + var _a; + // validate the project + console.log(">> Validating project..."); + yield (0, validate_metadata_1.validateMetadata)(); + yield (0, validate_services_1.validateServices)(); console.log(chalk_1.default.gray(">> Building Production Envs...")); const envGenerate = new env_generate_1.default(); yield envGenerate.handle({ environment: "production" }); + console.log(chalk_1.default.green(">> Production Envs built successfully!") + "\n"); const routeGenerate = new route_generate_1.default(); yield routeGenerate.handle(true); - return; - // validate the project - console.log(">> Validating project..."); - yield (0, validate_metadata_1.validateMetadata)(); - yield (0, validate_services_1.validateServices)(); - console.log("\n> Note: Please remove any zip file or unnecessary files/folders from your project before deploying!"); - console.log("\n> Deploying project..."); + console.log("\n>> Note: Please remove any zip file or unnecessary files/folders from your project before deploying!"); + console.log("\n>> Deploying project..."); const deploy = new deploy_1.default(); - console.log("\n> Gathering all deployable services..."); + console.log("\n>> Gathering all deployable services..."); // populate store yield deploy.setStore(); // populate services @@ -57,17 +58,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) { yield deploy.createZip(); // authenticate the user & store creds in local store console.log("\n>> Authenticating user credentials..."); - yield deploy.auth(options.auth); + const authData = yield deploy.auth(options.auth); console.log(">> Authentication successful!\n"); + const projects = (authData === null || authData === void 0 ? void 0 : authData.projects) || []; + const selectedProject = yield deploy.setProject(projects); // uploads the project zip file to minio console.log(">> Uploading project zip file..."); - yield deploy.upload(); + const fileId = yield deploy.upload(); console.log(">> Project zip file uploaded successfully!\n"); - // save store - yield deploy.saveStore(); - if (isWatch) { - console.log(">> Fetching deployment details...\n"); - yield deploy.watch(); - } + console.log(">> Submitting the deployment now..."); + const deployment = yield deploy.submit({ + fileId, + projectId: selectedProject.id, + userId: (_a = authData === null || authData === void 0 ? void 0 : authData.user) === null || _a === void 0 ? void 0 : _a.id, + }); + console.log(">> Deployment submitted successfully!\n"); + // // save store + // await deploy.saveStore(); + // if (isWatch) { + // console.log(">> Fetching deployment details...\n"); + // await deploy.watch(); + // } }); }); diff --git a/packages/bolt/build/actions/route-generate.js b/packages/bolt/build/actions/route-generate.js index b989cc0..c1ae232 100644 --- a/packages/bolt/build/actions/route-generate.js +++ b/packages/bolt/build/actions/route-generate.js @@ -34,7 +34,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) { yield (0, validate_services_1.validateServices)(); console.log(`>> Creating Ingress...`); yield (0, generate_routes_1.default)(_yamlContent, isProd); - process.exit(0); + { + !isProd && process.exit(0); + } }); } } diff --git a/packages/bolt/build/commands/13-deploy.js b/packages/bolt/build/commands/13-deploy.js index c59ce38..b6dd78a 100644 --- a/packages/bolt/build/commands/13-deploy.js +++ b/packages/bolt/build/commands/13-deploy.js @@ -16,22 +16,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) { if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { - define(["require", "exports", "chalk"], factory); + define(["require", "exports", "../actions/deploy"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - const chalk_1 = __importDefault(require("chalk")); - // import deploy from "../actions/deploy"; + const deploy_1 = __importDefault(require("../actions/deploy")); exports.default = (program) => __awaiter(void 0, void 0, void 0, function* () { program .command("deploy") .option("-a, --auth [true]", "Re-enter credentials, do not use presisted credentials from earlier", false) .description("Prepares the compressed project & initiates the deployment") .action((options) => { - console.log(chalk_1.default.green(">> Coming Soon...")); - process.exit(); - // deploy(options, true); + (0, deploy_1.default)(options, true); }); }); }); diff --git a/packages/bolt/build/config/index.d.ts b/packages/bolt/build/config/index.d.ts index b40010c..1dd94ec 100644 --- a/packages/bolt/build/config/index.d.ts +++ b/packages/bolt/build/config/index.d.ts @@ -1,8 +1,7 @@ /** * SEAL server details */ -export declare const SEAL_DOMAIN: string; /** * SEAL GQL service details */ -export declare const SEAL_GQL: string; +export declare const BOX_SERVER_URL: string; diff --git a/packages/bolt/build/config/index.js b/packages/bolt/build/config/index.js index 410152b..eeb9111 100644 --- a/packages/bolt/build/config/index.js +++ b/packages/bolt/build/config/index.js @@ -1,3 +1,7 @@ +/** + * SEAL server details + */ +// export const SEAL_DOMAIN: string = "https://api.gluestack.io"; (function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); @@ -9,13 +13,10 @@ })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - exports.SEAL_GQL = exports.SEAL_DOMAIN = void 0; - /** - * SEAL server details - */ - exports.SEAL_DOMAIN = 'https://api.gluestack.io'; + exports.BOX_SERVER_URL = void 0; /** * SEAL GQL service details */ - exports.SEAL_GQL = 'https://api.gluestack.io/backend/graphql'; + // export const SEAL_GQL: string = "https://api.gluestack.io/backend/graphql"; + exports.BOX_SERVER_URL = "http://localhost:8000/api"; }); diff --git a/packages/bolt/build/helpers/deploy/apis/api-request.d.ts b/packages/bolt/build/helpers/deploy/apis/api-request.d.ts new file mode 100644 index 0000000..5fc6d42 --- /dev/null +++ b/packages/bolt/build/helpers/deploy/apis/api-request.d.ts @@ -0,0 +1,7 @@ +export declare const apiRequest: ({ data, method, route, params, headers, }: { + data: any; + method: "GET" | "POST" | "PUT" | "DELETE"; + route: string; + params?: any; + headers?: any; +}) => Promise>; diff --git a/packages/bolt/build/helpers/deploy/apis/api-request.js b/packages/bolt/build/helpers/deploy/apis/api-request.js new file mode 100644 index 0000000..e0b027e --- /dev/null +++ b/packages/bolt/build/helpers/deploy/apis/api-request.js @@ -0,0 +1,49 @@ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + 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) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports", "../../get-store-data", "axios", "../../../config"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.apiRequest = void 0; + const get_store_data_1 = require("../../get-store-data"); + const axios_1 = __importDefault(require("axios")); + const config_1 = require("../../../config"); + const apiRequest = ({ data, method, route, params, headers, }) => __awaiter(void 0, void 0, void 0, function* () { + const accessKey = yield (0, get_store_data_1.getStoreData)("access_key"); + const secretKey = yield (0, get_store_data_1.getStoreData)("secret_key"); + const requestHeaders = Object.assign({ ["Access-Key"]: accessKey, ["Secret-Key"]: secretKey }, headers); + params = params ? getParamString(params) : ""; + const config = { + method: method, + url: `${config_1.BOX_SERVER_URL}/deployment${route}${params}`, + headers: requestHeaders, + data: data, + }; + return yield axios_1.default.request(config); + }); + exports.apiRequest = apiRequest; + const getParamString = (params) => { + let paramString = "?"; + for (const [key, value] of Object.entries(params)) { + paramString += `${key}=${value}&`; + } + return paramString; + }; +}); diff --git a/packages/bolt/build/helpers/deploy/apis/client.d.ts b/packages/bolt/build/helpers/deploy/apis/client.d.ts index eecccaf..337b398 100644 --- a/packages/bolt/build/helpers/deploy/apis/client.d.ts +++ b/packages/bolt/build/helpers/deploy/apis/client.d.ts @@ -1,3 +1,3 @@ -import { GraphQLClient } from 'graphql-request'; +import { GraphQLClient } from "graphql-request"; export declare const clientGQL: GraphQLClient; -export { request, gql } from 'graphql-request'; +export { request, gql } from "graphql-request"; diff --git a/packages/bolt/build/helpers/deploy/apis/client.js b/packages/bolt/build/helpers/deploy/apis/client.js index aec5ce5..e167715 100644 --- a/packages/bolt/build/helpers/deploy/apis/client.js +++ b/packages/bolt/build/helpers/deploy/apis/client.js @@ -12,7 +12,7 @@ exports.gql = exports.request = exports.clientGQL = void 0; const graphql_request_1 = require("graphql-request"); const config_1 = require("../../../config"); - exports.clientGQL = new graphql_request_1.GraphQLClient(config_1.SEAL_GQL); + exports.clientGQL = new graphql_request_1.GraphQLClient(config_1.BOX_SERVER_URL); var graphql_request_2 = require("graphql-request"); Object.defineProperty(exports, "request", { enumerable: true, get: function () { return graphql_request_2.request; } }); Object.defineProperty(exports, "gql", { enumerable: true, get: function () { return graphql_request_2.gql; } }); diff --git a/packages/bolt/build/helpers/deploy/deploy/auth.js b/packages/bolt/build/helpers/deploy/deploy/auth.js deleted file mode 100644 index babdb4b..0000000 --- a/packages/bolt/build/helpers/deploy/deploy/auth.js +++ /dev/null @@ -1,72 +0,0 @@ -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - 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) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -(function (factory) { - if (typeof module === "object" && typeof module.exports === "object") { - var v = factory(require, exports); - if (v !== undefined) module.exports = v; - } - else if (typeof define === "function" && define.amd) { - define(["require", "exports", "../../../config", "@gluestack/glue-server-sdk-js"], factory); - } -})(function (require, exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.auth = void 0; - const inquirer = require("inquirer"); - const config_1 = require("../../../config"); - const glue_server_sdk_js_1 = require("@gluestack/glue-server-sdk-js"); - const auth = (doAuth, store) => __awaiter(void 0, void 0, void 0, function* () { - const creds = { - email: store.get("email"), - password: store.get("password"), - }; - // prompts to collect credentials from users - if (doAuth || !creds.email || !creds.password) { - const results = yield inquirer.prompt([ - { - name: "email", - message: "Please enter your email", - type: "input", - }, - { - name: "password", - message: "Please enter your password", - type: "password", - }, - ]); - creds.email = results.email; - creds.password = results.password; - // store credentials in the store - store.set("email", results.email); - store.set("password", results.password); - } - const glue = new glue_server_sdk_js_1.Glue(config_1.SEAL_DOMAIN); - const response = yield glue.auth.login(Object.assign(Object.assign({}, creds), { role: "owner" })); - if (!response || !response.id) { - console.log(`>> Authentication failed. Message: ${response}`); - process.exit(-1); - } - if (!response.is_verified) { - console.log(`>> Authentication failed. Message: Account is not verified`); - process.exit(-1); - } - if (response.status === "on_waitlist") { - console.log(`>> Authentication failed. User is on waitlist`); - process.exit(-1); - } - // store user data in the store - store.set("team", response.team); - delete response.team; - store.set("user", response); - // save store - store.save(); - }); - exports.auth = auth; -}); diff --git a/packages/bolt/build/helpers/deploy/deploy/index.d.ts b/packages/bolt/build/helpers/deploy/deploy/index.d.ts deleted file mode 100644 index 545d7ca..0000000 --- a/packages/bolt/build/helpers/deploy/deploy/index.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './auth'; -export * from './upload'; -export * from './zip'; -export * from './watch'; diff --git a/packages/bolt/build/helpers/deploy/deploy/upload.js b/packages/bolt/build/helpers/deploy/deploy/upload.js deleted file mode 100644 index 8a155d1..0000000 --- a/packages/bolt/build/helpers/deploy/deploy/upload.js +++ /dev/null @@ -1,105 +0,0 @@ -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - 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) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -(function (factory) { - if (typeof module === "object" && typeof module.exports === "object") { - var v = factory(require, exports); - if (v !== undefined) module.exports = v; - } - else if (typeof define === "function" && define.amd) { - define(["require", "exports", "fs", "../../../config", "../apis/handlers/gql", "@gluestack/glue-server-sdk-js", "../apis/handlers/gql/create-deployment"], factory); - } -})(function (require, exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.upload = void 0; - const fs_1 = require("fs"); - const config_1 = require("../../../config"); - const gql_1 = require("../apis/handlers/gql"); - const glue_server_sdk_js_1 = require("@gluestack/glue-server-sdk-js"); - const create_deployment_1 = require("../apis/handlers/gql/create-deployment"); - const inquirer = require("inquirer"); - const upload = (filepath, store) => __awaiter(void 0, void 0, void 0, function* () { - let projectHash = store.get("project_hash"); - // prompts to collect Project ID from user - if (!projectHash || projectHash === "new") { - const team = store.get("team"); - let tmp; - try { - tmp = yield (0, gql_1.projects)(team.id, team.token); - } - catch (err) { - console.log(err); - console.log("> Error fetching projects... Please try again later."); - process.exit(-1); - } - // transform key-value pairs - const choices = [{ name: "Create a new Project", value: "new" }]; - choices.push(...tmp.projects.map((project) => { - return { name: project.name, value: project.project_hash }; - })); - // prompt to collect right project from user - const results = yield inquirer.prompt([ - { - name: "projectHash", - message: "Please choose an existing project or create one", - type: "list", - choices: choices, - }, - ]); - if (!results || !results.projectHash) { - console.error("> Error collecting project id"); - process.exit(-1); - } - // store project id in the store - projectHash = results.projectHash; - store.set("project_hash", results.projectHash); - } - // upload the project zip file to minio - const glue = new glue_server_sdk_js_1.Glue(config_1.SEAL_DOMAIN); - try { - const response = yield glue.storage.upload((0, fs_1.createReadStream)(filepath)); - if (response && !response.id) { - console.error("Error uploading the project zip file to minio"); - process.exit(1); - } - store.set("file_id", response.id); - console.log("> File uploaded successfully..."); - } - catch (error) { - console.log("> Uploading failed due to following reason:", error.message || error); - console.log(error); - process.exit(-1); - } - // submits the deployment - console.log("> Submitting the deployment now..."); - try { - const user = store.get("user"); - const team = store.get("team"); - const fileID = store.get("file_id"); - const projectHash = store.get("project_hash"); - const projectName = process.cwd().split("/")[process.cwd().split("/").length - 1]; - const response = yield (0, create_deployment_1.createDeployment)(projectName, projectHash === "new" ? "" : projectHash, team.id, user.access_token, fileID); - if (response && - response.createdbdeployment && - response.createdbdeployment.data) { - const { deployment_id, project_hash } = response.createdbdeployment.data; - // store the deployment id in the store - store.set("deployment_id", deployment_id); - store.set("project_hash", project_hash); - } - console.log("> Deployment submitted successfully..."); - } - catch (error) { - console.log("> Failed to create deployment:", error.response.errors || error); - } - // unlinkSync(filepath); - }); - exports.upload = upload; -}); diff --git a/packages/bolt/build/helpers/deploy/deploy/auth.d.ts b/packages/bolt/build/helpers/deploy/deployment/auth.d.ts similarity index 65% rename from packages/bolt/build/helpers/deploy/deploy/auth.d.ts rename to packages/bolt/build/helpers/deploy/deployment/auth.d.ts index c4d1688..0d1dbb7 100644 --- a/packages/bolt/build/helpers/deploy/deploy/auth.d.ts +++ b/packages/bolt/build/helpers/deploy/deployment/auth.d.ts @@ -1,2 +1,5 @@ import Store from "../../../libraries/store"; -export declare const auth: (doAuth: boolean, store: Store) => Promise; +export declare const auth: (doAuth: boolean, store: Store) => Promise<{ + user: any; + projects: any; +} | undefined>; diff --git a/packages/bolt/build/helpers/deploy/deployment/auth.js b/packages/bolt/build/helpers/deploy/deployment/auth.js new file mode 100644 index 0000000..3f55ff9 --- /dev/null +++ b/packages/bolt/build/helpers/deploy/deployment/auth.js @@ -0,0 +1,90 @@ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + 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) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports", "axios", "../../../config", "../../exit-with-msg"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.auth = void 0; + const inquirer = require("inquirer"); + const axios_1 = __importDefault(require("axios")); + const config_1 = require("../../../config"); + const exit_with_msg_1 = require("../../exit-with-msg"); + const auth = (doAuth, store) => __awaiter(void 0, void 0, void 0, function* () { + var _a, _b, _c, _d, _e; + try { + const creds = { + access_key: store.get("access_key"), + secret_key: store.get("secret_key"), + }; + // prompts to collect credentials from users + if (doAuth || !creds.access_key || !creds.secret_key) { + const results = yield inquirer.prompt([ + { + name: "access_key", + message: "Please enter your access key", + type: "input", + }, + { + name: "secret_key", + message: "Please enter your secret key", + type: "input", + }, + ]); + creds.access_key = results.access_key; + creds.secret_key = results.secret_key; + // store credentials in the store + store.set("access_key", results.access_key); + store.set("secret_key", results.secret_key); + } + // authenticate user + const { data } = yield axios_1.default.request({ + method: "POST", + url: `${config_1.BOX_SERVER_URL}/deployment/login`, + data: JSON.stringify(creds), + headers: { + "Content-Type": "application/json", + }, + }); + if (!data.success) { + yield (0, exit_with_msg_1.exitWithMsg)("Error authenticating user"); + } + // check if user is blocker + if ((_b = (_a = data.data) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.is_blocked) { + yield (0, exit_with_msg_1.exitWithMsg)("User is blocked"); + } + const userData = (_c = data.data) === null || _c === void 0 ? void 0 : _c.user; + const projects = (_e = (_d = data.data) === null || _d === void 0 ? void 0 : _d.user) === null || _e === void 0 ? void 0 : _e.projects; + // Delete projects from userData object without updating data.data.user.projects + delete userData.projects; + // remove projects from the userData object + // store user details in the store + store.set("user", userData || ""); + store.save(); + return { + user: userData, + projects: projects, + }; + } + catch (error) { + yield (0, exit_with_msg_1.exitWithMsg)("Error authenticating user"); + } + }); + exports.auth = auth; +}); diff --git a/packages/bolt/build/helpers/deploy/deployment/deploy.d.ts b/packages/bolt/build/helpers/deploy/deployment/deploy.d.ts new file mode 100644 index 0000000..b24178d --- /dev/null +++ b/packages/bolt/build/helpers/deploy/deployment/deploy.d.ts @@ -0,0 +1,5 @@ +export declare const deploy: ({ fileId, projectId, userId, }: { + fileId: number; + projectId: number; + userId: number; +}) => Promise; diff --git a/packages/bolt/build/helpers/deploy/deployment/deploy.js b/packages/bolt/build/helpers/deploy/deployment/deploy.js new file mode 100644 index 0000000..e41200a --- /dev/null +++ b/packages/bolt/build/helpers/deploy/deployment/deploy.js @@ -0,0 +1,50 @@ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + 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) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports", "../../exit-with-msg", "../apis/api-request"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.deploy = void 0; + const exit_with_msg_1 = require("../../exit-with-msg"); + const api_request_1 = require("../apis/api-request"); + const deploy = ({ fileId, projectId, userId, }) => __awaiter(void 0, void 0, void 0, function* () { + // submits the deployment + try { + const { data } = yield (0, api_request_1.apiRequest)({ + method: "POST", + data: { + file_id: fileId, + project_id: projectId, + user_id: userId, + }, + route: "/deploy", + headers: { + "Content-Type": "application/json", + }, + }); + if (!data || !data.success || !data.data.id) { + (0, exit_with_msg_1.exitWithMsg)("> Failed to create deployment:", data); + } + return data.data; + } + catch (error) { + console.log("Error", error); + yield (0, exit_with_msg_1.exitWithMsg)("Error creating deployment!"); + } + }); + exports.deploy = deploy; +}); diff --git a/packages/bolt/build/helpers/deploy/deployment/index.d.ts b/packages/bolt/build/helpers/deploy/deployment/index.d.ts new file mode 100644 index 0000000..37e7e29 --- /dev/null +++ b/packages/bolt/build/helpers/deploy/deployment/index.d.ts @@ -0,0 +1,6 @@ +export * from "./auth"; +export * from "./upload"; +export * from "./zip"; +export * from "./watch"; +export * from "./setProject"; +export * from "./deploy"; diff --git a/packages/bolt/build/helpers/deploy/deploy/index.js b/packages/bolt/build/helpers/deploy/deployment/index.js similarity index 89% rename from packages/bolt/build/helpers/deploy/deploy/index.js rename to packages/bolt/build/helpers/deploy/deployment/index.js index 91e7a93..b296332 100644 --- a/packages/bolt/build/helpers/deploy/deploy/index.js +++ b/packages/bolt/build/helpers/deploy/deployment/index.js @@ -18,7 +18,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) { if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { - define(["require", "exports", "./auth", "./upload", "./zip", "./watch"], factory); + define(["require", "exports", "./auth", "./upload", "./zip", "./watch", "./setProject", "./deploy"], factory); } })(function (require, exports) { "use strict"; @@ -27,4 +27,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) { __exportStar(require("./upload"), exports); __exportStar(require("./zip"), exports); __exportStar(require("./watch"), exports); + __exportStar(require("./setProject"), exports); + __exportStar(require("./deploy"), exports); }); diff --git a/packages/bolt/build/helpers/deploy/deployment/setProject.d.ts b/packages/bolt/build/helpers/deploy/deployment/setProject.d.ts new file mode 100644 index 0000000..c8e600d --- /dev/null +++ b/packages/bolt/build/helpers/deploy/deployment/setProject.d.ts @@ -0,0 +1 @@ +export declare const setProject: (projects: any[]) => Promise; diff --git a/packages/bolt/build/helpers/deploy/deployment/setProject.js b/packages/bolt/build/helpers/deploy/deployment/setProject.js new file mode 100644 index 0000000..f92e367 --- /dev/null +++ b/packages/bolt/build/helpers/deploy/deployment/setProject.js @@ -0,0 +1,102 @@ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + 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) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports", "../../exit-with-msg", "../../get-store-data", "../apis/api-request"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.setProject = void 0; + const exit_with_msg_1 = require("../../exit-with-msg"); + const get_store_data_1 = require("../../get-store-data"); + const api_request_1 = require("../apis/api-request"); + const inquirer = require("inquirer"); + const setProject = (projects) => __awaiter(void 0, void 0, void 0, function* () { + try { + const choices = [{ name: "Create a new Project", value: "create" }]; + if (projects.length) { + choices.push({ name: "Select a project", value: "select" }); + } + const user = yield (0, get_store_data_1.getStoreData)("user"); + if (!user.id) { + yield (0, exit_with_msg_1.exitWithMsg)("Error setting action for project Creation!"); + } + const result = yield inquirer.prompt([ + { + type: "list", + name: "action", + message: "Please choose an existing project or create one", + choices: choices, + }, + ]); + if (!result || !result.action) { + yield (0, exit_with_msg_1.exitWithMsg)("Error setting action for project Creation!"); + return; + } + switch (result.action) { + case "create": + const createPrompt = yield inquirer.prompt([ + { + type: "input", + name: "name", + message: "Please enter a name for the project", + }, + ]); + const body = { + project_name: createPrompt.name, + created_by: user.id, + }; + const { data } = yield (0, api_request_1.apiRequest)({ + method: "POST", + data: body, + route: "/projects", + headers: { + "Content-Type": "application/json", + }, + }); + if (!data || !data.success || !data.data.project) { + console.log({ data }); + yield (0, exit_with_msg_1.exitWithMsg)("Error creating project!"); + } + const project = data.data.project; + delete project.user; + return project; + break; + case "select": + const choices = projects.map((project) => { + return { name: project.name, value: project }; + }); + const selectPrompt = yield inquirer.prompt([ + { + type: "list", + name: "selectedProject", + message: "Please choose an existing project or create one", + choices: choices, + }, + ]); + return selectPrompt.selectedProject; + break; + default: + yield (0, exit_with_msg_1.exitWithMsg)("Error setting action for project Creation!"); + } + return result; + } + catch (error) { + console.log({ error: error.response.data || "nothing" }); + yield (0, exit_with_msg_1.exitWithMsg)("Error While Project Selection!"); + } + }); + exports.setProject = setProject; +}); diff --git a/packages/bolt/build/helpers/deploy/deploy/upload.d.ts b/packages/bolt/build/helpers/deploy/deployment/upload.d.ts similarity index 87% rename from packages/bolt/build/helpers/deploy/deploy/upload.d.ts rename to packages/bolt/build/helpers/deploy/deployment/upload.d.ts index 6d2803c..8c93acd 100644 --- a/packages/bolt/build/helpers/deploy/deploy/upload.d.ts +++ b/packages/bolt/build/helpers/deploy/deployment/upload.d.ts @@ -1,2 +1,2 @@ import Store from "../../../libraries/store"; -export declare const upload: (filepath: string, store: Store) => Promise; +export declare const upload: (filepath: string, store: Store) => Promise; diff --git a/packages/bolt/build/helpers/deploy/deployment/upload.js b/packages/bolt/build/helpers/deploy/deployment/upload.js new file mode 100644 index 0000000..0a2ad8f --- /dev/null +++ b/packages/bolt/build/helpers/deploy/deployment/upload.js @@ -0,0 +1,55 @@ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + 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) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports", "fs", "form-data", "../apis/api-request"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.upload = void 0; + const fs_1 = require("fs"); + const inquirer = require("inquirer"); + const form_data_1 = __importDefault(require("form-data")); + const api_request_1 = require("../apis/api-request"); + const upload = (filepath, store) => __awaiter(void 0, void 0, void 0, function* () { + // upload the project zip file to minio + try { + const form = new form_data_1.default(); + form.append("file", (0, fs_1.createReadStream)(filepath)); + const { data } = yield (0, api_request_1.apiRequest)({ + method: "POST", + route: "/upload", + data: form, + headers: Object.assign({}, form.getHeaders()), + }); + if (!data.success || !data.data || !data.data.id) { + console.error("Error uploading the project zip file to minio"); + process.exit(1); + } + const fileId = data.data.id; + (0, fs_1.unlinkSync)(filepath); + return fileId; + } + catch (error) { + console.log("> Uploading failed due to following reason:", error.message || error); + console.log(error); + process.exit(-1); + } + }); + exports.upload = upload; +}); diff --git a/packages/bolt/build/helpers/deploy/deploy/watch.d.ts b/packages/bolt/build/helpers/deploy/deployment/watch.d.ts similarity index 100% rename from packages/bolt/build/helpers/deploy/deploy/watch.d.ts rename to packages/bolt/build/helpers/deploy/deployment/watch.d.ts diff --git a/packages/bolt/build/helpers/deploy/deploy/watch.js b/packages/bolt/build/helpers/deploy/deployment/watch.js similarity index 100% rename from packages/bolt/build/helpers/deploy/deploy/watch.js rename to packages/bolt/build/helpers/deploy/deployment/watch.js diff --git a/packages/bolt/build/helpers/deploy/deploy/zip.d.ts b/packages/bolt/build/helpers/deploy/deployment/zip.d.ts similarity index 100% rename from packages/bolt/build/helpers/deploy/deploy/zip.d.ts rename to packages/bolt/build/helpers/deploy/deployment/zip.d.ts diff --git a/packages/bolt/build/helpers/deploy/deploy/zip.js b/packages/bolt/build/helpers/deploy/deployment/zip.js similarity index 78% rename from packages/bolt/build/helpers/deploy/deploy/zip.js rename to packages/bolt/build/helpers/deploy/deployment/zip.js index 0cccc6c..997f915 100644 --- a/packages/bolt/build/helpers/deploy/deploy/zip.js +++ b/packages/bolt/build/helpers/deploy/deployment/zip.js @@ -52,8 +52,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) { const file_exists_1 = require("../file-exists"); const readline = __importStar(require("readline")); const zip = (project_path) => __awaiter(void 0, void 0, void 0, function* () { - const filename = 'output.zip'; - const directory = (0, path_1.join)(project_path, '.deploy'); + const filename = `${(0, path_1.basename)(process.cwd())}.zip`; + const directory = (0, path_1.join)(project_path, ".deploy"); const zipPath = (0, path_1.join)(directory, filename); if (!(yield (0, file_exists_1.fileExists)(directory))) { (0, fs_1.mkdirSync)(directory, { recursive: true }); @@ -61,27 +61,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) { const promise = new Promise((resolve, reject) => { // create a file to stream archive data to. const output = (0, fs_1.createWriteStream)(zipPath); - const archive = (0, archiver_1.default)('zip', { - zlib: { level: 9 } // Sets the compression level. + const archive = (0, archiver_1.default)("zip", { + zlib: { level: 9 }, // Sets the compression level. }); // listen for all archive data to be written // 'close' event is fired only when a file descriptor is involved - output.on('close', () => { + output.on("close", () => { readline.clearLine(process.stdout, 0); readline.cursorTo(process.stdout, 0); - process.stdout.write(`> Compressed ${(0, format_bytes_1.formatBytes)(archive.pointer())} into "${filename}"!`); + process.stdout.write(`>> Compressed ${(0, format_bytes_1.formatBytes)(archive.pointer())} into "${filename}"!`); console.log(); resolve(zipPath); }); - archive.on('progress', (progress) => { + archive.on("progress", (progress) => { readline.clearLine(process.stdout, 0); readline.cursorTo(process.stdout, 0); - process.stdout.write(`> In progress: processed ${progress.entries.processed} files & ${(0, format_bytes_1.formatBytes)(progress.fs.processedBytes)} of data`); + process.stdout.write(`>> In progress: processed ${progress.entries.processed} files & ${(0, format_bytes_1.formatBytes)(progress.fs.processedBytes)} of data`); }); // good practice to catch warnings (ie stat failures and other non-blocking errors) - archive.on('warning', (err) => { - console.log('> Warning:', err); - if (err.code === 'ENOENT') { + archive.on("warning", (err) => { + console.log("> Warning:", err); + if (err.code === "ENOENT") { // log warning } else { @@ -92,30 +92,30 @@ var __importDefault = (this && this.__importDefault) || function (mod) { // This event is fired when the data source is drained no matter what was the data source. // It is not part of this library but rather from the NodeJS Stream API. // @see: https://nodejs.org/api/stream.html#stream_event_end - output.on('end', () => { - console.log('Data has been drained'); + output.on("end", () => { + console.log("Data has been drained"); }); // good practice to catch this error explicitly - archive.on('error', (err) => { + archive.on("error", (err) => { reject(err); }); // pipe archive data to the file archive.pipe(output); // append files from a glob pattern - archive.glob('**', { + archive.glob("**", { ignore: [ - '**/storage/**/data/**', - '**/databases/**/db/**', - 'node_modules/*', - '**/node_modules/**', - '**/.DS_Store', - '.git/**', - '**/*.zip', - '.deploy', - '**/.next/**', + "**/storage/**/data/**", + "**/databases/**/db/**", + "node_modules/*", + "**/node_modules/**", + "**/.DS_Store", + ".git/**", + "**/*.zip", + ".deploy", + "**/.next/**", ], cwd: project_path, - dot: true + dot: true, }); // finalize the archive (ie we are done appending files but streams have to finish yet) // 'close', 'end' or 'finish' may be fired right after calling this method so register to them beforehand diff --git a/packages/bolt/build/index.js b/packages/bolt/build/index.js old mode 100644 new mode 100755 diff --git a/packages/bolt/build/runners/service/docker.js b/packages/bolt/build/runners/service/docker.js index 380f575..3b20daa 100644 --- a/packages/bolt/build/runners/service/docker.js +++ b/packages/bolt/build/runners/service/docker.js @@ -58,6 +58,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge console.log(">> Initiaiting Docker run..."); const args = [ "run", + "--rm", "--detach", "--name", this.container_name, diff --git a/packages/bolt/src/actions/deploy/deploy.ts b/packages/bolt/src/actions/deploy/deploy.ts index ae0da83..cef3162 100644 --- a/packages/bolt/src/actions/deploy/deploy.ts +++ b/packages/bolt/src/actions/deploy/deploy.ts @@ -1,6 +1,13 @@ import getStore from "../../helpers/get-store"; import { BoltService } from "../../typings/bolt-service"; -import { auth, upload, zip, watch } from "../../helpers/deploy/deploy"; +import { + auth, + upload, + zip, + watch, + setProject, + deploy, +} from "../../helpers/deploy/deployment"; import Common from "../../common"; export default class DeployClass { @@ -21,7 +28,7 @@ export default class DeployClass { this.store.save(); } - async getSealContent() { + async getBoltFileContent() { const _yamlContent = await Common.getAndValidateBoltYaml(); return _yamlContent; } @@ -29,7 +36,7 @@ export default class DeployClass { // populate services async setServices() { const services: BoltService[] = this.services; - const _yamlContent = await this.getSealContent(); + const _yamlContent = await this.getBoltFileContent(); // Gather all the availables services for await (const [serviceName] of Object.entries(_yamlContent.services)) { const { content } = await Common.getAndValidateService( @@ -51,15 +58,33 @@ export default class DeployClass { return Promise.resolve(zipPath); } - // Authenticates users credentials and - // stores the details into the project's store async auth(doAuth: boolean) { - await auth(doAuth, this.store); + return await auth(doAuth, this.store); + } + + async setProject(projects: any[]) { + return await setProject(projects); } // uploads the zip into minio async upload() { - await upload(this.zipPath, this.store); + return await upload(this.zipPath, this.store); + } + + async submit({ + projectId, + fileId, + userId, + }: { + projectId: number; + fileId: number; + userId: number; + }) { + return await deploy({ + projectId, + fileId, + userId, + }); } // watches the deployment steps async watch() { diff --git a/packages/bolt/src/actions/deploy/index.ts b/packages/bolt/src/actions/deploy/index.ts index 0935aad..633b8d1 100644 --- a/packages/bolt/src/actions/deploy/index.ts +++ b/packages/bolt/src/actions/deploy/index.ts @@ -1,32 +1,33 @@ import chalk from "chalk"; import EnvGenerate from "../../actions/env-generate"; +import { exitWithMsg } from "../../helpers/exit-with-msg"; import { validateMetadata } from "../../helpers/validate-metadata"; import { validateServices } from "../../helpers/validate-services"; import RouteGenerate from "../route-generate"; import DeployClass from "./deploy"; export default async (options: any, isWatch: boolean = false) => { + // validate the project + console.log(">> Validating project..."); + await validateMetadata(); + await validateServices(); + console.log(chalk.gray(">> Building Production Envs...")); const envGenerate = new EnvGenerate(); await envGenerate.handle({ environment: "production" }); + console.log(chalk.green(">> Production Envs built successfully!") + "\n"); const routeGenerate = new RouteGenerate(); await routeGenerate.handle(true); - return; - // validate the project - console.log(">> Validating project..."); - await validateMetadata(); - await validateServices(); - console.log( - "\n> Note: Please remove any zip file or unnecessary files/folders from your project before deploying!" + "\n>> Note: Please remove any zip file or unnecessary files/folders from your project before deploying!" ); - console.log("\n> Deploying project..."); + console.log("\n>> Deploying project..."); const deploy = new DeployClass(); - console.log("\n> Gathering all deployable services..."); + console.log("\n>> Gathering all deployable services..."); // populate store await deploy.setStore(); @@ -47,19 +48,30 @@ export default async (options: any, isWatch: boolean = false) => { // authenticate the user & store creds in local store console.log("\n>> Authenticating user credentials..."); - await deploy.auth(options.auth); + const authData = await deploy.auth(options.auth); console.log(">> Authentication successful!\n"); + const projects = authData?.projects || []; + const selectedProject = await deploy.setProject(projects); + // uploads the project zip file to minio console.log(">> Uploading project zip file..."); - await deploy.upload(); + const fileId = await deploy.upload(); console.log(">> Project zip file uploaded successfully!\n"); - // save store - await deploy.saveStore(); + console.log(">> Submitting the deployment now..."); + const deployment = await deploy.submit({ + fileId, + projectId: selectedProject.id, + userId: authData?.user?.id, + }); + console.log(">> Deployment submitted successfully!\n"); - if (isWatch) { - console.log(">> Fetching deployment details...\n"); - await deploy.watch(); - } + // // save store + // await deploy.saveStore(); + + // if (isWatch) { + // console.log(">> Fetching deployment details...\n"); + // await deploy.watch(); + // } }; diff --git a/packages/bolt/src/commands/13-deploy.ts b/packages/bolt/src/commands/13-deploy.ts index 57f8c57..1b1fd10 100644 --- a/packages/bolt/src/commands/13-deploy.ts +++ b/packages/bolt/src/commands/13-deploy.ts @@ -11,8 +11,6 @@ export default async (program: any) => { ) .description("Prepares the compressed project & initiates the deployment") .action((options: any) => { - console.log(chalk.green(">> Coming Soon...")); - process.exit(); // deploy(options, true); }); }; diff --git a/packages/bolt/src/config/index.ts b/packages/bolt/src/config/index.ts index 911fef3..f3ed477 100644 --- a/packages/bolt/src/config/index.ts +++ b/packages/bolt/src/config/index.ts @@ -1,9 +1,11 @@ /** * SEAL server details */ -export const SEAL_DOMAIN: string = 'https://api.gluestack.io'; +// export const SEAL_DOMAIN: string = "https://api.gluestack.io"; /** * SEAL GQL service details */ -export const SEAL_GQL: string = 'https://api.gluestack.io/backend/graphql'; +// export const SEAL_GQL: string = "https://api.gluestack.io/backend/graphql"; + +export const BOX_SERVER_URL: string = "http://localhost:8000/api"; diff --git a/packages/bolt/src/helpers/deploy/apis/api-request.ts b/packages/bolt/src/helpers/deploy/apis/api-request.ts new file mode 100644 index 0000000..39bd6c7 --- /dev/null +++ b/packages/bolt/src/helpers/deploy/apis/api-request.ts @@ -0,0 +1,45 @@ +import { getStoreData } from "../../get-store-data"; +import axios from "axios"; +import { BOX_SERVER_URL } from "../../../config"; + +export const apiRequest = async ({ + data, + method, + route, + params, + headers, +}: { + data: any; + method: "GET" | "POST" | "PUT" | "DELETE"; + route: string; + params?: any; + headers?: any; +}) => { + const accessKey: string = await getStoreData("access_key"); + const secretKey: string = await getStoreData("secret_key"); + + const requestHeaders = { + ["Access-Key"]: accessKey, + ["Secret-Key"]: secretKey, + ...headers, + }; + + params = params ? getParamString(params) : ""; + + const config: any = { + method: method, + url: `${BOX_SERVER_URL}/deployment${route}${params}`, + headers: requestHeaders, + data: data, + }; + + return await axios.request(config); +}; + +const getParamString = (params: any) => { + let paramString = "?"; + for (const [key, value] of Object.entries(params)) { + paramString += `${key}=${value}&`; + } + return paramString; +}; diff --git a/packages/bolt/src/helpers/deploy/apis/client.ts b/packages/bolt/src/helpers/deploy/apis/client.ts index f5692f8..6b5a102 100644 --- a/packages/bolt/src/helpers/deploy/apis/client.ts +++ b/packages/bolt/src/helpers/deploy/apis/client.ts @@ -1,7 +1,6 @@ -import { GraphQLClient } from 'graphql-request'; -import { SEAL_GQL } from '../../../config'; +import { GraphQLClient } from "graphql-request"; +import { BOX_SERVER_URL } from "../../../config"; -export const clientGQL = new GraphQLClient(SEAL_GQL); +export const clientGQL = new GraphQLClient(BOX_SERVER_URL); - -export { request, gql } from 'graphql-request'; +export { request, gql } from "graphql-request"; diff --git a/packages/bolt/src/helpers/deploy/deploy/auth.ts b/packages/bolt/src/helpers/deploy/deploy/auth.ts deleted file mode 100644 index 122d3ee..0000000 --- a/packages/bolt/src/helpers/deploy/deploy/auth.ts +++ /dev/null @@ -1,57 +0,0 @@ -const inquirer = require("inquirer"); -import { SEAL_DOMAIN } from "../../../config"; -import { Glue } from "@gluestack/glue-server-sdk-js"; -import Store from "../../../libraries/store"; - -export const auth = async (doAuth: boolean, store: Store) => { - const creds = { - email: store.get("email"), - password: store.get("password"), - }; - - // prompts to collect credentials from users - if (doAuth || !creds.email || !creds.password) { - const results = await inquirer.prompt([ - { - name: "email", - message: "Please enter your email", - type: "input", - }, - { - name: "password", - message: "Please enter your password", - type: "password", - }, - ]); - - creds.email = results.email; - creds.password = results.password; - - // store credentials in the store - store.set("email", results.email); - store.set("password", results.password); - } - - const glue = new Glue(SEAL_DOMAIN); - const response = await glue.auth.login({ ...creds, role: "owner" }); - if (!response || !response.id) { - console.log(`>> Authentication failed. Message: ${response}`); - process.exit(-1); - } - if (!response.is_verified) { - console.log(`>> Authentication failed. Message: Account is not verified`); - process.exit(-1); - } - if (response.status === "on_waitlist") { - console.log(`>> Authentication failed. User is on waitlist`); - process.exit(-1); - } - - // store user data in the store - store.set("team", response.team); - delete response.team; - store.set("user", response); - - // save store - store.save(); -}; diff --git a/packages/bolt/src/helpers/deploy/deploy/index.ts b/packages/bolt/src/helpers/deploy/deploy/index.ts deleted file mode 100644 index 545d7ca..0000000 --- a/packages/bolt/src/helpers/deploy/deploy/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './auth'; -export * from './upload'; -export * from './zip'; -export * from './watch'; diff --git a/packages/bolt/src/helpers/deploy/deploy/upload.ts b/packages/bolt/src/helpers/deploy/deploy/upload.ts deleted file mode 100644 index c469435..0000000 --- a/packages/bolt/src/helpers/deploy/deploy/upload.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { createReadStream, unlinkSync } from "fs"; -import Store from "../../../libraries/store"; -import { SEAL_DOMAIN } from "../../../config"; -import { projects } from "../apis/handlers/gql"; -import { Glue } from "@gluestack/glue-server-sdk-js"; -import { createDeployment } from "../apis/handlers/gql/create-deployment"; - -const inquirer = require("inquirer"); - -export const upload = async (filepath: string, store: Store) => { - let projectHash = store.get("project_hash"); - - // prompts to collect Project ID from user - if (!projectHash || projectHash === "new") { - const team = store.get("team"); - let tmp: any; - try { - tmp = await projects(team.id, team.token); - } catch (err) { - console.log(err); - - console.log("> Error fetching projects... Please try again later."); - process.exit(-1); - } - - // transform key-value pairs - const choices: any = [{ name: "Create a new Project", value: "new" }]; - choices.push( - ...tmp.projects.map((project: any) => { - return { name: project.name, value: project.project_hash }; - }) - ); - - // prompt to collect right project from user - const results = await inquirer.prompt([ - { - name: "projectHash", - message: "Please choose an existing project or create one", - type: "list", - choices: choices, - }, - ]); - - if (!results || !results.projectHash) { - console.error("> Error collecting project id"); - process.exit(-1); - } - - // store project id in the store - projectHash = results.projectHash; - store.set("project_hash", results.projectHash); - } - - // upload the project zip file to minio - const glue = new Glue(SEAL_DOMAIN); - try { - const response = await glue.storage.upload(createReadStream(filepath)); - - if (response && !response.id) { - console.error("Error uploading the project zip file to minio"); - process.exit(1); - } - - store.set("file_id", response.id); - console.log("> File uploaded successfully..."); - } catch (error: any) { - console.log( - "> Uploading failed due to following reason:", - error.message || error - ); - console.log(error); - process.exit(-1); - } - - // submits the deployment - console.log("> Submitting the deployment now..."); - try { - const user = store.get("user"); - const team = store.get("team"); - const fileID = store.get("file_id"); - const projectHash = store.get("project_hash"); - const projectName: string = process.cwd().split("/")[ - process.cwd().split("/").length - 1 - ]; - - const response: any = await createDeployment( - projectName, - projectHash === "new" ? "" : projectHash, - team.id, - user.access_token, - fileID - ); - - if ( - response && - response.createdbdeployment && - response.createdbdeployment.data - ) { - const { deployment_id, project_hash } = response.createdbdeployment.data; - - // store the deployment id in the store - store.set("deployment_id", deployment_id); - store.set("project_hash", project_hash); - } - console.log("> Deployment submitted successfully..."); - } catch (error: any) { - console.log( - "> Failed to create deployment:", - error.response.errors || error - ); - } - - // unlinkSync(filepath); -}; diff --git a/packages/bolt/src/helpers/deploy/deployment/auth.ts b/packages/bolt/src/helpers/deploy/deployment/auth.ts new file mode 100644 index 0000000..2c751de --- /dev/null +++ b/packages/bolt/src/helpers/deploy/deployment/auth.ts @@ -0,0 +1,74 @@ +const inquirer = require("inquirer"); +import axios from "axios"; +import { BOX_SERVER_URL } from "../../../config"; +import Store from "../../../libraries/store"; +import { exitWithMsg } from "../../exit-with-msg"; + +export const auth = async (doAuth: boolean, store: Store) => { + try { + const creds = { + access_key: store.get("access_key"), + secret_key: store.get("secret_key"), + }; + + // prompts to collect credentials from users + if (doAuth || !creds.access_key || !creds.secret_key) { + const results = await inquirer.prompt([ + { + name: "access_key", + message: "Please enter your access key", + type: "input", + }, + { + name: "secret_key", + message: "Please enter your secret key", + type: "input", + }, + ]); + + creds.access_key = results.access_key; + creds.secret_key = results.secret_key; + + // store credentials in the store + store.set("access_key", results.access_key); + store.set("secret_key", results.secret_key); + } + + // authenticate user + const { data } = await axios.request({ + method: "POST", + url: `${BOX_SERVER_URL}/deployment/login`, + data: JSON.stringify(creds), + headers: { + "Content-Type": "application/json", + }, + }); + + if (!data.success) { + await exitWithMsg("Error authenticating user"); + } + + // check if user is blocker + if (data.data?.user?.is_blocked) { + await exitWithMsg("User is blocked"); + } + + const userData = data.data?.user; + const projects = data.data?.user?.projects; + // Delete projects from userData object without updating data.data.user.projects + delete userData.projects; + + // remove projects from the userData object + + // store user details in the store + store.set("user", userData || ""); + store.save(); + + return { + user: userData, + projects: projects, + }; + } catch (error: any) { + await exitWithMsg("Error authenticating user"); + } +}; diff --git a/packages/bolt/src/helpers/deploy/deployment/deploy.ts b/packages/bolt/src/helpers/deploy/deployment/deploy.ts new file mode 100644 index 0000000..e2d8187 --- /dev/null +++ b/packages/bolt/src/helpers/deploy/deployment/deploy.ts @@ -0,0 +1,36 @@ +import { exitWithMsg } from "../../exit-with-msg"; +import { apiRequest } from "../apis/api-request"; + +export const deploy = async ({ + fileId, + projectId, + userId, +}: { + fileId: number; + projectId: number; + userId: number; +}) => { + // submits the deployment + try { + const { data } = await apiRequest({ + method: "POST", + data: { + file_id: fileId, + project_id: projectId, + user_id: userId, + }, + route: "/deploy", + headers: { + "Content-Type": "application/json", + }, + }); + if (!data || !data.success || !data.data.id) { + exitWithMsg("> Failed to create deployment:", data); + } + + return data.data; + } catch (error: any) { + console.log("Error", error); + await exitWithMsg("Error creating deployment!"); + } +}; diff --git a/packages/bolt/src/helpers/deploy/deployment/index.ts b/packages/bolt/src/helpers/deploy/deployment/index.ts new file mode 100644 index 0000000..37e7e29 --- /dev/null +++ b/packages/bolt/src/helpers/deploy/deployment/index.ts @@ -0,0 +1,6 @@ +export * from "./auth"; +export * from "./upload"; +export * from "./zip"; +export * from "./watch"; +export * from "./setProject"; +export * from "./deploy"; diff --git a/packages/bolt/src/helpers/deploy/deployment/setProject.ts b/packages/bolt/src/helpers/deploy/deployment/setProject.ts new file mode 100644 index 0000000..3525bdc --- /dev/null +++ b/packages/bolt/src/helpers/deploy/deployment/setProject.ts @@ -0,0 +1,87 @@ +import { exitWithMsg } from "../../exit-with-msg"; +import { getStoreData } from "../../get-store-data"; +import { apiRequest } from "../apis/api-request"; + +const inquirer = require("inquirer"); + +export const setProject = async (projects: any[]) => { + try { + const choices: any = [{ name: "Create a new Project", value: "create" }]; + if (projects.length) { + choices.push({ name: "Select a project", value: "select" }); + } + + const user = await getStoreData("user"); + + if (!user.id) { + await exitWithMsg("Error setting action for project Creation!"); + } + + const result = await inquirer.prompt([ + { + type: "list", + name: "action", + message: "Please choose an existing project or create one", + choices: choices, + }, + ]); + + if (!result || !result.action) { + await exitWithMsg("Error setting action for project Creation!"); + return; + } + switch (result.action) { + case "create": + const createPrompt = await inquirer.prompt([ + { + type: "input", + name: "name", + message: "Please enter a name for the project", + }, + ]); + + const body = { + project_name: createPrompt.name, + created_by: user.id, + }; + + const { data } = await apiRequest({ + method: "POST", + data: body, + route: "/projects", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!data || !data.success || !data.data.project) { + console.log({ data }); + await exitWithMsg("Error creating project!"); + } + const project = data.data.project; + delete project.user; + return project; + break; + case "select": + const choices = projects.map((project: any) => { + return { name: project.name, value: project }; + }); + const selectPrompt = await inquirer.prompt([ + { + type: "list", + name: "selectedProject", + message: "Please choose an existing project or create one", + choices: choices, + }, + ]); + return selectPrompt.selectedProject; + break; + default: + await exitWithMsg("Error setting action for project Creation!"); + } + return result; + } catch (error: any) { + console.log({ error: error.response.data || "nothing" }); + await exitWithMsg("Error While Project Selection!"); + } +}; diff --git a/packages/bolt/src/helpers/deploy/deployment/upload.ts b/packages/bolt/src/helpers/deploy/deployment/upload.ts new file mode 100644 index 0000000..c5629eb --- /dev/null +++ b/packages/bolt/src/helpers/deploy/deployment/upload.ts @@ -0,0 +1,41 @@ +import { createReadStream, unlinkSync } from "fs"; +import Store from "../../../libraries/store"; +import { createDeployment } from "../apis/handlers/gql/create-deployment"; +import axios from "axios"; +import { BOX_SERVER_URL } from "../../../config"; +const inquirer = require("inquirer"); +import FormData from "form-data"; +import { apiRequest } from "../apis/api-request"; + +export const upload = async (filepath: string, store: Store) => { + // upload the project zip file to minio + try { + const form = new FormData(); + form.append("file", createReadStream(filepath)); + + const { data } = await apiRequest({ + method: "POST", + route: "/upload", + data: form, + headers: { + ...form.getHeaders(), + }, + }); + + if (!data.success || !data.data || !data.data.id) { + console.error("Error uploading the project zip file to minio"); + process.exit(1); + } + + const fileId = data.data.id; + unlinkSync(filepath); + return fileId; + } catch (error: any) { + console.log( + "> Uploading failed due to following reason:", + error.message || error + ); + console.log(error); + process.exit(-1); + } +}; diff --git a/packages/bolt/src/helpers/deploy/deploy/watch.ts b/packages/bolt/src/helpers/deploy/deployment/watch.ts similarity index 100% rename from packages/bolt/src/helpers/deploy/deploy/watch.ts rename to packages/bolt/src/helpers/deploy/deployment/watch.ts diff --git a/packages/bolt/src/helpers/deploy/deploy/zip.ts b/packages/bolt/src/helpers/deploy/deployment/zip.ts similarity index 55% rename from packages/bolt/src/helpers/deploy/deploy/zip.ts rename to packages/bolt/src/helpers/deploy/deployment/zip.ts index 4a22f87..b340b4d 100644 --- a/packages/bolt/src/helpers/deploy/deploy/zip.ts +++ b/packages/bolt/src/helpers/deploy/deployment/zip.ts @@ -1,16 +1,16 @@ -import { join } from 'path'; -import archiver from 'archiver'; -import { createWriteStream, mkdirSync } from 'fs'; -import { formatBytes } from '../format-bytes'; -import { fileExists } from '../file-exists'; +import { basename, join } from "path"; +import archiver from "archiver"; +import { createWriteStream, mkdirSync } from "fs"; +import { formatBytes } from "../format-bytes"; +import { fileExists } from "../file-exists"; import * as readline from "readline"; export const zip = async (project_path: string) => { - const filename = 'output.zip'; - const directory = join(project_path, '.deploy'); + const filename = `${basename(process.cwd())}.zip`; + const directory = join(project_path, ".deploy"); const zipPath = join(directory, filename); - if (!await fileExists(directory)) { + if (!(await fileExists(directory))) { mkdirSync(directory, { recursive: true }); } @@ -18,30 +18,36 @@ export const zip = async (project_path: string) => { // create a file to stream archive data to. const output = createWriteStream(zipPath); - const archive = archiver('zip', { - zlib: { level: 9 } // Sets the compression level. + const archive = archiver("zip", { + zlib: { level: 9 }, // Sets the compression level. }); // listen for all archive data to be written // 'close' event is fired only when a file descriptor is involved - output.on('close', () => { + output.on("close", () => { readline.clearLine(process.stdout, 0); readline.cursorTo(process.stdout, 0); - process.stdout.write(`> Compressed ${formatBytes(archive.pointer())} into "${filename}"!`); + process.stdout.write( + `>> Compressed ${formatBytes(archive.pointer())} into "${filename}"!` + ); console.log(); resolve(zipPath); }); - archive.on('progress', (progress) => { + archive.on("progress", (progress) => { readline.clearLine(process.stdout, 0); readline.cursorTo(process.stdout, 0); - process.stdout.write(`> In progress: processed ${progress.entries.processed} files & ${formatBytes(progress.fs.processedBytes)} of data`); + process.stdout.write( + `>> In progress: processed ${ + progress.entries.processed + } files & ${formatBytes(progress.fs.processedBytes)} of data` + ); }); // good practice to catch warnings (ie stat failures and other non-blocking errors) - archive.on('warning', (err) => { - console.log('> Warning:', err); - if (err.code === 'ENOENT') { + archive.on("warning", (err) => { + console.log("> Warning:", err); + if (err.code === "ENOENT") { // log warning } else { // throw error @@ -52,12 +58,12 @@ export const zip = async (project_path: string) => { // This event is fired when the data source is drained no matter what was the data source. // It is not part of this library but rather from the NodeJS Stream API. // @see: https://nodejs.org/api/stream.html#stream_event_end - output.on('end', () => { - console.log('Data has been drained'); + output.on("end", () => { + console.log("Data has been drained"); }); // good practice to catch this error explicitly - archive.on('error', (err: any) => { + archive.on("error", (err: any) => { reject(err); }); @@ -65,20 +71,20 @@ export const zip = async (project_path: string) => { archive.pipe(output); // append files from a glob pattern - archive.glob('**', { + archive.glob("**", { ignore: [ - '**/storage/**/data/**', - '**/databases/**/db/**', - 'node_modules/*', - '**/node_modules/**', - '**/.DS_Store', - '.git/**', - '**/*.zip', - '.deploy', - '**/.next/**', + "**/storage/**/data/**", + "**/databases/**/db/**", + "node_modules/*", + "**/node_modules/**", + "**/.DS_Store", + ".git/**", + "**/*.zip", + ".deploy", + "**/.next/**", ], cwd: project_path, - dot: true + dot: true, }); // finalize the archive (ie we are done appending files but streams have to finish yet) diff --git a/packages/bolt/test.js b/packages/bolt/test.js new file mode 100644 index 0000000..75aa10a --- /dev/null +++ b/packages/bolt/test.js @@ -0,0 +1,25 @@ +const axios = require("axios"); +let data = JSON.stringify({ + access_key: "f825b35e5d0f70d5b4b0e0f3ea35daadf9903d1f", + secret_key: + "c966f789b57625b10decabd811b525cc11735bc9a4d2f706b4c10693f0314257", +}); + +let config = { + method: "post", + maxBodyLength: Infinity, + url: "http://localhost:8000/api/deployment/login", + headers: { + "Content-Type": "application/json", + }, + data: data, +}; + +axios + .request(config) + .then((response) => { + console.log(JSON.stringify(response.data)); + }) + .catch((error) => { + console.log(error); + });