@dotenc/cli 0.5.2 → 0.6.0
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 +2 -4
- package/dist/cli.js +442 -233
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -112,8 +112,7 @@ After setup, your project will look like:
|
|
|
112
112
|
│ └── ...
|
|
113
113
|
├── .env.alice.enc
|
|
114
114
|
├── .env.production.enc
|
|
115
|
-
|
|
116
|
-
└── dotenc.json
|
|
115
|
+
└── .env.development.enc
|
|
117
116
|
```
|
|
118
117
|
|
|
119
118
|
Encrypted files are committed to Git. Public keys are stored inside `.dotenc/`. Each developer gets a personal encrypted environment (e.g., `.env.alice.enc`).
|
|
@@ -158,8 +157,7 @@ This will interactively guide you through the setup process:
|
|
|
158
157
|
2. Prompting for your username (defaults to your system username);
|
|
159
158
|
3. Letting you choose which SSH key to use;
|
|
160
159
|
4. Deriving the public key and storing it in `.dotenc/` (e.g., `.dotenc/alice.pub`);
|
|
161
|
-
5. Creating
|
|
162
|
-
6. Creating your personal encrypted environment (e.g., `.env.alice.enc`).
|
|
160
|
+
5. Creating encrypted `development` and personal environments (e.g., `.env.development.enc`, `.env.alice.enc`).
|
|
163
161
|
|
|
164
162
|
No keys to generate. If you already have an SSH key (and you probably do), you're ready to go.
|
|
165
163
|
|
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.
|
|
10
|
+
version: "0.6.0",
|
|
11
11
|
description: "🔐 Git-native encrypted environments powered by your SSH keys",
|
|
12
12
|
author: "Ivan Filho <i@ivanfilho.com>",
|
|
13
13
|
license: "MIT",
|
|
@@ -38,7 +38,6 @@ var init_package = __esm(() => {
|
|
|
38
38
|
typescript: "^5.8.2"
|
|
39
39
|
},
|
|
40
40
|
dependencies: {
|
|
41
|
-
"@paralleldrive/cuid2": "^2.2.2",
|
|
42
41
|
chalk: "^5.4.1",
|
|
43
42
|
commander: "^13.1.0",
|
|
44
43
|
eciesjs: "^0.4.15",
|
|
@@ -486,9 +485,77 @@ function tryParsePrivateKey(keyContent) {
|
|
|
486
485
|
return parseOpenSSHPrivateKey(keyContent);
|
|
487
486
|
}
|
|
488
487
|
}
|
|
488
|
+
function describeUnsupportedAlgorithm(keyType) {
|
|
489
|
+
return `unsupported algorithm: ${String(keyType ?? "unknown")}`;
|
|
490
|
+
}
|
|
491
|
+
function readLengthPrefixedBytes(buffer, offset) {
|
|
492
|
+
if (offset + 4 > buffer.length)
|
|
493
|
+
return null;
|
|
494
|
+
const length = buffer.readUInt32BE(offset);
|
|
495
|
+
const start = offset + 4;
|
|
496
|
+
const end = start + length;
|
|
497
|
+
if (end > buffer.length)
|
|
498
|
+
return null;
|
|
499
|
+
return { bytes: buffer.subarray(start, end), nextOffset: end };
|
|
500
|
+
}
|
|
501
|
+
function readLengthPrefixedString(buffer, offset) {
|
|
502
|
+
const bytes = readLengthPrefixedBytes(buffer, offset);
|
|
503
|
+
if (!bytes)
|
|
504
|
+
return null;
|
|
505
|
+
return { value: bytes.bytes.toString("ascii"), nextOffset: bytes.nextOffset };
|
|
506
|
+
}
|
|
507
|
+
function detectUnsupportedOpenSSHAlgorithm(keyContent) {
|
|
508
|
+
if (!keyContent.includes("BEGIN OPENSSH PRIVATE KEY"))
|
|
509
|
+
return null;
|
|
510
|
+
const lines = keyContent.split(`
|
|
511
|
+
`);
|
|
512
|
+
const startIdx = lines.findIndex((line) => line.trim().startsWith("-----BEGIN OPENSSH PRIVATE KEY-----"));
|
|
513
|
+
const endIdx = lines.findIndex((line) => line.trim().startsWith("-----END OPENSSH PRIVATE KEY-----"));
|
|
514
|
+
if (startIdx === -1 || endIdx === -1)
|
|
515
|
+
return null;
|
|
516
|
+
const base64 = lines.slice(startIdx + 1, endIdx).map((line) => line.trim()).join("");
|
|
517
|
+
const buffer = Buffer.from(base64, "base64");
|
|
518
|
+
const MAGIC = "openssh-key-v1\x00";
|
|
519
|
+
if (buffer.length < MAGIC.length)
|
|
520
|
+
return null;
|
|
521
|
+
const magic = buffer.subarray(0, MAGIC.length).toString("ascii");
|
|
522
|
+
if (magic !== MAGIC)
|
|
523
|
+
return null;
|
|
524
|
+
let offset = MAGIC.length;
|
|
525
|
+
const ciphername = readLengthPrefixedString(buffer, offset);
|
|
526
|
+
if (!ciphername)
|
|
527
|
+
return null;
|
|
528
|
+
offset = ciphername.nextOffset;
|
|
529
|
+
const kdfname = readLengthPrefixedString(buffer, offset);
|
|
530
|
+
if (!kdfname)
|
|
531
|
+
return null;
|
|
532
|
+
offset = kdfname.nextOffset;
|
|
533
|
+
const kdfoptions = readLengthPrefixedBytes(buffer, offset);
|
|
534
|
+
if (!kdfoptions)
|
|
535
|
+
return null;
|
|
536
|
+
offset = kdfoptions.nextOffset;
|
|
537
|
+
if (offset + 4 > buffer.length)
|
|
538
|
+
return null;
|
|
539
|
+
const keyCount = buffer.readUInt32BE(offset);
|
|
540
|
+
offset += 4;
|
|
541
|
+
if (keyCount < 1)
|
|
542
|
+
return null;
|
|
543
|
+
const publicBlob = readLengthPrefixedBytes(buffer, offset);
|
|
544
|
+
if (!publicBlob)
|
|
545
|
+
return null;
|
|
546
|
+
const publicBlobType = readLengthPrefixedString(publicBlob.bytes, 0);
|
|
547
|
+
if (!publicBlobType)
|
|
548
|
+
return null;
|
|
549
|
+
if (publicBlobType.value === "ssh-rsa")
|
|
550
|
+
return null;
|
|
551
|
+
if (publicBlobType.value === "ssh-ed25519")
|
|
552
|
+
return null;
|
|
553
|
+
return publicBlobType.value;
|
|
554
|
+
}
|
|
489
555
|
var SSH_KEY_FILES, getPrivateKeys = async () => {
|
|
490
556
|
const privateKeys = [];
|
|
491
557
|
const passphraseProtectedKeys = [];
|
|
558
|
+
const unsupportedKeys = [];
|
|
492
559
|
if (process.env.DOTENC_PRIVATE_KEY) {
|
|
493
560
|
let privateKey = null;
|
|
494
561
|
try {
|
|
@@ -512,6 +579,10 @@ var SSH_KEY_FILES, getPrivateKeys = async () => {
|
|
|
512
579
|
}
|
|
513
580
|
privateKeys.push(entry);
|
|
514
581
|
} else {
|
|
582
|
+
unsupportedKeys.push({
|
|
583
|
+
name: "env.DOTENC_PRIVATE_KEY",
|
|
584
|
+
reason: describeUnsupportedAlgorithm(privateKey.asymmetricKeyType)
|
|
585
|
+
});
|
|
515
586
|
console.error(`Unsupported key type in DOTENC_PRIVATE_KEY: ${privateKey.asymmetricKeyType}. Only RSA and Ed25519 are supported.`);
|
|
516
587
|
}
|
|
517
588
|
} else {
|
|
@@ -520,11 +591,15 @@ var SSH_KEY_FILES, getPrivateKeys = async () => {
|
|
|
520
591
|
process.exit(1);
|
|
521
592
|
}
|
|
522
593
|
console.error("Invalid private key format in DOTENC_PRIVATE_KEY environment variable. Please provide a valid private key (PEM or OpenSSH format).");
|
|
594
|
+
unsupportedKeys.push({
|
|
595
|
+
name: "env.DOTENC_PRIVATE_KEY",
|
|
596
|
+
reason: "invalid private key format"
|
|
597
|
+
});
|
|
523
598
|
}
|
|
524
599
|
}
|
|
525
600
|
const sshDir = path2.join(os.homedir(), ".ssh");
|
|
526
601
|
if (!existsSync(sshDir)) {
|
|
527
|
-
return { keys: privateKeys, passphraseProtectedKeys };
|
|
602
|
+
return { keys: privateKeys, passphraseProtectedKeys, unsupportedKeys };
|
|
528
603
|
}
|
|
529
604
|
const files = await fs2.readdir(sshDir);
|
|
530
605
|
const knownFiles = SSH_KEY_FILES.filter((f) => files.includes(f));
|
|
@@ -551,12 +626,27 @@ var SSH_KEY_FILES, getPrivateKeys = async () => {
|
|
|
551
626
|
if (!privateKey) {
|
|
552
627
|
if (isPassphraseProtected(keyContent)) {
|
|
553
628
|
passphraseProtectedKeys.push(fileName);
|
|
629
|
+
unsupportedKeys.push({
|
|
630
|
+
name: fileName,
|
|
631
|
+
reason: "passphrase-protected"
|
|
632
|
+
});
|
|
633
|
+
} else {
|
|
634
|
+
const unsupportedOpenSSHType = detectUnsupportedOpenSSHAlgorithm(keyContent);
|
|
635
|
+
unsupportedKeys.push({
|
|
636
|
+
name: fileName,
|
|
637
|
+
reason: unsupportedOpenSSHType ? describeUnsupportedAlgorithm(unsupportedOpenSSHType) : "invalid private key format"
|
|
638
|
+
});
|
|
554
639
|
}
|
|
555
640
|
continue;
|
|
556
641
|
}
|
|
557
642
|
const algorithm = detectAlgorithm(privateKey);
|
|
558
|
-
if (!algorithm)
|
|
643
|
+
if (!algorithm) {
|
|
644
|
+
unsupportedKeys.push({
|
|
645
|
+
name: fileName,
|
|
646
|
+
reason: describeUnsupportedAlgorithm(privateKey.asymmetricKeyType)
|
|
647
|
+
});
|
|
559
648
|
continue;
|
|
649
|
+
}
|
|
560
650
|
const entry = {
|
|
561
651
|
name: fileName,
|
|
562
652
|
privateKey,
|
|
@@ -570,7 +660,7 @@ var SSH_KEY_FILES, getPrivateKeys = async () => {
|
|
|
570
660
|
}
|
|
571
661
|
privateKeys.push(entry);
|
|
572
662
|
}
|
|
573
|
-
return { keys: privateKeys, passphraseProtectedKeys };
|
|
663
|
+
return { keys: privateKeys, passphraseProtectedKeys, unsupportedKeys };
|
|
574
664
|
};
|
|
575
665
|
var init_getPrivateKeys = __esm(() => {
|
|
576
666
|
init_getKeyFingerprint();
|
|
@@ -880,20 +970,41 @@ var init_chooseEnvironment = __esm(() => {
|
|
|
880
970
|
|
|
881
971
|
// src/prompts/choosePublicKey.ts
|
|
882
972
|
import inquirer2 from "inquirer";
|
|
883
|
-
|
|
884
|
-
const
|
|
885
|
-
|
|
973
|
+
async function _runChoosePublicKeyPrompt(message, multiple, depsOverrides = {}) {
|
|
974
|
+
const deps = {
|
|
975
|
+
...defaultDeps,
|
|
976
|
+
...depsOverrides
|
|
977
|
+
};
|
|
978
|
+
const publicKeys = await deps.getPublicKeys();
|
|
979
|
+
const result = await deps.prompt([
|
|
886
980
|
{
|
|
887
|
-
type: multiple ? "
|
|
981
|
+
type: multiple ? "checkbox" : "list",
|
|
888
982
|
name: "key",
|
|
889
983
|
message,
|
|
890
984
|
choices: publicKeys.map((key) => key.name.replace(".pub", ""))
|
|
891
985
|
}
|
|
892
986
|
]);
|
|
987
|
+
if (multiple) {
|
|
988
|
+
return Array.isArray(result.key) ? result.key : [result.key];
|
|
989
|
+
}
|
|
990
|
+
if (Array.isArray(result.key)) {
|
|
991
|
+
return result.key[0] ?? "";
|
|
992
|
+
}
|
|
893
993
|
return result.key;
|
|
894
|
-
}
|
|
994
|
+
}
|
|
995
|
+
async function choosePublicKeyPrompt(message, multiple) {
|
|
996
|
+
if (multiple) {
|
|
997
|
+
return _runChoosePublicKeyPrompt(message, true);
|
|
998
|
+
}
|
|
999
|
+
return _runChoosePublicKeyPrompt(message, false);
|
|
1000
|
+
}
|
|
1001
|
+
var defaultDeps;
|
|
895
1002
|
var init_choosePublicKey = __esm(() => {
|
|
896
1003
|
init_getPublicKeys();
|
|
1004
|
+
defaultDeps = {
|
|
1005
|
+
prompt: inquirer2.prompt,
|
|
1006
|
+
getPublicKeys
|
|
1007
|
+
};
|
|
897
1008
|
});
|
|
898
1009
|
|
|
899
1010
|
// src/commands/auth/grant.ts
|
|
@@ -1213,25 +1324,6 @@ var init_getEnvironmentNameSuggestion = __esm(() => {
|
|
|
1213
1324
|
init_environmentExists();
|
|
1214
1325
|
});
|
|
1215
1326
|
|
|
1216
|
-
// src/helpers/projectConfig.ts
|
|
1217
|
-
import { existsSync as existsSync5 } from "node:fs";
|
|
1218
|
-
import fs8 from "node:fs/promises";
|
|
1219
|
-
import path8 from "node:path";
|
|
1220
|
-
import { z as z3 } from "zod";
|
|
1221
|
-
var projectConfigSchema, configPath, getProjectConfig = async () => {
|
|
1222
|
-
if (existsSync5(configPath)) {
|
|
1223
|
-
const config = JSON.parse(await fs8.readFile(configPath, "utf-8"));
|
|
1224
|
-
return projectConfigSchema.parse(config);
|
|
1225
|
-
}
|
|
1226
|
-
return {};
|
|
1227
|
-
};
|
|
1228
|
-
var init_projectConfig = __esm(() => {
|
|
1229
|
-
projectConfigSchema = z3.object({
|
|
1230
|
-
projectId: z3.string()
|
|
1231
|
-
});
|
|
1232
|
-
configPath = path8.join(process.cwd(), "dotenc.json");
|
|
1233
|
-
});
|
|
1234
|
-
|
|
1235
1327
|
// src/prompts/createEnvironment.ts
|
|
1236
1328
|
import inquirer4 from "inquirer";
|
|
1237
1329
|
var createEnvironmentPrompt = async (message, defaultValue) => {
|
|
@@ -1248,15 +1340,23 @@ var createEnvironmentPrompt = async (message, defaultValue) => {
|
|
|
1248
1340
|
var init_createEnvironment = () => {};
|
|
1249
1341
|
|
|
1250
1342
|
// src/commands/env/create.ts
|
|
1251
|
-
import
|
|
1252
|
-
import
|
|
1343
|
+
import fs8 from "node:fs/promises";
|
|
1344
|
+
import path8 from "node:path";
|
|
1253
1345
|
import chalk9 from "chalk";
|
|
1254
|
-
var
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1346
|
+
var _getRunUsageHintForEnvironment = (environmentName) => {
|
|
1347
|
+
if (environmentName === "development") {
|
|
1348
|
+
return chalk9.gray("dotenc dev <command> [args...]");
|
|
1349
|
+
}
|
|
1350
|
+
return `${chalk9.gray(`dotenc run -e ${environmentName} <command> [args...]`)} or ${chalk9.gray(`DOTENC_ENV=${environmentName} dotenc run <command> [args...]`)}`;
|
|
1351
|
+
}, _normalizePublicKeyNamesForCreate = (selection) => {
|
|
1352
|
+
if (Array.isArray(selection)) {
|
|
1353
|
+
return selection;
|
|
1354
|
+
}
|
|
1355
|
+
if (typeof selection === "string" && selection.trim().length > 0) {
|
|
1356
|
+
return [selection];
|
|
1259
1357
|
}
|
|
1358
|
+
return [];
|
|
1359
|
+
}, createCommand = async (environmentNameArg, publicKeyNameArg, initialContent) => {
|
|
1260
1360
|
let environmentName = environmentNameArg;
|
|
1261
1361
|
if (!environmentName) {
|
|
1262
1362
|
environmentName = await createEnvironmentPrompt("What should the environment be named?", getEnvironmentNameSuggestion());
|
|
@@ -1279,7 +1379,8 @@ var createCommand = async (environmentNameArg, publicKeyNameArg, initialContent)
|
|
|
1279
1379
|
console.error(`${chalk9.red("Error:")} no public keys found. Please add a public key using ${chalk9.gray("dotenc key add")}.`);
|
|
1280
1380
|
process.exit(1);
|
|
1281
1381
|
}
|
|
1282
|
-
const
|
|
1382
|
+
const publicKeySelection = publicKeyNameArg ? publicKeyNameArg : await choosePublicKeyPrompt("Which public key(s) do you want to grant access for this environment?", true);
|
|
1383
|
+
const publicKeys = _normalizePublicKeyNamesForCreate(publicKeySelection);
|
|
1283
1384
|
const dataKey = createDataKey();
|
|
1284
1385
|
const content = initialContent ?? `# ${environmentName} environment
|
|
1285
1386
|
`;
|
|
@@ -1302,16 +1403,14 @@ var createCommand = async (environmentNameArg, publicKeyNameArg, initialContent)
|
|
|
1302
1403
|
algorithm: publicKey.algorithm
|
|
1303
1404
|
});
|
|
1304
1405
|
}
|
|
1305
|
-
await
|
|
1406
|
+
await fs8.writeFile(path8.join(process.cwd(), `.env.${environmentName}.enc`), JSON.stringify(environmentJson, null, 2), "utf-8");
|
|
1306
1407
|
console.log(`${chalk9.green("✔")} Environment ${chalk9.cyan(environmentName)} created!`);
|
|
1307
1408
|
console.log(`
|
|
1308
1409
|
Some useful tips:`);
|
|
1309
1410
|
const editCommand = chalk9.gray(`dotenc env edit ${environmentName}`);
|
|
1310
1411
|
console.log(`
|
|
1311
1412
|
- To securely edit your environment: ${editCommand}`);
|
|
1312
|
-
|
|
1313
|
-
const runCommandWithEnv = chalk9.gray(`DOTENC_ENV=${environmentName} dotenc run <command> [args...]`);
|
|
1314
|
-
console.log(`- To run your application: ${runCommand2} or ${runCommandWithEnv}`);
|
|
1413
|
+
console.log(`- To run your application: ${_getRunUsageHintForEnvironment(environmentName)}`);
|
|
1315
1414
|
};
|
|
1316
1415
|
var init_create = __esm(() => {
|
|
1317
1416
|
init_crypto();
|
|
@@ -1319,7 +1418,6 @@ var init_create = __esm(() => {
|
|
|
1319
1418
|
init_environmentExists();
|
|
1320
1419
|
init_getEnvironmentNameSuggestion();
|
|
1321
1420
|
init_getPublicKeys();
|
|
1322
|
-
init_projectConfig();
|
|
1323
1421
|
init_choosePublicKey();
|
|
1324
1422
|
init_createEnvironment();
|
|
1325
1423
|
});
|
|
@@ -1446,10 +1544,10 @@ var init_getDefaultEditor = __esm(() => {
|
|
|
1446
1544
|
|
|
1447
1545
|
// src/commands/env/edit.ts
|
|
1448
1546
|
import { spawnSync } from "node:child_process";
|
|
1449
|
-
import { existsSync as
|
|
1450
|
-
import
|
|
1547
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
1548
|
+
import fs9 from "node:fs/promises";
|
|
1451
1549
|
import os3 from "node:os";
|
|
1452
|
-
import
|
|
1550
|
+
import path9 from "node:path";
|
|
1453
1551
|
import chalk10 from "chalk";
|
|
1454
1552
|
var editCommand = async (environmentNameArg) => {
|
|
1455
1553
|
const environmentName = environmentNameArg || await chooseEnvironmentPrompt("What environment do you want to edit?");
|
|
@@ -1459,8 +1557,8 @@ var editCommand = async (environmentNameArg) => {
|
|
|
1459
1557
|
process.exit(1);
|
|
1460
1558
|
}
|
|
1461
1559
|
const environmentFile = `.env.${environmentName}.enc`;
|
|
1462
|
-
const environmentFilePath =
|
|
1463
|
-
if (!
|
|
1560
|
+
const environmentFilePath = path9.join(process.cwd(), environmentFile);
|
|
1561
|
+
if (!existsSync5(environmentFilePath)) {
|
|
1464
1562
|
console.error(`Environment file not found: ${environmentFilePath}`);
|
|
1465
1563
|
process.exit(1);
|
|
1466
1564
|
}
|
|
@@ -1484,15 +1582,15 @@ ${environment.keys.map((key) => `# - ${key.name}`).join(`
|
|
|
1484
1582
|
# Use 'dotenc auth grant' and/or 'dotenc auth revoke' to manage access.
|
|
1485
1583
|
# Make sure to save your changes before closing the editor.
|
|
1486
1584
|
${separator}${content}`;
|
|
1487
|
-
const tempDir = await
|
|
1488
|
-
const tempFilePath =
|
|
1489
|
-
await
|
|
1585
|
+
const tempDir = await fs9.mkdtemp(path9.join(os3.tmpdir(), "dotenc-"));
|
|
1586
|
+
const tempFilePath = path9.join(tempDir, `.env.${environmentName}`);
|
|
1587
|
+
await fs9.writeFile(tempFilePath, content, { encoding: "utf-8", mode: 384 });
|
|
1490
1588
|
const initialHash = createHash(content);
|
|
1491
1589
|
const cleanup = async () => {
|
|
1492
|
-
await
|
|
1590
|
+
await fs9.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
|
1493
1591
|
};
|
|
1494
1592
|
const onSignal = () => {
|
|
1495
|
-
|
|
1593
|
+
fs9.rm(tempDir, { recursive: true, force: true }).catch(() => {}).finally(() => process.exit(130));
|
|
1496
1594
|
};
|
|
1497
1595
|
process.on("SIGINT", onSignal);
|
|
1498
1596
|
process.on("SIGTERM", onSignal);
|
|
@@ -1507,7 +1605,7 @@ ${separator}${content}`;
|
|
|
1507
1605
|
Editor exited with code ${result.status}`);
|
|
1508
1606
|
process.exit(1);
|
|
1509
1607
|
}
|
|
1510
|
-
let newContent = await
|
|
1608
|
+
let newContent = await fs9.readFile(tempFilePath, "utf-8");
|
|
1511
1609
|
const finalHash = createHash(newContent);
|
|
1512
1610
|
if (initialHash === finalHash) {
|
|
1513
1611
|
console.log(`
|
|
@@ -1697,31 +1795,22 @@ var init_rotate = __esm(() => {
|
|
|
1697
1795
|
init_chooseEnvironment();
|
|
1698
1796
|
});
|
|
1699
1797
|
|
|
1700
|
-
// src/helpers/createProject.ts
|
|
1701
|
-
import { createId } from "@paralleldrive/cuid2";
|
|
1702
|
-
var createProject = async () => {
|
|
1703
|
-
return {
|
|
1704
|
-
projectId: createId()
|
|
1705
|
-
};
|
|
1706
|
-
};
|
|
1707
|
-
var init_createProject = () => {};
|
|
1708
|
-
|
|
1709
1798
|
// src/helpers/setupGitDiff.ts
|
|
1710
1799
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
1711
|
-
import
|
|
1712
|
-
import
|
|
1800
|
+
import fs10 from "node:fs";
|
|
1801
|
+
import path10 from "node:path";
|
|
1713
1802
|
var setupGitDiff = () => {
|
|
1714
|
-
const gitattributesPath =
|
|
1803
|
+
const gitattributesPath = path10.join(process.cwd(), ".gitattributes");
|
|
1715
1804
|
const marker = "*.enc diff=dotenc";
|
|
1716
1805
|
let content = "";
|
|
1717
|
-
if (
|
|
1718
|
-
content =
|
|
1806
|
+
if (fs10.existsSync(gitattributesPath)) {
|
|
1807
|
+
content = fs10.readFileSync(gitattributesPath, "utf-8");
|
|
1719
1808
|
}
|
|
1720
1809
|
if (!content.includes(marker)) {
|
|
1721
1810
|
const newline = content.length > 0 && !content.endsWith(`
|
|
1722
1811
|
`) ? `
|
|
1723
1812
|
` : "";
|
|
1724
|
-
|
|
1813
|
+
fs10.writeFileSync(gitattributesPath, `${content}${newline}${marker}
|
|
1725
1814
|
`);
|
|
1726
1815
|
}
|
|
1727
1816
|
spawnSync2("git", ["config", "--local", "diff.dotenc.textconv", "dotenc textconv"], {
|
|
@@ -1730,10 +1819,169 @@ var setupGitDiff = () => {
|
|
|
1730
1819
|
};
|
|
1731
1820
|
var init_setupGitDiff = () => {};
|
|
1732
1821
|
|
|
1733
|
-
// src/
|
|
1822
|
+
// src/helpers/createEd25519SshKey.ts
|
|
1823
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
1824
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
1825
|
+
import fs11 from "node:fs/promises";
|
|
1826
|
+
import os4 from "node:os";
|
|
1827
|
+
import path11 from "node:path";
|
|
1828
|
+
var DEFAULT_DOTENC_KEY_BASENAME = "id_ed25519_dotenc", defaultResolveNewKeyPathDeps, _resolveNewDotencSshKeyPath = (deps = defaultResolveNewKeyPathDeps) => {
|
|
1829
|
+
const sshDir = path11.join(os4.homedir(), ".ssh");
|
|
1830
|
+
const basePath = path11.join(sshDir, DEFAULT_DOTENC_KEY_BASENAME);
|
|
1831
|
+
if (!deps.existsSync(basePath) && !deps.existsSync(`${basePath}.pub`)) {
|
|
1832
|
+
return basePath;
|
|
1833
|
+
}
|
|
1834
|
+
for (let index = 1;index < 1000; index += 1) {
|
|
1835
|
+
const candidatePath = path11.join(sshDir, `${DEFAULT_DOTENC_KEY_BASENAME}_${index}`);
|
|
1836
|
+
if (!deps.existsSync(candidatePath) && !deps.existsSync(`${candidatePath}.pub`)) {
|
|
1837
|
+
return candidatePath;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
throw new Error("Could not determine an available SSH key path in ~/.ssh.");
|
|
1841
|
+
}, defaultCreateEd25519SshKeyDeps, createEd25519SshKey = async (deps = defaultCreateEd25519SshKeyDeps) => {
|
|
1842
|
+
const keyPath = deps.resolveNewSshKeyPath();
|
|
1843
|
+
await deps.mkdir(path11.dirname(keyPath), { recursive: true, mode: 448 });
|
|
1844
|
+
const result = deps.spawnSync("ssh-keygen", ["-t", "ed25519", "-f", keyPath, "-N", "", "-q", "-C", "dotenc"], {
|
|
1845
|
+
stdio: "pipe",
|
|
1846
|
+
encoding: "utf-8"
|
|
1847
|
+
});
|
|
1848
|
+
if (result.error) {
|
|
1849
|
+
throw new Error(`Failed to run ssh-keygen: ${result.error.message || "unknown error"}`);
|
|
1850
|
+
}
|
|
1851
|
+
if (typeof result.status === "number" && result.status !== 0) {
|
|
1852
|
+
const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
|
|
1853
|
+
const stdout = typeof result.stdout === "string" ? result.stdout.trim() : "";
|
|
1854
|
+
throw new Error(`ssh-keygen failed (${result.status}): ${stderr || stdout || "unknown error"}`);
|
|
1855
|
+
}
|
|
1856
|
+
return keyPath;
|
|
1857
|
+
};
|
|
1858
|
+
var init_createEd25519SshKey = __esm(() => {
|
|
1859
|
+
defaultResolveNewKeyPathDeps = {
|
|
1860
|
+
existsSync: existsSync6
|
|
1861
|
+
};
|
|
1862
|
+
defaultCreateEd25519SshKeyDeps = {
|
|
1863
|
+
mkdir: fs11.mkdir,
|
|
1864
|
+
spawnSync: spawnSync3,
|
|
1865
|
+
resolveNewSshKeyPath: () => _resolveNewDotencSshKeyPath()
|
|
1866
|
+
};
|
|
1867
|
+
});
|
|
1868
|
+
|
|
1869
|
+
// src/prompts/choosePrivateKey.ts
|
|
1870
|
+
import path12 from "node:path";
|
|
1871
|
+
import chalk12 from "chalk";
|
|
1734
1872
|
import inquirer5 from "inquirer";
|
|
1873
|
+
function toSupportedChoice(key) {
|
|
1874
|
+
return {
|
|
1875
|
+
name: `${key.name} (${key.algorithm})`,
|
|
1876
|
+
value: key.name
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1879
|
+
function toUnsupportedChoice(key, index) {
|
|
1880
|
+
return {
|
|
1881
|
+
name: `${chalk12.gray(key.name)} (${chalk12.yellow(key.reason)})`,
|
|
1882
|
+
value: `__unsupported_${index}__`,
|
|
1883
|
+
disabled: true
|
|
1884
|
+
};
|
|
1885
|
+
}
|
|
1886
|
+
var CREATE_NEW_PRIVATE_KEY_CHOICE = "__dotenc_create_new_private_key__", defaultChoosePrivateKeyPromptDeps, buildPromptChoices = (keys, unsupportedKeys) => {
|
|
1887
|
+
const choices = keys.map(toSupportedChoice);
|
|
1888
|
+
if (unsupportedKeys.length > 0) {
|
|
1889
|
+
if (choices.length > 0) {
|
|
1890
|
+
choices.push({
|
|
1891
|
+
name: chalk12.gray("────────"),
|
|
1892
|
+
value: "__separator_supported_unsupported__",
|
|
1893
|
+
disabled: true
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
choices.push({
|
|
1897
|
+
name: chalk12.gray("Unsupported keys (ignored)"),
|
|
1898
|
+
value: "__unsupported_header__",
|
|
1899
|
+
disabled: true
|
|
1900
|
+
});
|
|
1901
|
+
choices.push(...unsupportedKeys.map(toUnsupportedChoice));
|
|
1902
|
+
}
|
|
1903
|
+
if (choices.length > 0) {
|
|
1904
|
+
choices.push({
|
|
1905
|
+
name: chalk12.gray("────────"),
|
|
1906
|
+
value: "__separator_create__",
|
|
1907
|
+
disabled: true
|
|
1908
|
+
});
|
|
1909
|
+
}
|
|
1910
|
+
choices.push({
|
|
1911
|
+
name: "Create a new SSH key (ed25519, recommended)",
|
|
1912
|
+
value: CREATE_NEW_PRIVATE_KEY_CHOICE
|
|
1913
|
+
});
|
|
1914
|
+
return choices;
|
|
1915
|
+
}, _runChoosePrivateKeyPrompt = async (message, deps = defaultChoosePrivateKeyPromptDeps) => {
|
|
1916
|
+
for (;; ) {
|
|
1917
|
+
const {
|
|
1918
|
+
keys,
|
|
1919
|
+
passphraseProtectedKeys,
|
|
1920
|
+
unsupportedKeys = []
|
|
1921
|
+
} = await deps.getPrivateKeys();
|
|
1922
|
+
const privateKeyMap = new Map(keys.map((key) => [key.name, key]));
|
|
1923
|
+
if (!deps.isInteractive()) {
|
|
1924
|
+
if (keys.length > 0) {
|
|
1925
|
+
return keys[0];
|
|
1926
|
+
}
|
|
1927
|
+
if (passphraseProtectedKeys.length > 0) {
|
|
1928
|
+
throw new Error(passphraseProtectedKeyError(passphraseProtectedKeys));
|
|
1929
|
+
}
|
|
1930
|
+
if (unsupportedKeys.length > 0) {
|
|
1931
|
+
const unsupportedList = unsupportedKeys.map((key) => ` - ${key.name}: ${key.reason}`).join(`
|
|
1932
|
+
`);
|
|
1933
|
+
throw new Error(`No supported SSH keys found.
|
|
1934
|
+
|
|
1935
|
+
Unsupported keys:
|
|
1936
|
+
${unsupportedList}
|
|
1937
|
+
|
|
1938
|
+
Generate a new key with:
|
|
1939
|
+
ssh-keygen -t ed25519 -N ""`);
|
|
1940
|
+
}
|
|
1941
|
+
throw new Error('No SSH keys found in ~/.ssh/. Generate one with: ssh-keygen -t ed25519 -N ""');
|
|
1942
|
+
}
|
|
1943
|
+
const result = await deps.prompt([
|
|
1944
|
+
{
|
|
1945
|
+
type: "list",
|
|
1946
|
+
name: "key",
|
|
1947
|
+
message,
|
|
1948
|
+
choices: buildPromptChoices(keys, unsupportedKeys)
|
|
1949
|
+
}
|
|
1950
|
+
]);
|
|
1951
|
+
const selected = String(result.key || "");
|
|
1952
|
+
if (selected === CREATE_NEW_PRIVATE_KEY_CHOICE) {
|
|
1953
|
+
try {
|
|
1954
|
+
const createdPath = await deps.createEd25519SshKey();
|
|
1955
|
+
deps.logInfo(`${chalk12.green("✔")} Created ${chalk12.cyan(path12.basename(createdPath))} at ${chalk12.gray(createdPath)}.`);
|
|
1956
|
+
} catch (error) {
|
|
1957
|
+
deps.logWarn(`${chalk12.yellow("Warning:")} failed to create a new SSH key. ${error instanceof Error ? error.message : String(error)}`);
|
|
1958
|
+
}
|
|
1959
|
+
continue;
|
|
1960
|
+
}
|
|
1961
|
+
const selectedKey = privateKeyMap.get(selected);
|
|
1962
|
+
if (selectedKey) {
|
|
1963
|
+
return selectedKey;
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
}, choosePrivateKeyPrompt = async (message) => _runChoosePrivateKeyPrompt(message);
|
|
1967
|
+
var init_choosePrivateKey = __esm(() => {
|
|
1968
|
+
init_createEd25519SshKey();
|
|
1969
|
+
init_errors();
|
|
1970
|
+
init_getPrivateKeys();
|
|
1971
|
+
defaultChoosePrivateKeyPromptDeps = {
|
|
1972
|
+
getPrivateKeys,
|
|
1973
|
+
prompt: inquirer5.prompt,
|
|
1974
|
+
createEd25519SshKey,
|
|
1975
|
+
logInfo: console.log,
|
|
1976
|
+
logWarn: console.warn,
|
|
1977
|
+
isInteractive: () => Boolean(process.stdin.isTTY && process.stdout.isTTY)
|
|
1978
|
+
};
|
|
1979
|
+
});
|
|
1980
|
+
|
|
1981
|
+
// src/prompts/inputName.ts
|
|
1982
|
+
import inquirer6 from "inquirer";
|
|
1735
1983
|
var inputNamePrompt = async (message, defaultValue) => {
|
|
1736
|
-
const result = await
|
|
1984
|
+
const result = await inquirer6.prompt([
|
|
1737
1985
|
{
|
|
1738
1986
|
type: "input",
|
|
1739
1987
|
name: "name",
|
|
@@ -1818,9 +2066,9 @@ function validatePublicKey(key) {
|
|
|
1818
2066
|
}
|
|
1819
2067
|
|
|
1820
2068
|
// src/prompts/inputKey.ts
|
|
1821
|
-
import
|
|
2069
|
+
import inquirer7 from "inquirer";
|
|
1822
2070
|
var inputKeyPrompt = async (message, defaultValue) => {
|
|
1823
|
-
const result = await
|
|
2071
|
+
const result = await inquirer7.prompt([
|
|
1824
2072
|
{
|
|
1825
2073
|
type: "password",
|
|
1826
2074
|
name: "key",
|
|
@@ -1837,26 +2085,21 @@ var init_inputKey = () => {};
|
|
|
1837
2085
|
import crypto10 from "node:crypto";
|
|
1838
2086
|
import { existsSync as existsSync7 } from "node:fs";
|
|
1839
2087
|
import fs12 from "node:fs/promises";
|
|
1840
|
-
import
|
|
1841
|
-
import
|
|
1842
|
-
import
|
|
1843
|
-
import
|
|
2088
|
+
import os5 from "node:os";
|
|
2089
|
+
import path13 from "node:path";
|
|
2090
|
+
import chalk13 from "chalk";
|
|
2091
|
+
import inquirer8 from "inquirer";
|
|
1844
2092
|
var keyAddCommand = async (nameArg, options) => {
|
|
1845
|
-
const { projectId } = await getProjectConfig();
|
|
1846
|
-
if (!projectId) {
|
|
1847
|
-
console.error('No project found. Run "dotenc init" to create one.');
|
|
1848
|
-
process.exit(1);
|
|
1849
|
-
}
|
|
1850
2093
|
let publicKey;
|
|
1851
2094
|
if (options?.fromSsh) {
|
|
1852
|
-
const sshPath = options.fromSsh.startsWith("~") ?
|
|
2095
|
+
const sshPath = options.fromSsh.startsWith("~") ? path13.join(os5.homedir(), options.fromSsh.slice(1)) : options.fromSsh;
|
|
1853
2096
|
if (!existsSync7(sshPath)) {
|
|
1854
|
-
console.error(`File ${
|
|
2097
|
+
console.error(`File ${chalk13.cyan(sshPath)} does not exist. Please provide a valid SSH key path.`);
|
|
1855
2098
|
process.exit(1);
|
|
1856
2099
|
}
|
|
1857
2100
|
const keyContent = await fs12.readFile(sshPath, "utf-8");
|
|
1858
2101
|
if (isPassphraseProtected(keyContent)) {
|
|
1859
|
-
console.error(`${
|
|
2102
|
+
console.error(`${chalk13.red("Error:")} the provided key is passphrase-protected, which is not currently supported by dotenc.`);
|
|
1860
2103
|
process.exit(1);
|
|
1861
2104
|
}
|
|
1862
2105
|
try {
|
|
@@ -1879,12 +2122,12 @@ var keyAddCommand = async (nameArg, options) => {
|
|
|
1879
2122
|
}
|
|
1880
2123
|
if (options?.fromFile) {
|
|
1881
2124
|
if (!existsSync7(options.fromFile)) {
|
|
1882
|
-
console.error(`File ${
|
|
2125
|
+
console.error(`File ${chalk13.cyan(options.fromFile)} does not exist. Please provide a valid file path.`);
|
|
1883
2126
|
process.exit(1);
|
|
1884
2127
|
}
|
|
1885
2128
|
const keyContent = await fs12.readFile(options.fromFile, "utf-8");
|
|
1886
2129
|
if (isPassphraseProtected(keyContent)) {
|
|
1887
|
-
console.error(`${
|
|
2130
|
+
console.error(`${chalk13.red("Error:")} the provided key is passphrase-protected, which is not currently supported by dotenc.`);
|
|
1888
2131
|
process.exit(1);
|
|
1889
2132
|
}
|
|
1890
2133
|
try {
|
|
@@ -1906,7 +2149,7 @@ var keyAddCommand = async (nameArg, options) => {
|
|
|
1906
2149
|
}
|
|
1907
2150
|
if (options?.fromString) {
|
|
1908
2151
|
if (isPassphraseProtected(options.fromString)) {
|
|
1909
|
-
console.error(`${
|
|
2152
|
+
console.error(`${chalk13.red("Error:")} the provided key is passphrase-protected, which is not currently supported by dotenc.`);
|
|
1910
2153
|
process.exit(1);
|
|
1911
2154
|
}
|
|
1912
2155
|
try {
|
|
@@ -1927,23 +2170,12 @@ var keyAddCommand = async (nameArg, options) => {
|
|
|
1927
2170
|
}
|
|
1928
2171
|
}
|
|
1929
2172
|
if (!publicKey) {
|
|
1930
|
-
const
|
|
1931
|
-
if (sshKeys.length === 0 && passphraseProtectedKeys.length > 0) {
|
|
1932
|
-
console.warn(`${chalk12.yellow("Warning:")} SSH keys were found but are passphrase-protected (not supported by dotenc):
|
|
1933
|
-
${passphraseProtectedKeys.map((k) => ` - ${k}`).join(`
|
|
1934
|
-
`)}
|
|
1935
|
-
`);
|
|
1936
|
-
}
|
|
1937
|
-
const choices = sshKeys.map((key) => ({
|
|
1938
|
-
name: `${key.name} (${key.algorithm})`,
|
|
1939
|
-
value: key.name
|
|
1940
|
-
}));
|
|
1941
|
-
const modePrompt = await inquirer7.prompt({
|
|
2173
|
+
const modePrompt = await inquirer8.prompt({
|
|
1942
2174
|
type: "list",
|
|
1943
2175
|
name: "mode",
|
|
1944
2176
|
message: "Would you like to add one of your SSH keys or paste a public key?",
|
|
1945
2177
|
choices: [
|
|
1946
|
-
|
|
2178
|
+
{ name: "Choose or create an SSH key", value: "choose" },
|
|
1947
2179
|
{ name: "Paste a public key (PEM format)", value: "paste" }
|
|
1948
2180
|
]
|
|
1949
2181
|
});
|
|
@@ -1961,15 +2193,11 @@ ${passphraseProtectedKeys.map((k) => ` - ${k}`).join(`
|
|
|
1961
2193
|
process.exit(1);
|
|
1962
2194
|
}
|
|
1963
2195
|
} else {
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
});
|
|
1970
|
-
const selectedKey = sshKeys.find((k) => k.name === keyPrompt.key);
|
|
1971
|
-
if (!selectedKey) {
|
|
1972
|
-
console.error("SSH key not found.");
|
|
2196
|
+
let selectedKey;
|
|
2197
|
+
try {
|
|
2198
|
+
selectedKey = await choosePrivateKeyPrompt("Which SSH key do you want to add?");
|
|
2199
|
+
} catch (error) {
|
|
2200
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1973
2201
|
process.exit(1);
|
|
1974
2202
|
}
|
|
1975
2203
|
publicKey = crypto10.createPublicKey(selectedKey.privateKey);
|
|
@@ -1991,25 +2219,24 @@ ${passphraseProtectedKeys.map((k) => ` - ${k}`).join(`
|
|
|
1991
2219
|
type: "spki",
|
|
1992
2220
|
format: "pem"
|
|
1993
2221
|
});
|
|
1994
|
-
if (!existsSync7(
|
|
1995
|
-
await fs12.mkdir(
|
|
2222
|
+
if (!existsSync7(path13.join(process.cwd(), ".dotenc"))) {
|
|
2223
|
+
await fs12.mkdir(path13.join(process.cwd(), ".dotenc"));
|
|
1996
2224
|
}
|
|
1997
2225
|
let name = nameArg;
|
|
1998
2226
|
if (!name) {
|
|
1999
2227
|
name = await inputNamePrompt("What name do you want to give to the new public key?");
|
|
2000
|
-
if (existsSync7(
|
|
2001
|
-
console.error(`A public key with name ${
|
|
2228
|
+
if (existsSync7(path13.join(process.cwd(), ".dotenc", `${name}.pub`))) {
|
|
2229
|
+
console.error(`A public key with name ${chalk13.cyan(name)} already exists. Please choose a different name.`);
|
|
2002
2230
|
process.exit(1);
|
|
2003
2231
|
}
|
|
2004
2232
|
}
|
|
2005
|
-
await fs12.writeFile(
|
|
2233
|
+
await fs12.writeFile(path13.join(process.cwd(), ".dotenc", `${name}.pub`), publicKeyOutput, "utf-8");
|
|
2006
2234
|
console.log(`
|
|
2007
|
-
Public key ${
|
|
2235
|
+
Public key ${chalk13.cyan(name)} added successfully!`);
|
|
2008
2236
|
};
|
|
2009
2237
|
var init_add = __esm(() => {
|
|
2010
|
-
init_getPrivateKeys();
|
|
2011
2238
|
init_parseOpenSSHKey();
|
|
2012
|
-
|
|
2239
|
+
init_choosePrivateKey();
|
|
2013
2240
|
init_inputKey();
|
|
2014
2241
|
init_inputName();
|
|
2015
2242
|
});
|
|
@@ -2018,61 +2245,32 @@ var init_add = __esm(() => {
|
|
|
2018
2245
|
import crypto11 from "node:crypto";
|
|
2019
2246
|
import { existsSync as existsSync8 } from "node:fs";
|
|
2020
2247
|
import fs13 from "node:fs/promises";
|
|
2021
|
-
import
|
|
2022
|
-
import
|
|
2023
|
-
import
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
if (!privateKeys.length) {
|
|
2028
|
-
if (passphraseProtectedKeys.length > 0) {
|
|
2029
|
-
console.error(passphraseProtectedKeyError(passphraseProtectedKeys));
|
|
2030
|
-
} else {
|
|
2031
|
-
console.error(`${chalk13.red("Error:")} no SSH keys found in ~/.ssh/. Please generate one first using ${chalk13.gray("ssh-keygen")}.`);
|
|
2032
|
-
}
|
|
2033
|
-
process.exit(1);
|
|
2248
|
+
import os6 from "node:os";
|
|
2249
|
+
import path14 from "node:path";
|
|
2250
|
+
import chalk14 from "chalk";
|
|
2251
|
+
var _resolveDocsUrl = () => {
|
|
2252
|
+
if (typeof package_default.homepage === "string" && package_default.homepage.trim().length > 0) {
|
|
2253
|
+
return package_default.homepage;
|
|
2034
2254
|
}
|
|
2035
|
-
const
|
|
2255
|
+
const repositoryUrl = typeof package_default.repository === "string" ? package_default.repository : package_default.repository?.url;
|
|
2256
|
+
if (typeof repositoryUrl !== "string" || repositoryUrl.trim().length === 0) {
|
|
2257
|
+
return;
|
|
2258
|
+
}
|
|
2259
|
+
return repositoryUrl.replace(/^git\+/, "").replace(/\.git$/, "");
|
|
2260
|
+
}, initCommand = async (options) => {
|
|
2261
|
+
const username = options.name || await inputNamePrompt("What's your name?", os6.userInfo().username);
|
|
2036
2262
|
if (!username) {
|
|
2037
|
-
console.error(`${
|
|
2263
|
+
console.error(`${chalk14.red("Error:")} no name provided.`);
|
|
2038
2264
|
process.exit(1);
|
|
2039
2265
|
}
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
} catch (error) {
|
|
2046
|
-
console.error(`${chalk13.red("Error:")} failed to create the project.`);
|
|
2047
|
-
console.error(`${chalk13.red("Details:")} ${error instanceof Error ? error.message : error}`);
|
|
2048
|
-
process.exit(1);
|
|
2049
|
-
}
|
|
2050
|
-
}
|
|
2051
|
-
let keyToAdd;
|
|
2052
|
-
if (privateKeys.length === 1) {
|
|
2053
|
-
keyToAdd = privateKeys[0].name;
|
|
2054
|
-
} else {
|
|
2055
|
-
const result = await inquirer8.prompt([
|
|
2056
|
-
{
|
|
2057
|
-
type: "list",
|
|
2058
|
-
name: "key",
|
|
2059
|
-
message: "Which SSH key would you like to use?",
|
|
2060
|
-
choices: privateKeys.map((key) => ({
|
|
2061
|
-
name: `${key.name} (${key.algorithm})`,
|
|
2062
|
-
value: key.name
|
|
2063
|
-
}))
|
|
2064
|
-
}
|
|
2065
|
-
]);
|
|
2066
|
-
keyToAdd = result.key;
|
|
2067
|
-
}
|
|
2068
|
-
if (!keyToAdd) {
|
|
2069
|
-
console.error(`${chalk13.red("Error:")} no SSH key selected. Please select a key.`);
|
|
2266
|
+
let keyEntry;
|
|
2267
|
+
try {
|
|
2268
|
+
keyEntry = await choosePrivateKeyPrompt("Which SSH key would you like to use?");
|
|
2269
|
+
} catch (error) {
|
|
2270
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
2070
2271
|
process.exit(1);
|
|
2071
2272
|
}
|
|
2072
|
-
|
|
2073
|
-
if (!keyEntry)
|
|
2074
|
-
process.exit(1);
|
|
2075
|
-
console.log(`Adding key: ${chalk13.cyan(username)} (${keyEntry.algorithm})`);
|
|
2273
|
+
console.log(`Adding key: ${chalk14.cyan(username)} (${keyEntry.algorithm})`);
|
|
2076
2274
|
const publicKey = crypto11.createPublicKey(keyEntry.privateKey);
|
|
2077
2275
|
const publicKeyPem = publicKey.export({ type: "spki", format: "pem" }).toString();
|
|
2078
2276
|
await keyAddCommand(username, {
|
|
@@ -2081,36 +2279,47 @@ var initCommand = async (options) => {
|
|
|
2081
2279
|
try {
|
|
2082
2280
|
setupGitDiff();
|
|
2083
2281
|
} catch (_error) {
|
|
2084
|
-
console.warn(`${
|
|
2282
|
+
console.warn(`${chalk14.yellow("Warning:")} could not set up git diff driver. You can run ${chalk14.gray("dotenc init")} again inside a git repository.`);
|
|
2085
2283
|
}
|
|
2086
2284
|
let initialContent;
|
|
2087
|
-
const envPath =
|
|
2285
|
+
const envPath = path14.join(process.cwd(), ".env");
|
|
2088
2286
|
if (existsSync8(envPath)) {
|
|
2089
2287
|
initialContent = await fs13.readFile(envPath, "utf-8");
|
|
2090
2288
|
await fs13.unlink(envPath);
|
|
2091
|
-
console.log(`Migrated ${
|
|
2289
|
+
console.log(`Migrated ${chalk14.gray(".env")} contents to ${chalk14.cyan("development")} environment.`);
|
|
2290
|
+
}
|
|
2291
|
+
await createCommand("development", username, initialContent);
|
|
2292
|
+
if (username !== "development") {
|
|
2293
|
+
await createCommand(username, username);
|
|
2092
2294
|
}
|
|
2093
|
-
await createCommand(username, username, initialContent);
|
|
2094
2295
|
console.log(`
|
|
2095
|
-
${
|
|
2296
|
+
${chalk14.green("✔")} Initialization complete!`);
|
|
2096
2297
|
console.log(`
|
|
2097
2298
|
Some useful tips:`);
|
|
2098
|
-
const
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2299
|
+
const developmentEditCmd = chalk14.gray("dotenc env edit development");
|
|
2300
|
+
const personalEditCmd = chalk14.gray(`dotenc env edit ${username}`);
|
|
2301
|
+
console.log(`- Edit the development environment: ${developmentEditCmd}`);
|
|
2302
|
+
if (username !== "development") {
|
|
2303
|
+
console.log(`- Edit your personal environment: ${personalEditCmd}`);
|
|
2304
|
+
}
|
|
2305
|
+
const devEnvironmentChain = username === "development" ? "development" : `development,${username}`;
|
|
2306
|
+
const devCmd = chalk14.gray("dotenc dev <command>");
|
|
2307
|
+
console.log(`- Run in development mode: ${devCmd} ${chalk14.gray(`(loads ${devEnvironmentChain})`)}`);
|
|
2308
|
+
const docsUrl = _resolveDocsUrl();
|
|
2309
|
+
if (docsUrl) {
|
|
2310
|
+
console.log(`- Full docs: ${chalk14.gray(docsUrl)}`);
|
|
2311
|
+
}
|
|
2102
2312
|
if (existsSync8(".claude") || existsSync8("CLAUDE.md")) {
|
|
2103
|
-
console.log(`- Install the agent skill: ${
|
|
2313
|
+
console.log(`- Install the agent skill: ${chalk14.gray("dotenc tools install-agent-skill")}`);
|
|
2104
2314
|
}
|
|
2105
2315
|
if (existsSync8(".vscode") || existsSync8(".cursor") || existsSync8(".windsurf")) {
|
|
2106
|
-
console.log(`- Add the editor extension: ${
|
|
2316
|
+
console.log(`- Add the editor extension: ${chalk14.gray("dotenc tools install-vscode-extension")}`);
|
|
2107
2317
|
}
|
|
2108
2318
|
};
|
|
2109
2319
|
var init_init = __esm(() => {
|
|
2110
|
-
|
|
2111
|
-
init_errors();
|
|
2112
|
-
init_getPrivateKeys();
|
|
2320
|
+
init_package();
|
|
2113
2321
|
init_setupGitDiff();
|
|
2322
|
+
init_choosePrivateKey();
|
|
2114
2323
|
init_inputName();
|
|
2115
2324
|
init_create();
|
|
2116
2325
|
init_add();
|
|
@@ -2148,16 +2357,16 @@ var init_confirm = () => {};
|
|
|
2148
2357
|
// src/commands/key/remove.ts
|
|
2149
2358
|
import { existsSync as existsSync9 } from "node:fs";
|
|
2150
2359
|
import fs14 from "node:fs/promises";
|
|
2151
|
-
import
|
|
2152
|
-
import
|
|
2360
|
+
import path15 from "node:path";
|
|
2361
|
+
import chalk15 from "chalk";
|
|
2153
2362
|
var keyRemoveCommand = async (nameArg) => {
|
|
2154
2363
|
let name = nameArg;
|
|
2155
2364
|
if (!name) {
|
|
2156
2365
|
name = await choosePublicKeyPrompt("Which public key do you want to remove?");
|
|
2157
2366
|
}
|
|
2158
|
-
const filePath =
|
|
2367
|
+
const filePath = path15.join(process.cwd(), ".dotenc", `${name}.pub`);
|
|
2159
2368
|
if (!existsSync9(filePath)) {
|
|
2160
|
-
console.error(`Public key ${
|
|
2369
|
+
console.error(`Public key ${chalk15.cyan(name)} not found.`);
|
|
2161
2370
|
process.exit(1);
|
|
2162
2371
|
}
|
|
2163
2372
|
const allEnvironments = await getEnvironments();
|
|
@@ -2171,7 +2380,7 @@ var keyRemoveCommand = async (nameArg) => {
|
|
|
2171
2380
|
} catch {}
|
|
2172
2381
|
}
|
|
2173
2382
|
if (affectedEnvironments.length > 0) {
|
|
2174
|
-
console.log(`Key ${
|
|
2383
|
+
console.log(`Key ${chalk15.cyan(name)} has access to the following environments:`);
|
|
2175
2384
|
for (const env of affectedEnvironments) {
|
|
2176
2385
|
console.log(` - ${env}`);
|
|
2177
2386
|
}
|
|
@@ -2184,7 +2393,7 @@ Access will be revoked from these environments automatically.`);
|
|
|
2184
2393
|
return;
|
|
2185
2394
|
}
|
|
2186
2395
|
await fs14.unlink(filePath);
|
|
2187
|
-
console.log(`Public key ${
|
|
2396
|
+
console.log(`Public key ${chalk15.cyan(name)} removed successfully.`);
|
|
2188
2397
|
for (const envName of affectedEnvironments) {
|
|
2189
2398
|
try {
|
|
2190
2399
|
const envJson = await getEnvironmentByName(envName);
|
|
@@ -2192,9 +2401,9 @@ Access will be revoked from these environments automatically.`);
|
|
|
2192
2401
|
await encryptEnvironment(envName, content, {
|
|
2193
2402
|
revokePublicKeys: [name]
|
|
2194
2403
|
});
|
|
2195
|
-
console.log(`Revoked access from ${
|
|
2404
|
+
console.log(`Revoked access from ${chalk15.cyan(envName)} environment.`);
|
|
2196
2405
|
} catch {
|
|
2197
|
-
console.warn(`${
|
|
2406
|
+
console.warn(`${chalk15.yellow("Warning:")} could not revoke access from ${chalk15.cyan(envName)}. You may need to run ${chalk15.gray(`dotenc auth revoke ${envName} ${name}`)} manually or rotate the environment.`);
|
|
2198
2407
|
}
|
|
2199
2408
|
}
|
|
2200
2409
|
};
|
|
@@ -2209,9 +2418,9 @@ var init_remove = __esm(() => {
|
|
|
2209
2418
|
|
|
2210
2419
|
// src/commands/textconv.ts
|
|
2211
2420
|
import fs15 from "node:fs/promises";
|
|
2212
|
-
import
|
|
2421
|
+
import path16 from "node:path";
|
|
2213
2422
|
var textconvCommand = async (filePath) => {
|
|
2214
|
-
const absolutePath =
|
|
2423
|
+
const absolutePath = path16.isAbsolute(filePath) ? filePath : path16.join(process.cwd(), filePath);
|
|
2215
2424
|
try {
|
|
2216
2425
|
const environment = await getEnvironmentByPath(absolutePath);
|
|
2217
2426
|
const plaintext = await decryptEnvironmentData(environment);
|
|
@@ -2228,18 +2437,18 @@ var init_textconv = __esm(() => {
|
|
|
2228
2437
|
|
|
2229
2438
|
// src/commands/tools/install-agent-skill.ts
|
|
2230
2439
|
import { spawn as spawn2 } from "node:child_process";
|
|
2231
|
-
import
|
|
2440
|
+
import chalk16 from "chalk";
|
|
2232
2441
|
import inquirer10 from "inquirer";
|
|
2233
|
-
var SKILL_SOURCE = "ivanfilhoz/dotenc", SKILL_NAME = "dotenc", runNpx = (args) => new Promise((resolve, reject) => {
|
|
2234
|
-
const child =
|
|
2442
|
+
var SKILL_SOURCE = "ivanfilhoz/dotenc", SKILL_NAME = "dotenc", runNpx = (args, spawnImpl = spawn2) => new Promise((resolve, reject) => {
|
|
2443
|
+
const child = spawnImpl("npx", args, {
|
|
2235
2444
|
stdio: "inherit",
|
|
2236
2445
|
shell: process.platform === "win32"
|
|
2237
2446
|
});
|
|
2238
2447
|
child.on("error", reject);
|
|
2239
2448
|
child.on("exit", (code) => resolve(code ?? 1));
|
|
2240
|
-
}),
|
|
2449
|
+
}), defaultDeps2, _runInstallAgentSkillCommand = async (options, depsOverrides = {}) => {
|
|
2241
2450
|
const deps = {
|
|
2242
|
-
...
|
|
2451
|
+
...defaultDeps2,
|
|
2243
2452
|
...depsOverrides
|
|
2244
2453
|
};
|
|
2245
2454
|
const { scope } = await deps.prompt([
|
|
@@ -2265,21 +2474,21 @@ var SKILL_SOURCE = "ivanfilhoz/dotenc", SKILL_NAME = "dotenc", runNpx = (args) =
|
|
|
2265
2474
|
try {
|
|
2266
2475
|
exitCode = await deps.runNpx(args);
|
|
2267
2476
|
} catch (error) {
|
|
2268
|
-
deps.logError(`${
|
|
2269
|
-
deps.logError(`${
|
|
2477
|
+
deps.logError(`${chalk16.red("Error:")} failed to run ${chalk16.gray(npxCommand)}.`);
|
|
2478
|
+
deps.logError(`${chalk16.red("Details:")} ${error instanceof Error ? error.message : String(error)}`);
|
|
2270
2479
|
deps.exit(1);
|
|
2271
2480
|
}
|
|
2272
2481
|
if (exitCode !== 0) {
|
|
2273
|
-
deps.logError(`${
|
|
2482
|
+
deps.logError(`${chalk16.red("Error:")} skill installation command exited with code ${exitCode}.`);
|
|
2274
2483
|
deps.exit(exitCode);
|
|
2275
2484
|
}
|
|
2276
|
-
deps.log(`${
|
|
2277
|
-
deps.log(`Run ${
|
|
2485
|
+
deps.log(`${chalk16.green("✓")} Agent skill installation completed via ${chalk16.gray(npxCommand)}.`);
|
|
2486
|
+
deps.log(`Run ${chalk16.gray("/dotenc")} in your agent to use it.`);
|
|
2278
2487
|
}, installAgentSkillCommand = async (options) => {
|
|
2279
2488
|
await _runInstallAgentSkillCommand(options);
|
|
2280
2489
|
};
|
|
2281
2490
|
var init_install_agent_skill = __esm(() => {
|
|
2282
|
-
|
|
2491
|
+
defaultDeps2 = {
|
|
2283
2492
|
prompt: inquirer10.prompt,
|
|
2284
2493
|
runNpx,
|
|
2285
2494
|
log: console.log,
|
|
@@ -2292,12 +2501,12 @@ var init_install_agent_skill = __esm(() => {
|
|
|
2292
2501
|
import { exec, execFile } from "node:child_process";
|
|
2293
2502
|
import { existsSync as existsSync10 } from "node:fs";
|
|
2294
2503
|
import fs16 from "node:fs/promises";
|
|
2295
|
-
import
|
|
2504
|
+
import path17 from "node:path";
|
|
2296
2505
|
import { promisify } from "node:util";
|
|
2297
|
-
import
|
|
2506
|
+
import chalk17 from "chalk";
|
|
2298
2507
|
import inquirer11 from "inquirer";
|
|
2299
2508
|
async function addToExtensionsJson() {
|
|
2300
|
-
const extensionsJsonPath =
|
|
2509
|
+
const extensionsJsonPath = path17.join(process.cwd(), ".vscode", "extensions.json");
|
|
2301
2510
|
let json = {};
|
|
2302
2511
|
if (existsSync10(extensionsJsonPath)) {
|
|
2303
2512
|
const content = await fs16.readFile(extensionsJsonPath, "utf-8");
|
|
@@ -2307,7 +2516,7 @@ async function addToExtensionsJson() {
|
|
|
2307
2516
|
json = {};
|
|
2308
2517
|
}
|
|
2309
2518
|
} else {
|
|
2310
|
-
await fs16.mkdir(
|
|
2519
|
+
await fs16.mkdir(path17.join(process.cwd(), ".vscode"), { recursive: true });
|
|
2311
2520
|
}
|
|
2312
2521
|
if (!Array.isArray(json.recommendations)) {
|
|
2313
2522
|
json.recommendations = [];
|
|
@@ -2315,9 +2524,9 @@ async function addToExtensionsJson() {
|
|
|
2315
2524
|
if (!json.recommendations.includes(EXTENSION_ID)) {
|
|
2316
2525
|
json.recommendations.push(EXTENSION_ID);
|
|
2317
2526
|
await fs16.writeFile(extensionsJsonPath, JSON.stringify(json, null, 2), "utf-8");
|
|
2318
|
-
console.log(`${
|
|
2527
|
+
console.log(`${chalk17.green("✓")} Added dotenc to ${chalk17.gray(".vscode/extensions.json")}`);
|
|
2319
2528
|
} else {
|
|
2320
|
-
console.log(`${
|
|
2529
|
+
console.log(`${chalk17.green("✓")} dotenc already in ${chalk17.gray(".vscode/extensions.json")}`);
|
|
2321
2530
|
}
|
|
2322
2531
|
}
|
|
2323
2532
|
async function which(bin) {
|
|
@@ -2330,11 +2539,11 @@ async function which(bin) {
|
|
|
2330
2539
|
}
|
|
2331
2540
|
async function detectEditors() {
|
|
2332
2541
|
const detected = [];
|
|
2333
|
-
if (existsSync10(
|
|
2542
|
+
if (existsSync10(path17.join(process.cwd(), ".cursor")))
|
|
2334
2543
|
detected.push("cursor");
|
|
2335
|
-
if (existsSync10(
|
|
2544
|
+
if (existsSync10(path17.join(process.cwd(), ".windsurf")))
|
|
2336
2545
|
detected.push("windsurf");
|
|
2337
|
-
if (existsSync10(
|
|
2546
|
+
if (existsSync10(path17.join(process.cwd(), ".vscode")))
|
|
2338
2547
|
detected.push("vscode");
|
|
2339
2548
|
const checks = [
|
|
2340
2549
|
{ key: "cursor", bins: ["cursor"] },
|
|
@@ -2381,7 +2590,7 @@ async function _runInstallVscodeExtension(getEditors = detectEditors, _openUrl =
|
|
|
2381
2590
|
await addToExtensionsJson();
|
|
2382
2591
|
if (editors.length === 0) {
|
|
2383
2592
|
console.log(`
|
|
2384
|
-
Install the extension in VS Code: ${
|
|
2593
|
+
Install the extension in VS Code: ${chalk17.cyan(EDITOR_PROTOCOL_URLS.vscode)}`);
|
|
2385
2594
|
return;
|
|
2386
2595
|
}
|
|
2387
2596
|
if (editors.length === 1) {
|
|
@@ -2400,10 +2609,10 @@ Install the extension in VS Code: ${chalk16.cyan(EDITOR_PROTOCOL_URLS.vscode)}`)
|
|
|
2400
2609
|
try {
|
|
2401
2610
|
await _openUrl(url);
|
|
2402
2611
|
} catch {
|
|
2403
|
-
console.log(`Open manually: ${
|
|
2612
|
+
console.log(`Open manually: ${chalk17.cyan(url)}`);
|
|
2404
2613
|
}
|
|
2405
2614
|
} else {
|
|
2406
|
-
console.log(`Install manually: ${
|
|
2615
|
+
console.log(`Install manually: ${chalk17.cyan(url)}`);
|
|
2407
2616
|
}
|
|
2408
2617
|
return;
|
|
2409
2618
|
}
|
|
@@ -2412,7 +2621,7 @@ Install the extension in your editor:`);
|
|
|
2412
2621
|
for (const editor of editors) {
|
|
2413
2622
|
const name = EDITOR_NAMES[editor] ?? editor;
|
|
2414
2623
|
const url = EDITOR_PROTOCOL_URLS[editor];
|
|
2415
|
-
console.log(` ${name}: ${
|
|
2624
|
+
console.log(` ${name}: ${chalk17.cyan(url)}`);
|
|
2416
2625
|
}
|
|
2417
2626
|
}
|
|
2418
2627
|
var execFileAsync, execAsync, EXTENSION_ID = "dotenc.dotenc", EDITOR_PROTOCOL_URLS, EDITOR_NAMES, installVscodeExtensionCommand = async () => {
|
|
@@ -2519,31 +2728,31 @@ var init_update = () => {};
|
|
|
2519
2728
|
|
|
2520
2729
|
// src/commands/update.ts
|
|
2521
2730
|
import { spawn as spawn3 } from "node:child_process";
|
|
2522
|
-
import
|
|
2523
|
-
var runPackageManagerCommand = (command, args) => new Promise((resolve, reject) => {
|
|
2524
|
-
const child =
|
|
2731
|
+
import chalk18 from "chalk";
|
|
2732
|
+
var runPackageManagerCommand = (command, args, spawnImpl = spawn3) => new Promise((resolve, reject) => {
|
|
2733
|
+
const child = spawnImpl(command, args, {
|
|
2525
2734
|
stdio: "inherit",
|
|
2526
2735
|
shell: process.platform === "win32"
|
|
2527
2736
|
});
|
|
2528
2737
|
child.on("error", reject);
|
|
2529
2738
|
child.on("exit", (code) => resolve(code ?? 1));
|
|
2530
|
-
}),
|
|
2739
|
+
}), defaultDeps3, updateCommands, _runUpdateCommand = async (depsOverrides = {}) => {
|
|
2531
2740
|
const deps = {
|
|
2532
|
-
...
|
|
2741
|
+
...defaultDeps3,
|
|
2533
2742
|
...depsOverrides
|
|
2534
2743
|
};
|
|
2535
2744
|
const method = deps.detectInstallMethod();
|
|
2536
2745
|
if (method === "binary") {
|
|
2537
|
-
deps.log(`Standalone binary detected. Download the latest release at ${
|
|
2746
|
+
deps.log(`Standalone binary detected. Download the latest release at ${chalk18.cyan(GITHUB_RELEASES_URL)}.`);
|
|
2538
2747
|
return;
|
|
2539
2748
|
}
|
|
2540
2749
|
if (method === "unknown") {
|
|
2541
2750
|
deps.log("Could not determine installation method automatically.");
|
|
2542
2751
|
deps.log(`Try one of these commands:`);
|
|
2543
|
-
deps.log(` ${
|
|
2544
|
-
deps.log(` ${
|
|
2545
|
-
deps.log(` ${
|
|
2546
|
-
deps.log(`Or download from ${
|
|
2752
|
+
deps.log(` ${chalk18.gray("brew upgrade dotenc")}`);
|
|
2753
|
+
deps.log(` ${chalk18.gray("scoop update dotenc")}`);
|
|
2754
|
+
deps.log(` ${chalk18.gray("npm install -g @dotenc/cli")}`);
|
|
2755
|
+
deps.log(`Or download from ${chalk18.cyan(GITHUB_RELEASES_URL)}.`);
|
|
2547
2756
|
return;
|
|
2548
2757
|
}
|
|
2549
2758
|
const updater = updateCommands[method];
|
|
@@ -2552,12 +2761,12 @@ var runPackageManagerCommand = (command, args) => new Promise((resolve, reject)
|
|
|
2552
2761
|
try {
|
|
2553
2762
|
exitCode = await deps.runPackageManagerCommand(updater.command, updater.args);
|
|
2554
2763
|
} catch (error) {
|
|
2555
|
-
deps.logError(`${
|
|
2556
|
-
deps.logError(`${
|
|
2764
|
+
deps.logError(`${chalk18.red("Error:")} failed to run ${chalk18.gray([updater.command, ...updater.args].join(" "))}.`);
|
|
2765
|
+
deps.logError(`${chalk18.red("Details:")} ${error instanceof Error ? error.message : String(error)}`);
|
|
2557
2766
|
deps.exit(1);
|
|
2558
2767
|
}
|
|
2559
2768
|
if (exitCode !== 0) {
|
|
2560
|
-
deps.logError(`${
|
|
2769
|
+
deps.logError(`${chalk18.red("Error:")} update command exited with code ${exitCode}.`);
|
|
2561
2770
|
deps.exit(exitCode);
|
|
2562
2771
|
}
|
|
2563
2772
|
}, updateCommand = async () => {
|
|
@@ -2565,7 +2774,7 @@ var runPackageManagerCommand = (command, args) => new Promise((resolve, reject)
|
|
|
2565
2774
|
};
|
|
2566
2775
|
var init_update2 = __esm(() => {
|
|
2567
2776
|
init_update();
|
|
2568
|
-
|
|
2777
|
+
defaultDeps3 = {
|
|
2569
2778
|
detectInstallMethod,
|
|
2570
2779
|
runPackageManagerCommand,
|
|
2571
2780
|
log: console.log,
|
|
@@ -2644,8 +2853,8 @@ var init_whoami = __esm(() => {
|
|
|
2644
2853
|
});
|
|
2645
2854
|
|
|
2646
2855
|
// src/helpers/updateNotifier.ts
|
|
2647
|
-
import
|
|
2648
|
-
var CHECK_INTERVAL_MS,
|
|
2856
|
+
import chalk19 from "chalk";
|
|
2857
|
+
var CHECK_INTERVAL_MS, defaultDeps4, shouldSkipCheck = (args, env) => {
|
|
2649
2858
|
if (env.DOTENC_SKIP_UPDATE_CHECK === "1") {
|
|
2650
2859
|
return true;
|
|
2651
2860
|
}
|
|
@@ -2667,7 +2876,7 @@ var CHECK_INTERVAL_MS, defaultDeps3, shouldSkipCheck = (args, env) => {
|
|
|
2667
2876
|
} catch {}
|
|
2668
2877
|
}, maybeNotifyAboutUpdate = async (depsOverrides = {}) => {
|
|
2669
2878
|
const deps = {
|
|
2670
|
-
...
|
|
2879
|
+
...defaultDeps4,
|
|
2671
2880
|
...depsOverrides
|
|
2672
2881
|
};
|
|
2673
2882
|
if (shouldSkipCheck(deps.args, deps.env)) {
|
|
@@ -2700,7 +2909,7 @@ var CHECK_INTERVAL_MS, defaultDeps3, shouldSkipCheck = (args, env) => {
|
|
|
2700
2909
|
if (updateState.notifiedVersion === latestVersion) {
|
|
2701
2910
|
return;
|
|
2702
2911
|
}
|
|
2703
|
-
deps.log(`${
|
|
2912
|
+
deps.log(`${chalk19.yellow("Update available:")} ${chalk19.gray(`dotenc ${deps.currentVersion}`)} -> ${chalk19.cyan(`dotenc ${latestVersion}`)}. Run ${chalk19.gray("dotenc update")}.`);
|
|
2704
2913
|
updateState = {
|
|
2705
2914
|
...updateState,
|
|
2706
2915
|
notifiedVersion: latestVersion
|
|
@@ -2712,7 +2921,7 @@ var init_updateNotifier = __esm(() => {
|
|
|
2712
2921
|
init_homeConfig();
|
|
2713
2922
|
init_update();
|
|
2714
2923
|
CHECK_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
2715
|
-
|
|
2924
|
+
defaultDeps4 = {
|
|
2716
2925
|
getHomeConfig,
|
|
2717
2926
|
setHomeConfig,
|
|
2718
2927
|
fetchLatestVersion,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotenc/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "🔐 Git-native encrypted environments powered by your SSH keys",
|
|
5
5
|
"author": "Ivan Filho <i@ivanfilho.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
"typescript": "^5.8.2"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@paralleldrive/cuid2": "^2.2.2",
|
|
35
34
|
"chalk": "^5.4.1",
|
|
36
35
|
"commander": "^13.1.0",
|
|
37
36
|
"eciesjs": "^0.4.15",
|