@dotenc/cli 0.4.3 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/cli.js +253 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
[![NPM Version][npm-image]][npm-url]
|
|
4
4
|
[![Github License][license-image]](LICENSE)
|
|
5
5
|
[![NPM Downloads][downloads-image]][npm-url]
|
|
6
|
+
[![Codecov][codecov-image]][codecov-url]
|
|
6
7
|
|
|
7
8
|
🔐 Git-native encrypted environments powered by your SSH keys
|
|
8
9
|
|
|
@@ -103,7 +104,7 @@ Your SSH private keys never leave `~/.ssh/`. dotenc reads them in place - nothin
|
|
|
103
104
|
|
|
104
105
|
After setup, your project will look like:
|
|
105
106
|
|
|
106
|
-
```
|
|
107
|
+
```plaintext
|
|
107
108
|
.
|
|
108
109
|
├── .dotenc/
|
|
109
110
|
│ ├── alice.pub
|
|
@@ -332,7 +333,7 @@ Copy the **entire** contents of the private key file and store it as a secret en
|
|
|
332
333
|
cat ci_key
|
|
333
334
|
```
|
|
334
335
|
|
|
335
|
-
```
|
|
336
|
+
```plaintext
|
|
336
337
|
-----BEGIN OPENSSH PRIVATE KEY-----
|
|
337
338
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbm...
|
|
338
339
|
-----END OPENSSH PRIVATE KEY-----
|
|
@@ -446,7 +447,6 @@ Alternatively, the `DOTENC_ENV` variable can be used to set the environment, so
|
|
|
446
447
|
dotenc run node app.js
|
|
447
448
|
```
|
|
448
449
|
|
|
449
|
-
> **Note:** `dotenc textconv` is an internal command used by the git diff driver. It is set up automatically during `dotenc init` and allows `git diff` to show decrypted content of `.env.*.enc` files.
|
|
450
450
|
|
|
451
451
|
## How dotenc compares
|
|
452
452
|
|
|
@@ -478,3 +478,5 @@ It does not aim to replace centralized secret managers like Vault or Doppler —
|
|
|
478
478
|
[license-image]: https://img.shields.io/github/license/ivanfilhoz/dotenc.svg
|
|
479
479
|
[downloads-image]: https://img.shields.io/npm/dm/@dotenc/cli.svg
|
|
480
480
|
[npm-url]: https://npmjs.org/package/@dotenc/cli
|
|
481
|
+
[codecov-image]: https://codecov.io/gh/ivanfilhoz/dotenc/graph/badge.svg?token=U2MKXVGBA0
|
|
482
|
+
[codecov-url]: https://codecov.io/gh/ivanfilhoz/dotenc
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ var package_default;
|
|
|
7
7
|
var init_package = __esm(() => {
|
|
8
8
|
package_default = {
|
|
9
9
|
name: "@dotenc/cli",
|
|
10
|
-
version: "0.4.
|
|
10
|
+
version: "0.4.5",
|
|
11
11
|
description: "🔐 Git-native encrypted environments powered by your SSH keys",
|
|
12
12
|
author: "Ivan Filho <i@ivanfilho.com>",
|
|
13
13
|
license: "MIT",
|
|
@@ -579,8 +579,8 @@ var init_getPrivateKeys = __esm(() => {
|
|
|
579
579
|
|
|
580
580
|
// src/helpers/decryptEnvironment.ts
|
|
581
581
|
import chalk2 from "chalk";
|
|
582
|
-
var decryptEnvironmentData = async (environment) => {
|
|
583
|
-
const { keys: availablePrivateKeys, passphraseProtectedKeys } = await getPrivateKeys();
|
|
582
|
+
var defaultDecryptEnvironmentDataDeps, decryptEnvironmentData = async (environment, deps = defaultDecryptEnvironmentDataDeps) => {
|
|
583
|
+
const { keys: availablePrivateKeys, passphraseProtectedKeys } = await deps.getPrivateKeys();
|
|
584
584
|
if (!availablePrivateKeys.length) {
|
|
585
585
|
if (passphraseProtectedKeys.length > 0) {
|
|
586
586
|
throw new Error(passphraseProtectedKeyError(passphraseProtectedKeys));
|
|
@@ -603,20 +603,20 @@ var decryptEnvironmentData = async (environment) => {
|
|
|
603
603
|
}
|
|
604
604
|
let dataKey;
|
|
605
605
|
try {
|
|
606
|
-
dataKey = decryptDataKey(selectedPrivateKey, Buffer.from(grantedKey.encryptedDataKey, "base64"));
|
|
606
|
+
dataKey = deps.decryptDataKey(selectedPrivateKey, Buffer.from(grantedKey.encryptedDataKey, "base64"));
|
|
607
607
|
} catch (error) {
|
|
608
608
|
throw new Error("Failed to decrypt the data key.", { cause: error });
|
|
609
609
|
}
|
|
610
|
-
const decryptedContent = await decryptData(dataKey, Buffer.from(environment.encryptedContent, "base64"));
|
|
610
|
+
const decryptedContent = await deps.decryptData(dataKey, Buffer.from(environment.encryptedContent, "base64"));
|
|
611
611
|
return decryptedContent;
|
|
612
|
-
}, decryptEnvironment = async (name) => {
|
|
613
|
-
const { keys: availablePrivateKeys } = await getPrivateKeys();
|
|
614
|
-
const environmentJson = await getEnvironmentByName(name);
|
|
612
|
+
}, defaultDecryptEnvironmentDeps, decryptEnvironment = async (name, deps = defaultDecryptEnvironmentDeps) => {
|
|
613
|
+
const { keys: availablePrivateKeys } = await deps.getPrivateKeys();
|
|
614
|
+
const environmentJson = await deps.getEnvironmentByName(name);
|
|
615
615
|
try {
|
|
616
|
-
return await decryptEnvironmentData(environmentJson);
|
|
616
|
+
return await decryptEnvironmentData(environmentJson, deps);
|
|
617
617
|
} catch (error) {
|
|
618
618
|
if (error instanceof Error && error.message === "Access denied to the environment.") {
|
|
619
|
-
|
|
619
|
+
deps.logError(`You do not have access to this environment.
|
|
620
620
|
|
|
621
621
|
These are your available private keys:
|
|
622
622
|
|
|
@@ -630,7 +630,7 @@ var decryptEnvironmentData = async (environment) => {
|
|
|
630
630
|
`);
|
|
631
631
|
}
|
|
632
632
|
if (error instanceof Error && error.message === "Failed to decrypt the data key.") {
|
|
633
|
-
|
|
633
|
+
deps.logError(`${chalk2.red("Error:")} failed to decrypt the data key. Please ensure you have the correct private key.`);
|
|
634
634
|
}
|
|
635
635
|
throw error;
|
|
636
636
|
}
|
|
@@ -641,6 +641,16 @@ var init_decryptEnvironment = __esm(() => {
|
|
|
641
641
|
init_errors();
|
|
642
642
|
init_getEnvironmentByName();
|
|
643
643
|
init_getPrivateKeys();
|
|
644
|
+
defaultDecryptEnvironmentDataDeps = {
|
|
645
|
+
getPrivateKeys,
|
|
646
|
+
decryptDataKey,
|
|
647
|
+
decryptData
|
|
648
|
+
};
|
|
649
|
+
defaultDecryptEnvironmentDeps = {
|
|
650
|
+
...defaultDecryptEnvironmentDataDeps,
|
|
651
|
+
getEnvironmentByName,
|
|
652
|
+
logError: (message) => console.error(message)
|
|
653
|
+
};
|
|
644
654
|
});
|
|
645
655
|
|
|
646
656
|
// src/helpers/encryptDataKey.ts
|
|
@@ -1000,10 +1010,12 @@ import fs7 from "node:fs/promises";
|
|
|
1000
1010
|
import os2 from "node:os";
|
|
1001
1011
|
import path6 from "node:path";
|
|
1002
1012
|
import { z as z2 } from "zod";
|
|
1003
|
-
var homeConfigSchema,
|
|
1013
|
+
var homeConfigSchema, getConfigPath = () => path6.join(os2.homedir(), ".dotenc", "config.json"), setHomeConfig = async (config) => {
|
|
1004
1014
|
const parsedConfig = homeConfigSchema.parse(config);
|
|
1015
|
+
const configPath = getConfigPath();
|
|
1005
1016
|
await fs7.writeFile(configPath, JSON.stringify(parsedConfig, null, 2), "utf-8");
|
|
1006
1017
|
}, getHomeConfig = async () => {
|
|
1018
|
+
const configPath = getConfigPath();
|
|
1007
1019
|
if (existsSync3(configPath)) {
|
|
1008
1020
|
const config = JSON.parse(await fs7.readFile(configPath, "utf-8"));
|
|
1009
1021
|
return homeConfigSchema.parse(config);
|
|
@@ -1014,7 +1026,6 @@ var init_homeConfig = __esm(() => {
|
|
|
1014
1026
|
homeConfigSchema = z2.object({
|
|
1015
1027
|
editor: z2.string().nullish()
|
|
1016
1028
|
});
|
|
1017
|
-
configPath = path6.join(os2.homedir(), ".dotenc", "config.json");
|
|
1018
1029
|
});
|
|
1019
1030
|
|
|
1020
1031
|
// src/commands/config.ts
|
|
@@ -1077,66 +1088,69 @@ var init_parseEnv = __esm(() => {
|
|
|
1077
1088
|
// src/commands/run.ts
|
|
1078
1089
|
import { spawn } from "node:child_process";
|
|
1079
1090
|
import chalk7 from "chalk";
|
|
1080
|
-
var runCommand = async (command, args, options) => {
|
|
1091
|
+
var defaultRunCommandDeps, runCommand = async (command, args, options, _command, deps = defaultRunCommandDeps) => {
|
|
1081
1092
|
const environmentName = options.env || process.env.DOTENC_ENV;
|
|
1082
1093
|
if (!environmentName) {
|
|
1083
|
-
|
|
1094
|
+
deps.logError(`No environment provided. Use -e or set DOTENC_ENV to the environment you want to run the command in.
|
|
1084
1095
|
To start a new environment, use "dotenc init [environment]".`);
|
|
1085
|
-
|
|
1096
|
+
deps.exit(1);
|
|
1086
1097
|
}
|
|
1087
1098
|
const environments = environmentName.split(",");
|
|
1088
1099
|
for (const env of environments) {
|
|
1089
|
-
const validation = validateEnvironmentName(env);
|
|
1100
|
+
const validation = deps.validateEnvironmentName(env);
|
|
1090
1101
|
if (!validation.valid) {
|
|
1091
|
-
|
|
1092
|
-
|
|
1102
|
+
deps.logError(`${chalk7.red("Error:")} ${validation.reason}`);
|
|
1103
|
+
deps.exit(1);
|
|
1093
1104
|
}
|
|
1094
1105
|
}
|
|
1095
1106
|
let failureCount = 0;
|
|
1096
1107
|
const decryptedEnvs = await Promise.all(environments.map(async (environment) => {
|
|
1097
1108
|
let content;
|
|
1098
1109
|
try {
|
|
1099
|
-
content = await decryptEnvironment(environment);
|
|
1110
|
+
content = await deps.decryptEnvironment(environment);
|
|
1100
1111
|
} catch (error) {
|
|
1101
|
-
|
|
1112
|
+
deps.logError(error instanceof Error ? error.message : `Unknown error occurred while decrypting the environment ${environment}.`);
|
|
1102
1113
|
failureCount++;
|
|
1103
1114
|
return {};
|
|
1104
1115
|
}
|
|
1105
|
-
const decryptedEnv2 = parseEnv(content);
|
|
1116
|
+
const decryptedEnv2 = deps.parseEnv(content);
|
|
1106
1117
|
return decryptedEnv2;
|
|
1107
1118
|
}));
|
|
1108
1119
|
if (failureCount === environments.length) {
|
|
1109
|
-
|
|
1110
|
-
|
|
1120
|
+
deps.logError(`${chalk7.red("Error:")} All environments failed to load.`);
|
|
1121
|
+
deps.exit(1);
|
|
1111
1122
|
}
|
|
1112
1123
|
if (failureCount > 0) {
|
|
1113
|
-
|
|
1124
|
+
deps.logError(`${chalk7.yellow("Warning:")} ${failureCount} of ${environments.length} environment(s) failed to load.`);
|
|
1114
1125
|
}
|
|
1115
1126
|
const decryptedEnv = decryptedEnvs.reduce((acc, env) => {
|
|
1116
1127
|
return { ...acc, ...env };
|
|
1117
1128
|
}, {});
|
|
1118
1129
|
const mergedEnv = { ...process.env, ...decryptedEnv };
|
|
1119
|
-
const child = spawn(command, args, {
|
|
1130
|
+
const child = deps.spawn(command, args, {
|
|
1120
1131
|
env: mergedEnv,
|
|
1121
1132
|
stdio: "inherit"
|
|
1122
1133
|
});
|
|
1123
1134
|
child.on("exit", (code) => {
|
|
1124
|
-
|
|
1135
|
+
deps.exit(code ?? 0);
|
|
1125
1136
|
});
|
|
1126
1137
|
};
|
|
1127
1138
|
var init_run = __esm(() => {
|
|
1128
1139
|
init_decryptEnvironment();
|
|
1129
1140
|
init_parseEnv();
|
|
1141
|
+
defaultRunCommandDeps = {
|
|
1142
|
+
decryptEnvironment,
|
|
1143
|
+
parseEnv,
|
|
1144
|
+
validateEnvironmentName,
|
|
1145
|
+
spawn,
|
|
1146
|
+
logError: (message) => console.error(message),
|
|
1147
|
+
exit: (code) => process.exit(code)
|
|
1148
|
+
};
|
|
1130
1149
|
});
|
|
1131
1150
|
|
|
1132
1151
|
// src/commands/dev.ts
|
|
1133
1152
|
import chalk8 from "chalk";
|
|
1134
|
-
var devCommand = async (command, args, deps = {
|
|
1135
|
-
getCurrentKeyName,
|
|
1136
|
-
runCommand,
|
|
1137
|
-
logError: (message) => console.error(message),
|
|
1138
|
-
exit: (code) => process.exit(code)
|
|
1139
|
-
}) => {
|
|
1153
|
+
var defaultDevCommandDeps, devCommand = async (command, args, deps = defaultDevCommandDeps) => {
|
|
1140
1154
|
const keyName = await deps.getCurrentKeyName();
|
|
1141
1155
|
if (!keyName) {
|
|
1142
1156
|
deps.logError(`${chalk8.red("Error:")} could not resolve your identity. Run ${chalk8.gray("dotenc init")} first.`);
|
|
@@ -1147,6 +1161,12 @@ var devCommand = async (command, args, deps = {
|
|
|
1147
1161
|
var init_dev = __esm(() => {
|
|
1148
1162
|
init_getCurrentKeyName();
|
|
1149
1163
|
init_run();
|
|
1164
|
+
defaultDevCommandDeps = {
|
|
1165
|
+
getCurrentKeyName,
|
|
1166
|
+
runCommand,
|
|
1167
|
+
logError: console.error,
|
|
1168
|
+
exit: process.exit
|
|
1169
|
+
};
|
|
1150
1170
|
});
|
|
1151
1171
|
|
|
1152
1172
|
// src/helpers/environmentExists.ts
|
|
@@ -1172,9 +1192,9 @@ import { existsSync as existsSync5 } from "node:fs";
|
|
|
1172
1192
|
import fs8 from "node:fs/promises";
|
|
1173
1193
|
import path8 from "node:path";
|
|
1174
1194
|
import { z as z3 } from "zod";
|
|
1175
|
-
var projectConfigSchema,
|
|
1176
|
-
if (existsSync5(
|
|
1177
|
-
const config = JSON.parse(await fs8.readFile(
|
|
1195
|
+
var projectConfigSchema, configPath, getProjectConfig = async () => {
|
|
1196
|
+
if (existsSync5(configPath)) {
|
|
1197
|
+
const config = JSON.parse(await fs8.readFile(configPath, "utf-8"));
|
|
1178
1198
|
return projectConfigSchema.parse(config);
|
|
1179
1199
|
}
|
|
1180
1200
|
return {};
|
|
@@ -1183,7 +1203,7 @@ var init_projectConfig = __esm(() => {
|
|
|
1183
1203
|
projectConfigSchema = z3.object({
|
|
1184
1204
|
projectId: z3.string()
|
|
1185
1205
|
});
|
|
1186
|
-
|
|
1206
|
+
configPath = path8.join(process.cwd(), "dotenc.json");
|
|
1187
1207
|
});
|
|
1188
1208
|
|
|
1189
1209
|
// src/prompts/createEnvironment.ts
|
|
@@ -1278,6 +1298,77 @@ var init_create = __esm(() => {
|
|
|
1278
1298
|
init_createEnvironment();
|
|
1279
1299
|
});
|
|
1280
1300
|
|
|
1301
|
+
// src/commands/env/decrypt.ts
|
|
1302
|
+
var defaultDecryptCommandDeps, ansiPattern, stripAnsi = (value) => value.replace(ansiPattern, ""), mapErrorCode = (message) => {
|
|
1303
|
+
if (message.includes("Environment file not found")) {
|
|
1304
|
+
return "ENVIRONMENT_NOT_FOUND";
|
|
1305
|
+
}
|
|
1306
|
+
if (message === "Access denied to the environment.") {
|
|
1307
|
+
return "ACCESS_DENIED";
|
|
1308
|
+
}
|
|
1309
|
+
if (message.includes("No private keys found")) {
|
|
1310
|
+
return "NO_PRIVATE_KEYS";
|
|
1311
|
+
}
|
|
1312
|
+
if (message.toLowerCase().includes("passphrase-protected")) {
|
|
1313
|
+
return "PASSPHRASE_PROTECTED_KEYS";
|
|
1314
|
+
}
|
|
1315
|
+
return "UNKNOWN";
|
|
1316
|
+
}, writeJson = (message, deps) => {
|
|
1317
|
+
deps.writeStdout(`${JSON.stringify(message)}
|
|
1318
|
+
`);
|
|
1319
|
+
}, decryptCommand = async (environmentName, options, _command, deps = defaultDecryptCommandDeps) => {
|
|
1320
|
+
const validation = deps.validateEnvironmentName(environmentName);
|
|
1321
|
+
if (!validation.valid) {
|
|
1322
|
+
if (options.json) {
|
|
1323
|
+
writeJson({
|
|
1324
|
+
ok: false,
|
|
1325
|
+
error: {
|
|
1326
|
+
code: "INVALID_ENVIRONMENT_NAME",
|
|
1327
|
+
message: validation.reason
|
|
1328
|
+
}
|
|
1329
|
+
}, deps);
|
|
1330
|
+
} else {
|
|
1331
|
+
deps.logError(validation.reason);
|
|
1332
|
+
}
|
|
1333
|
+
deps.exit(1);
|
|
1334
|
+
}
|
|
1335
|
+
try {
|
|
1336
|
+
const environment = await deps.getEnvironmentByName(environmentName);
|
|
1337
|
+
const plaintext = await deps.decryptEnvironmentData(environment);
|
|
1338
|
+
if (options.json) {
|
|
1339
|
+
writeJson({ ok: true, content: plaintext }, deps);
|
|
1340
|
+
} else {
|
|
1341
|
+
deps.writeStdout(plaintext);
|
|
1342
|
+
}
|
|
1343
|
+
} catch (error) {
|
|
1344
|
+
const rawMessage = error instanceof Error ? error.message : "Unknown error occurred while decrypting the environment.";
|
|
1345
|
+
const message = stripAnsi(rawMessage);
|
|
1346
|
+
const code = mapErrorCode(message);
|
|
1347
|
+
if (options.json) {
|
|
1348
|
+
writeJson({
|
|
1349
|
+
ok: false,
|
|
1350
|
+
error: { code, message }
|
|
1351
|
+
}, deps);
|
|
1352
|
+
} else {
|
|
1353
|
+
deps.logError(message);
|
|
1354
|
+
}
|
|
1355
|
+
deps.exit(1);
|
|
1356
|
+
}
|
|
1357
|
+
};
|
|
1358
|
+
var init_decrypt = __esm(() => {
|
|
1359
|
+
init_decryptEnvironment();
|
|
1360
|
+
init_getEnvironmentByName();
|
|
1361
|
+
defaultDecryptCommandDeps = {
|
|
1362
|
+
validateEnvironmentName,
|
|
1363
|
+
getEnvironmentByName,
|
|
1364
|
+
decryptEnvironmentData,
|
|
1365
|
+
writeStdout: (message) => process.stdout.write(message),
|
|
1366
|
+
logError: (message) => console.error(message),
|
|
1367
|
+
exit: (code) => process.exit(code)
|
|
1368
|
+
};
|
|
1369
|
+
ansiPattern = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
|
|
1370
|
+
});
|
|
1371
|
+
|
|
1281
1372
|
// src/helpers/createHash.ts
|
|
1282
1373
|
import crypto9 from "node:crypto";
|
|
1283
1374
|
var createHash = (input) => {
|
|
@@ -1287,7 +1378,14 @@ var init_createHash = () => {};
|
|
|
1287
1378
|
|
|
1288
1379
|
// src/helpers/getDefaultEditor.ts
|
|
1289
1380
|
import { execSync } from "node:child_process";
|
|
1290
|
-
var
|
|
1381
|
+
var commandExists = (command) => {
|
|
1382
|
+
try {
|
|
1383
|
+
execSync(`command -v ${command}`, { stdio: "ignore" });
|
|
1384
|
+
return true;
|
|
1385
|
+
} catch {
|
|
1386
|
+
return false;
|
|
1387
|
+
}
|
|
1388
|
+
}, defaultGetDefaultEditorDeps, getDefaultEditor = async (deps = defaultGetDefaultEditorDeps) => {
|
|
1291
1389
|
const config = await deps.getHomeConfig();
|
|
1292
1390
|
if (config.editor) {
|
|
1293
1391
|
return config.editor;
|
|
@@ -1314,14 +1412,7 @@ var init_getDefaultEditor = __esm(() => {
|
|
|
1314
1412
|
init_homeConfig();
|
|
1315
1413
|
defaultGetDefaultEditorDeps = {
|
|
1316
1414
|
getHomeConfig,
|
|
1317
|
-
commandExists
|
|
1318
|
-
try {
|
|
1319
|
-
execSync(`command -v ${command}`, { stdio: "ignore" });
|
|
1320
|
-
return true;
|
|
1321
|
-
} catch {
|
|
1322
|
-
return false;
|
|
1323
|
-
}
|
|
1324
|
-
},
|
|
1415
|
+
commandExists,
|
|
1325
1416
|
platform: process.platform
|
|
1326
1417
|
};
|
|
1327
1418
|
});
|
|
@@ -1423,6 +1514,117 @@ var init_edit = __esm(() => {
|
|
|
1423
1514
|
init_chooseEnvironment();
|
|
1424
1515
|
});
|
|
1425
1516
|
|
|
1517
|
+
// src/commands/env/encrypt.ts
|
|
1518
|
+
var defaultEncryptCommandDeps, ansiPattern2, stripAnsi2 = (value) => value.replace(ansiPattern2, ""), mapErrorCode2 = (message) => {
|
|
1519
|
+
if (message.includes("Environment file not found")) {
|
|
1520
|
+
return "ENVIRONMENT_NOT_FOUND";
|
|
1521
|
+
}
|
|
1522
|
+
if (message === "Access denied to the environment.") {
|
|
1523
|
+
return "ACCESS_DENIED";
|
|
1524
|
+
}
|
|
1525
|
+
if (message.includes("No private keys found")) {
|
|
1526
|
+
return "NO_PRIVATE_KEYS";
|
|
1527
|
+
}
|
|
1528
|
+
if (message.includes("No public keys found")) {
|
|
1529
|
+
return "NO_PUBLIC_KEYS";
|
|
1530
|
+
}
|
|
1531
|
+
if (message.toLowerCase().includes("passphrase-protected")) {
|
|
1532
|
+
return "PASSPHRASE_PROTECTED_KEYS";
|
|
1533
|
+
}
|
|
1534
|
+
return "UNKNOWN";
|
|
1535
|
+
}, writeJson2 = (message, deps) => {
|
|
1536
|
+
deps.writeStdout(`${JSON.stringify(message)}
|
|
1537
|
+
`);
|
|
1538
|
+
}, runWithoutConsoleNoise = async (fn) => {
|
|
1539
|
+
const originalLog = console.log;
|
|
1540
|
+
const originalError = console.error;
|
|
1541
|
+
try {
|
|
1542
|
+
console.log = () => {};
|
|
1543
|
+
console.error = () => {};
|
|
1544
|
+
await fn();
|
|
1545
|
+
} finally {
|
|
1546
|
+
console.log = originalLog;
|
|
1547
|
+
console.error = originalError;
|
|
1548
|
+
}
|
|
1549
|
+
}, encryptCommand = async (environmentName, options, _command, deps = defaultEncryptCommandDeps) => {
|
|
1550
|
+
const validation = deps.validateEnvironmentName(environmentName);
|
|
1551
|
+
if (!validation.valid) {
|
|
1552
|
+
if (options.json) {
|
|
1553
|
+
writeJson2({
|
|
1554
|
+
ok: false,
|
|
1555
|
+
error: {
|
|
1556
|
+
code: "INVALID_ENVIRONMENT_NAME",
|
|
1557
|
+
message: validation.reason
|
|
1558
|
+
}
|
|
1559
|
+
}, deps);
|
|
1560
|
+
} else {
|
|
1561
|
+
deps.logError(validation.reason);
|
|
1562
|
+
}
|
|
1563
|
+
deps.exit(1);
|
|
1564
|
+
}
|
|
1565
|
+
if (!options.stdin) {
|
|
1566
|
+
const message = 'No input source provided. Use "--stdin" and pipe the plaintext content.';
|
|
1567
|
+
if (options.json) {
|
|
1568
|
+
writeJson2({
|
|
1569
|
+
ok: false,
|
|
1570
|
+
error: {
|
|
1571
|
+
code: "MISSING_STDIN",
|
|
1572
|
+
message
|
|
1573
|
+
}
|
|
1574
|
+
}, deps);
|
|
1575
|
+
} else {
|
|
1576
|
+
deps.logError(message);
|
|
1577
|
+
}
|
|
1578
|
+
deps.exit(1);
|
|
1579
|
+
}
|
|
1580
|
+
try {
|
|
1581
|
+
const content = await deps.readStdin();
|
|
1582
|
+
if (options.json) {
|
|
1583
|
+
await runWithoutConsoleNoise(async () => {
|
|
1584
|
+
await deps.encryptEnvironment(environmentName, content);
|
|
1585
|
+
});
|
|
1586
|
+
writeJson2({ ok: true }, deps);
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
await deps.encryptEnvironment(environmentName, content);
|
|
1590
|
+
} catch (error) {
|
|
1591
|
+
const rawMessage = error instanceof Error ? error.message : "Unknown error occurred while encrypting the environment.";
|
|
1592
|
+
const message = stripAnsi2(rawMessage);
|
|
1593
|
+
const code = mapErrorCode2(message);
|
|
1594
|
+
if (options.json) {
|
|
1595
|
+
writeJson2({
|
|
1596
|
+
ok: false,
|
|
1597
|
+
error: { code, message }
|
|
1598
|
+
}, deps);
|
|
1599
|
+
} else {
|
|
1600
|
+
deps.logError(message);
|
|
1601
|
+
}
|
|
1602
|
+
deps.exit(1);
|
|
1603
|
+
}
|
|
1604
|
+
};
|
|
1605
|
+
var init_encrypt = __esm(() => {
|
|
1606
|
+
init_encryptEnvironment();
|
|
1607
|
+
defaultEncryptCommandDeps = {
|
|
1608
|
+
validateEnvironmentName,
|
|
1609
|
+
encryptEnvironment,
|
|
1610
|
+
readStdin: () => new Promise((resolve, reject) => {
|
|
1611
|
+
let input = "";
|
|
1612
|
+
process.stdin.setEncoding("utf-8");
|
|
1613
|
+
process.stdin.on("data", (chunk) => {
|
|
1614
|
+
input += chunk;
|
|
1615
|
+
});
|
|
1616
|
+
process.stdin.on("end", () => {
|
|
1617
|
+
resolve(input);
|
|
1618
|
+
});
|
|
1619
|
+
process.stdin.on("error", reject);
|
|
1620
|
+
}),
|
|
1621
|
+
writeStdout: (message) => process.stdout.write(message),
|
|
1622
|
+
logError: (message) => console.error(message),
|
|
1623
|
+
exit: (code) => process.exit(code)
|
|
1624
|
+
};
|
|
1625
|
+
ansiPattern2 = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
|
|
1626
|
+
});
|
|
1627
|
+
|
|
1426
1628
|
// src/commands/env/list.ts
|
|
1427
1629
|
var envListCommand = async () => {
|
|
1428
1630
|
const environments = await getEnvironments();
|
|
@@ -2049,7 +2251,9 @@ var init_program = __esm(() => {
|
|
|
2049
2251
|
init_config();
|
|
2050
2252
|
init_dev();
|
|
2051
2253
|
init_create();
|
|
2254
|
+
init_decrypt();
|
|
2052
2255
|
init_edit();
|
|
2256
|
+
init_encrypt();
|
|
2053
2257
|
init_list2();
|
|
2054
2258
|
init_rotate();
|
|
2055
2259
|
init_init();
|
|
@@ -2065,6 +2269,8 @@ var init_program = __esm(() => {
|
|
|
2065
2269
|
env = program.command("env").description("manage environments");
|
|
2066
2270
|
env.command("create").argument("[environment]", "the name of the new environment").argument("[publicKey]", "the name of the public key to grant access to the environment").description("create a new environment").action((env2, pubKey) => createCommand(env2, pubKey));
|
|
2067
2271
|
env.command("edit").argument("[environment]", "the environment to edit").description("edit an environment").action(editCommand);
|
|
2272
|
+
env.command("decrypt", { hidden: true }).argument("<environment>", "the environment to decrypt").addOption(new Option("--json", "output machine-readable JSON")).description("decrypt an environment and print plaintext to stdout").action(decryptCommand);
|
|
2273
|
+
env.command("encrypt", { hidden: true }).argument("<environment>", "the environment to encrypt").addOption(new Option("--stdin", "read plaintext content from stdin")).addOption(new Option("--json", "output machine-readable JSON")).description("encrypt plaintext content and write it to an environment file").action(encryptCommand);
|
|
2068
2274
|
env.command("rotate").argument("[environment]", "the environment to rotate the data key for").description("rotate the data key for an environment").action(rotateCommand);
|
|
2069
2275
|
env.command("list").description("list all environments").action(envListCommand);
|
|
2070
2276
|
auth = program.command("auth").description("manage environment access");
|
|
@@ -2077,7 +2283,7 @@ var init_program = __esm(() => {
|
|
|
2077
2283
|
key.command("add").argument("[name]", "the name of the public key in the project").addOption(new Option("--from-ssh <path>", "add a public key derived from an SSH key file")).addOption(new Option("-f, --from-file <file>", "add the key from a PEM file")).addOption(new Option("-s, --from-string <string>", "add a public key from a string")).description("add a public key to the project").action(keyAddCommand);
|
|
2078
2284
|
key.command("list").description("list all public keys in the project").action(keyListCommand);
|
|
2079
2285
|
key.command("remove").argument("[name]", "the name of the public key to remove").description("remove a public key from the project").action(keyRemoveCommand);
|
|
2080
|
-
program.command("textconv").argument("<filepath>", "path to the encrypted environment file").description("decrypt an environment file for git diff").action(textconvCommand);
|
|
2286
|
+
program.command("textconv", { hidden: true }).argument("<filepath>", "path to the encrypted environment file").description("decrypt an environment file for git diff").action(textconvCommand);
|
|
2081
2287
|
program.command("whoami").description("show your identity in this project").action(whoamiCommand);
|
|
2082
2288
|
program.command("config").argument("<key>", "the key to get or set").argument("[value]", "the value to set the key to").addOption(new Option("-r, --remove", "remove a configuration key")).description("manage global configuration").action(configCommand);
|
|
2083
2289
|
program.parse();
|