UNPKG

@aminya/dotenv-vault

Version:

A secrets manager for .env files – from the same people that pioneered dotenv.

152 lines (149 loc) 6.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NewService = void 0; const tslib_1 = require("tslib"); const crypto = tslib_1.__importStar(require("crypto")); const chalk_1 = tslib_1.__importDefault(require("chalk")); const axios_1 = tslib_1.__importDefault(require("axios")); const vars_1 = require("../vars"); const fs_1 = require("fs"); const core_1 = require("@oclif/core"); const append_to_ignore_service_1 = require("../services/append-to-ignore-service"); const log_service_1 = require("../services/log-service"); const abort_service_1 = require("../services/abort-service"); class NewService { constructor(attrs = {}) { this.cmd = attrs.cmd; this.dotenvVault = attrs.dotenvVault; this.yes = attrs.yes; this.log = new log_service_1.LogService({ cmd: attrs.cmd }); this.abort = new abort_service_1.AbortService({ cmd: attrs.cmd }); const rand = crypto.randomBytes(32).toString('hex'); this.requestUid = `req_${rand}`; this.checkCount = 0; } async run() { new append_to_ignore_service_1.AppendToIgnoreService().run(); // Step 1 if (vars_1.vars.missingEnvVault) { (0, fs_1.writeFileSync)(vars_1.vars.vaultFilename, this.vaultFileContent(` # Generate vault identifiers at ${this.url}`)); } // Step 2 B if (this.dotenvVault) { if (vars_1.vars.invalidVaultValue(this.dotenvVault)) { this.abort.invalidEnvVault(); } core_1.CliUx.ux.action.start(`${chalk_1.default.dim(this.log.pretextLocal)}Adding ${vars_1.vars.vaultFilename} (${vars_1.vars.vaultKey})`); await core_1.CliUx.ux.wait(1000); core_1.CliUx.ux.action.stop(); (0, fs_1.writeFileSync)(vars_1.vars.vaultFilename, this.vaultFileContent(this.dotenvVault)); this.log.local(`Added to ${vars_1.vars.vaultFilename} (${vars_1.vars.vaultKey}=${this.dotenvVault.slice(0, 9)}...)`); this.log.plain(''); this.log.plain(`Next run ${chalk_1.default.bold(`${vars_1.vars.cli} ${this.pushOrPullCommand}`)}`); // assumes dev started from UI (because prompted to enter existing dotenvVault uid) so recommend push or pull command instead of login return; } if (vars_1.vars.existingVaultValue) { this.abort.existingEnvVault(); } if (!this.yes) { this.log.local(`New project URL: ${this.urlWithProjectName}`); const answer = await core_1.CliUx.ux.prompt(`${chalk_1.default.dim(this.log.pretextLocal)}Press ${chalk_1.default.green('y')} (or any key) to open up the browser to create a new project vault (.env.vault) or ${chalk_1.default.yellow('q')} to exit`); if (answer === 'q' || answer === 'Q') { this.abort.quit(); } } this.log.local(`Opening browser to ${this.urlWithProjectName}`); core_1.CliUx.ux.open(this.urlWithProjectName).catch(_ => { }); core_1.CliUx.ux.action.start(`${chalk_1.default.dim(this.log.pretextLocal)}Waiting for project vault (.env.vault) to be created`); await this.check(); } async check() { if (this.controller) { this.controller.abort(); } this.controller = new AbortController(); const options = { method: 'POST', headers: { 'content-type': 'application/json' }, data: { requestUid: this.requestUid, }, url: this.checkUrl, signal: this.controller.signal, }; let resp; try { this.checkCount += 1; resp = await (0, axios_1.default)(options); } catch (error) { resp = error.response; } finally { if (resp.status < 300) { // Step 3 core_1.CliUx.ux.action.stop(); const vaultUid = resp.data.data.vaultUid; (0, fs_1.writeFileSync)(vars_1.vars.vaultFilename, this.vaultFileContent(vaultUid)); this.log.local(`Added to ${vars_1.vars.vaultFilename} (${vars_1.vars.vaultKey}=${vaultUid.slice(0, 9)}...)`); this.log.plain(''); this.log.plain(`Next run ${chalk_1.default.bold(`${vars_1.vars.cli} login`)}`); } else if (this.checkCount < 50) { // 404 - keep trying await core_1.CliUx.ux.wait(2000); // check every 2 seconds await this.check(); // check again } else { core_1.CliUx.ux.action.stop('giving up'); this.log.local('Things were taking too long... gave up. Please try again.'); } } } vaultFileContent(value) { const s = `${vars_1.vars.vaultFileHeaderComment} # # Hello 👋, # # Your environment variables will be encrypted and # safely stored in this .env.vault file, after you # run the login, push, and build commands. # # Next run: # # $ ${vars_1.vars.cli} login # # # You can safely commit this file to code. # # Enjoy. 🌴 # #/----------------settings/metadata-----------------/ ${vars_1.vars.vaultKey}="${value}" DOTENV_API_URL="${vars_1.vars.apiUrl}" DOTENV_CLI="${vars_1.vars.cli}" `; return s; } get url() { return vars_1.vars.apiUrl + '/new'; } get checkUrl() { return `${vars_1.vars.apiUrl}/vault`; } get urlWithProjectName() { const dir = process.cwd(); const splitDir = dir.split('\\').join('/').split('/'); // handle windows and unix paths const projectName = splitDir[splitDir.length - 1]; return `${this.url}?project_name=${projectName}&request_uid=${this.requestUid}`; } get pushOrPullCommand() { // tell dev to push if he already has a local .env file if ((0, fs_1.existsSync)('.env')) { return 'push'; } // otherwise tell him to pull return 'pull'; } } exports.NewService = NewService;