@aminya/dotenv-vault
Version:
A secrets manager for .env files – from the same people that pioneered dotenv.
152 lines (149 loc) • 6.09 kB
JavaScript
"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;