@dotenc/cli 0.5.1 → 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 +444 -234
- 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
|
});
|
|
@@ -1361,8 +1459,9 @@ var defaultDecryptCommandDeps, ansiPattern, stripAnsi = (value) => value.replace
|
|
|
1361
1459
|
try {
|
|
1362
1460
|
const environment = await deps.getEnvironmentByName(environmentName);
|
|
1363
1461
|
const plaintext = await deps.decryptEnvironmentData(environment);
|
|
1462
|
+
const grantedUsers = Array.from(new Set(environment.keys.map((key) => key.name.trim()).filter((name) => name.length > 0)));
|
|
1364
1463
|
if (options.json) {
|
|
1365
|
-
writeJson({ ok: true, content: plaintext }, deps);
|
|
1464
|
+
writeJson({ ok: true, content: plaintext, grantedUsers }, deps);
|
|
1366
1465
|
} else {
|
|
1367
1466
|
deps.writeStdout(plaintext);
|
|
1368
1467
|
}
|
|
@@ -1445,10 +1544,10 @@ var init_getDefaultEditor = __esm(() => {
|
|
|
1445
1544
|
|
|
1446
1545
|
// src/commands/env/edit.ts
|
|
1447
1546
|
import { spawnSync } from "node:child_process";
|
|
1448
|
-
import { existsSync as
|
|
1449
|
-
import
|
|
1547
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
1548
|
+
import fs9 from "node:fs/promises";
|
|
1450
1549
|
import os3 from "node:os";
|
|
1451
|
-
import
|
|
1550
|
+
import path9 from "node:path";
|
|
1452
1551
|
import chalk10 from "chalk";
|
|
1453
1552
|
var editCommand = async (environmentNameArg) => {
|
|
1454
1553
|
const environmentName = environmentNameArg || await chooseEnvironmentPrompt("What environment do you want to edit?");
|
|
@@ -1458,8 +1557,8 @@ var editCommand = async (environmentNameArg) => {
|
|
|
1458
1557
|
process.exit(1);
|
|
1459
1558
|
}
|
|
1460
1559
|
const environmentFile = `.env.${environmentName}.enc`;
|
|
1461
|
-
const environmentFilePath =
|
|
1462
|
-
if (!
|
|
1560
|
+
const environmentFilePath = path9.join(process.cwd(), environmentFile);
|
|
1561
|
+
if (!existsSync5(environmentFilePath)) {
|
|
1463
1562
|
console.error(`Environment file not found: ${environmentFilePath}`);
|
|
1464
1563
|
process.exit(1);
|
|
1465
1564
|
}
|
|
@@ -1483,15 +1582,15 @@ ${environment.keys.map((key) => `# - ${key.name}`).join(`
|
|
|
1483
1582
|
# Use 'dotenc auth grant' and/or 'dotenc auth revoke' to manage access.
|
|
1484
1583
|
# Make sure to save your changes before closing the editor.
|
|
1485
1584
|
${separator}${content}`;
|
|
1486
|
-
const tempDir = await
|
|
1487
|
-
const tempFilePath =
|
|
1488
|
-
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 });
|
|
1489
1588
|
const initialHash = createHash(content);
|
|
1490
1589
|
const cleanup = async () => {
|
|
1491
|
-
await
|
|
1590
|
+
await fs9.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
|
1492
1591
|
};
|
|
1493
1592
|
const onSignal = () => {
|
|
1494
|
-
|
|
1593
|
+
fs9.rm(tempDir, { recursive: true, force: true }).catch(() => {}).finally(() => process.exit(130));
|
|
1495
1594
|
};
|
|
1496
1595
|
process.on("SIGINT", onSignal);
|
|
1497
1596
|
process.on("SIGTERM", onSignal);
|
|
@@ -1506,7 +1605,7 @@ ${separator}${content}`;
|
|
|
1506
1605
|
Editor exited with code ${result.status}`);
|
|
1507
1606
|
process.exit(1);
|
|
1508
1607
|
}
|
|
1509
|
-
let newContent = await
|
|
1608
|
+
let newContent = await fs9.readFile(tempFilePath, "utf-8");
|
|
1510
1609
|
const finalHash = createHash(newContent);
|
|
1511
1610
|
if (initialHash === finalHash) {
|
|
1512
1611
|
console.log(`
|
|
@@ -1696,31 +1795,22 @@ var init_rotate = __esm(() => {
|
|
|
1696
1795
|
init_chooseEnvironment();
|
|
1697
1796
|
});
|
|
1698
1797
|
|
|
1699
|
-
// src/helpers/createProject.ts
|
|
1700
|
-
import { createId } from "@paralleldrive/cuid2";
|
|
1701
|
-
var createProject = async () => {
|
|
1702
|
-
return {
|
|
1703
|
-
projectId: createId()
|
|
1704
|
-
};
|
|
1705
|
-
};
|
|
1706
|
-
var init_createProject = () => {};
|
|
1707
|
-
|
|
1708
1798
|
// src/helpers/setupGitDiff.ts
|
|
1709
1799
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
1710
|
-
import
|
|
1711
|
-
import
|
|
1800
|
+
import fs10 from "node:fs";
|
|
1801
|
+
import path10 from "node:path";
|
|
1712
1802
|
var setupGitDiff = () => {
|
|
1713
|
-
const gitattributesPath =
|
|
1803
|
+
const gitattributesPath = path10.join(process.cwd(), ".gitattributes");
|
|
1714
1804
|
const marker = "*.enc diff=dotenc";
|
|
1715
1805
|
let content = "";
|
|
1716
|
-
if (
|
|
1717
|
-
content =
|
|
1806
|
+
if (fs10.existsSync(gitattributesPath)) {
|
|
1807
|
+
content = fs10.readFileSync(gitattributesPath, "utf-8");
|
|
1718
1808
|
}
|
|
1719
1809
|
if (!content.includes(marker)) {
|
|
1720
1810
|
const newline = content.length > 0 && !content.endsWith(`
|
|
1721
1811
|
`) ? `
|
|
1722
1812
|
` : "";
|
|
1723
|
-
|
|
1813
|
+
fs10.writeFileSync(gitattributesPath, `${content}${newline}${marker}
|
|
1724
1814
|
`);
|
|
1725
1815
|
}
|
|
1726
1816
|
spawnSync2("git", ["config", "--local", "diff.dotenc.textconv", "dotenc textconv"], {
|
|
@@ -1729,10 +1819,169 @@ var setupGitDiff = () => {
|
|
|
1729
1819
|
};
|
|
1730
1820
|
var init_setupGitDiff = () => {};
|
|
1731
1821
|
|
|
1732
|
-
// 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";
|
|
1733
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";
|
|
1734
1983
|
var inputNamePrompt = async (message, defaultValue) => {
|
|
1735
|
-
const result = await
|
|
1984
|
+
const result = await inquirer6.prompt([
|
|
1736
1985
|
{
|
|
1737
1986
|
type: "input",
|
|
1738
1987
|
name: "name",
|
|
@@ -1817,9 +2066,9 @@ function validatePublicKey(key) {
|
|
|
1817
2066
|
}
|
|
1818
2067
|
|
|
1819
2068
|
// src/prompts/inputKey.ts
|
|
1820
|
-
import
|
|
2069
|
+
import inquirer7 from "inquirer";
|
|
1821
2070
|
var inputKeyPrompt = async (message, defaultValue) => {
|
|
1822
|
-
const result = await
|
|
2071
|
+
const result = await inquirer7.prompt([
|
|
1823
2072
|
{
|
|
1824
2073
|
type: "password",
|
|
1825
2074
|
name: "key",
|
|
@@ -1836,26 +2085,21 @@ var init_inputKey = () => {};
|
|
|
1836
2085
|
import crypto10 from "node:crypto";
|
|
1837
2086
|
import { existsSync as existsSync7 } from "node:fs";
|
|
1838
2087
|
import fs12 from "node:fs/promises";
|
|
1839
|
-
import
|
|
1840
|
-
import
|
|
1841
|
-
import
|
|
1842
|
-
import
|
|
2088
|
+
import os5 from "node:os";
|
|
2089
|
+
import path13 from "node:path";
|
|
2090
|
+
import chalk13 from "chalk";
|
|
2091
|
+
import inquirer8 from "inquirer";
|
|
1843
2092
|
var keyAddCommand = async (nameArg, options) => {
|
|
1844
|
-
const { projectId } = await getProjectConfig();
|
|
1845
|
-
if (!projectId) {
|
|
1846
|
-
console.error('No project found. Run "dotenc init" to create one.');
|
|
1847
|
-
process.exit(1);
|
|
1848
|
-
}
|
|
1849
2093
|
let publicKey;
|
|
1850
2094
|
if (options?.fromSsh) {
|
|
1851
|
-
const sshPath = options.fromSsh.startsWith("~") ?
|
|
2095
|
+
const sshPath = options.fromSsh.startsWith("~") ? path13.join(os5.homedir(), options.fromSsh.slice(1)) : options.fromSsh;
|
|
1852
2096
|
if (!existsSync7(sshPath)) {
|
|
1853
|
-
console.error(`File ${
|
|
2097
|
+
console.error(`File ${chalk13.cyan(sshPath)} does not exist. Please provide a valid SSH key path.`);
|
|
1854
2098
|
process.exit(1);
|
|
1855
2099
|
}
|
|
1856
2100
|
const keyContent = await fs12.readFile(sshPath, "utf-8");
|
|
1857
2101
|
if (isPassphraseProtected(keyContent)) {
|
|
1858
|
-
console.error(`${
|
|
2102
|
+
console.error(`${chalk13.red("Error:")} the provided key is passphrase-protected, which is not currently supported by dotenc.`);
|
|
1859
2103
|
process.exit(1);
|
|
1860
2104
|
}
|
|
1861
2105
|
try {
|
|
@@ -1878,12 +2122,12 @@ var keyAddCommand = async (nameArg, options) => {
|
|
|
1878
2122
|
}
|
|
1879
2123
|
if (options?.fromFile) {
|
|
1880
2124
|
if (!existsSync7(options.fromFile)) {
|
|
1881
|
-
console.error(`File ${
|
|
2125
|
+
console.error(`File ${chalk13.cyan(options.fromFile)} does not exist. Please provide a valid file path.`);
|
|
1882
2126
|
process.exit(1);
|
|
1883
2127
|
}
|
|
1884
2128
|
const keyContent = await fs12.readFile(options.fromFile, "utf-8");
|
|
1885
2129
|
if (isPassphraseProtected(keyContent)) {
|
|
1886
|
-
console.error(`${
|
|
2130
|
+
console.error(`${chalk13.red("Error:")} the provided key is passphrase-protected, which is not currently supported by dotenc.`);
|
|
1887
2131
|
process.exit(1);
|
|
1888
2132
|
}
|
|
1889
2133
|
try {
|
|
@@ -1905,7 +2149,7 @@ var keyAddCommand = async (nameArg, options) => {
|
|
|
1905
2149
|
}
|
|
1906
2150
|
if (options?.fromString) {
|
|
1907
2151
|
if (isPassphraseProtected(options.fromString)) {
|
|
1908
|
-
console.error(`${
|
|
2152
|
+
console.error(`${chalk13.red("Error:")} the provided key is passphrase-protected, which is not currently supported by dotenc.`);
|
|
1909
2153
|
process.exit(1);
|
|
1910
2154
|
}
|
|
1911
2155
|
try {
|
|
@@ -1926,23 +2170,12 @@ var keyAddCommand = async (nameArg, options) => {
|
|
|
1926
2170
|
}
|
|
1927
2171
|
}
|
|
1928
2172
|
if (!publicKey) {
|
|
1929
|
-
const
|
|
1930
|
-
if (sshKeys.length === 0 && passphraseProtectedKeys.length > 0) {
|
|
1931
|
-
console.warn(`${chalk12.yellow("Warning:")} SSH keys were found but are passphrase-protected (not supported by dotenc):
|
|
1932
|
-
${passphraseProtectedKeys.map((k) => ` - ${k}`).join(`
|
|
1933
|
-
`)}
|
|
1934
|
-
`);
|
|
1935
|
-
}
|
|
1936
|
-
const choices = sshKeys.map((key) => ({
|
|
1937
|
-
name: `${key.name} (${key.algorithm})`,
|
|
1938
|
-
value: key.name
|
|
1939
|
-
}));
|
|
1940
|
-
const modePrompt = await inquirer7.prompt({
|
|
2173
|
+
const modePrompt = await inquirer8.prompt({
|
|
1941
2174
|
type: "list",
|
|
1942
2175
|
name: "mode",
|
|
1943
2176
|
message: "Would you like to add one of your SSH keys or paste a public key?",
|
|
1944
2177
|
choices: [
|
|
1945
|
-
|
|
2178
|
+
{ name: "Choose or create an SSH key", value: "choose" },
|
|
1946
2179
|
{ name: "Paste a public key (PEM format)", value: "paste" }
|
|
1947
2180
|
]
|
|
1948
2181
|
});
|
|
@@ -1960,15 +2193,11 @@ ${passphraseProtectedKeys.map((k) => ` - ${k}`).join(`
|
|
|
1960
2193
|
process.exit(1);
|
|
1961
2194
|
}
|
|
1962
2195
|
} else {
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
});
|
|
1969
|
-
const selectedKey = sshKeys.find((k) => k.name === keyPrompt.key);
|
|
1970
|
-
if (!selectedKey) {
|
|
1971
|
-
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));
|
|
1972
2201
|
process.exit(1);
|
|
1973
2202
|
}
|
|
1974
2203
|
publicKey = crypto10.createPublicKey(selectedKey.privateKey);
|
|
@@ -1990,25 +2219,24 @@ ${passphraseProtectedKeys.map((k) => ` - ${k}`).join(`
|
|
|
1990
2219
|
type: "spki",
|
|
1991
2220
|
format: "pem"
|
|
1992
2221
|
});
|
|
1993
|
-
if (!existsSync7(
|
|
1994
|
-
await fs12.mkdir(
|
|
2222
|
+
if (!existsSync7(path13.join(process.cwd(), ".dotenc"))) {
|
|
2223
|
+
await fs12.mkdir(path13.join(process.cwd(), ".dotenc"));
|
|
1995
2224
|
}
|
|
1996
2225
|
let name = nameArg;
|
|
1997
2226
|
if (!name) {
|
|
1998
2227
|
name = await inputNamePrompt("What name do you want to give to the new public key?");
|
|
1999
|
-
if (existsSync7(
|
|
2000
|
-
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.`);
|
|
2001
2230
|
process.exit(1);
|
|
2002
2231
|
}
|
|
2003
2232
|
}
|
|
2004
|
-
await fs12.writeFile(
|
|
2233
|
+
await fs12.writeFile(path13.join(process.cwd(), ".dotenc", `${name}.pub`), publicKeyOutput, "utf-8");
|
|
2005
2234
|
console.log(`
|
|
2006
|
-
Public key ${
|
|
2235
|
+
Public key ${chalk13.cyan(name)} added successfully!`);
|
|
2007
2236
|
};
|
|
2008
2237
|
var init_add = __esm(() => {
|
|
2009
|
-
init_getPrivateKeys();
|
|
2010
2238
|
init_parseOpenSSHKey();
|
|
2011
|
-
|
|
2239
|
+
init_choosePrivateKey();
|
|
2012
2240
|
init_inputKey();
|
|
2013
2241
|
init_inputName();
|
|
2014
2242
|
});
|
|
@@ -2017,61 +2245,32 @@ var init_add = __esm(() => {
|
|
|
2017
2245
|
import crypto11 from "node:crypto";
|
|
2018
2246
|
import { existsSync as existsSync8 } from "node:fs";
|
|
2019
2247
|
import fs13 from "node:fs/promises";
|
|
2020
|
-
import
|
|
2021
|
-
import
|
|
2022
|
-
import
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
if (!privateKeys.length) {
|
|
2027
|
-
if (passphraseProtectedKeys.length > 0) {
|
|
2028
|
-
console.error(passphraseProtectedKeyError(passphraseProtectedKeys));
|
|
2029
|
-
} else {
|
|
2030
|
-
console.error(`${chalk13.red("Error:")} no SSH keys found in ~/.ssh/. Please generate one first using ${chalk13.gray("ssh-keygen")}.`);
|
|
2031
|
-
}
|
|
2032
|
-
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;
|
|
2033
2254
|
}
|
|
2034
|
-
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);
|
|
2035
2262
|
if (!username) {
|
|
2036
|
-
console.error(`${
|
|
2263
|
+
console.error(`${chalk14.red("Error:")} no name provided.`);
|
|
2037
2264
|
process.exit(1);
|
|
2038
2265
|
}
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
} catch (error) {
|
|
2045
|
-
console.error(`${chalk13.red("Error:")} failed to create the project.`);
|
|
2046
|
-
console.error(`${chalk13.red("Details:")} ${error instanceof Error ? error.message : error}`);
|
|
2047
|
-
process.exit(1);
|
|
2048
|
-
}
|
|
2049
|
-
}
|
|
2050
|
-
let keyToAdd;
|
|
2051
|
-
if (privateKeys.length === 1) {
|
|
2052
|
-
keyToAdd = privateKeys[0].name;
|
|
2053
|
-
} else {
|
|
2054
|
-
const result = await inquirer8.prompt([
|
|
2055
|
-
{
|
|
2056
|
-
type: "list",
|
|
2057
|
-
name: "key",
|
|
2058
|
-
message: "Which SSH key would you like to use?",
|
|
2059
|
-
choices: privateKeys.map((key) => ({
|
|
2060
|
-
name: `${key.name} (${key.algorithm})`,
|
|
2061
|
-
value: key.name
|
|
2062
|
-
}))
|
|
2063
|
-
}
|
|
2064
|
-
]);
|
|
2065
|
-
keyToAdd = result.key;
|
|
2066
|
-
}
|
|
2067
|
-
if (!keyToAdd) {
|
|
2068
|
-
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));
|
|
2069
2271
|
process.exit(1);
|
|
2070
2272
|
}
|
|
2071
|
-
|
|
2072
|
-
if (!keyEntry)
|
|
2073
|
-
process.exit(1);
|
|
2074
|
-
console.log(`Adding key: ${chalk13.cyan(username)} (${keyEntry.algorithm})`);
|
|
2273
|
+
console.log(`Adding key: ${chalk14.cyan(username)} (${keyEntry.algorithm})`);
|
|
2075
2274
|
const publicKey = crypto11.createPublicKey(keyEntry.privateKey);
|
|
2076
2275
|
const publicKeyPem = publicKey.export({ type: "spki", format: "pem" }).toString();
|
|
2077
2276
|
await keyAddCommand(username, {
|
|
@@ -2080,36 +2279,47 @@ var initCommand = async (options) => {
|
|
|
2080
2279
|
try {
|
|
2081
2280
|
setupGitDiff();
|
|
2082
2281
|
} catch (_error) {
|
|
2083
|
-
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.`);
|
|
2084
2283
|
}
|
|
2085
2284
|
let initialContent;
|
|
2086
|
-
const envPath =
|
|
2285
|
+
const envPath = path14.join(process.cwd(), ".env");
|
|
2087
2286
|
if (existsSync8(envPath)) {
|
|
2088
2287
|
initialContent = await fs13.readFile(envPath, "utf-8");
|
|
2089
2288
|
await fs13.unlink(envPath);
|
|
2090
|
-
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);
|
|
2091
2294
|
}
|
|
2092
|
-
await createCommand(username, username, initialContent);
|
|
2093
2295
|
console.log(`
|
|
2094
|
-
${
|
|
2296
|
+
${chalk14.green("✔")} Initialization complete!`);
|
|
2095
2297
|
console.log(`
|
|
2096
2298
|
Some useful tips:`);
|
|
2097
|
-
const
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
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
|
+
}
|
|
2101
2312
|
if (existsSync8(".claude") || existsSync8("CLAUDE.md")) {
|
|
2102
|
-
console.log(`- Install the agent skill: ${
|
|
2313
|
+
console.log(`- Install the agent skill: ${chalk14.gray("dotenc tools install-agent-skill")}`);
|
|
2103
2314
|
}
|
|
2104
2315
|
if (existsSync8(".vscode") || existsSync8(".cursor") || existsSync8(".windsurf")) {
|
|
2105
|
-
console.log(`- Add the editor extension: ${
|
|
2316
|
+
console.log(`- Add the editor extension: ${chalk14.gray("dotenc tools install-vscode-extension")}`);
|
|
2106
2317
|
}
|
|
2107
2318
|
};
|
|
2108
2319
|
var init_init = __esm(() => {
|
|
2109
|
-
|
|
2110
|
-
init_errors();
|
|
2111
|
-
init_getPrivateKeys();
|
|
2320
|
+
init_package();
|
|
2112
2321
|
init_setupGitDiff();
|
|
2322
|
+
init_choosePrivateKey();
|
|
2113
2323
|
init_inputName();
|
|
2114
2324
|
init_create();
|
|
2115
2325
|
init_add();
|
|
@@ -2147,16 +2357,16 @@ var init_confirm = () => {};
|
|
|
2147
2357
|
// src/commands/key/remove.ts
|
|
2148
2358
|
import { existsSync as existsSync9 } from "node:fs";
|
|
2149
2359
|
import fs14 from "node:fs/promises";
|
|
2150
|
-
import
|
|
2151
|
-
import
|
|
2360
|
+
import path15 from "node:path";
|
|
2361
|
+
import chalk15 from "chalk";
|
|
2152
2362
|
var keyRemoveCommand = async (nameArg) => {
|
|
2153
2363
|
let name = nameArg;
|
|
2154
2364
|
if (!name) {
|
|
2155
2365
|
name = await choosePublicKeyPrompt("Which public key do you want to remove?");
|
|
2156
2366
|
}
|
|
2157
|
-
const filePath =
|
|
2367
|
+
const filePath = path15.join(process.cwd(), ".dotenc", `${name}.pub`);
|
|
2158
2368
|
if (!existsSync9(filePath)) {
|
|
2159
|
-
console.error(`Public key ${
|
|
2369
|
+
console.error(`Public key ${chalk15.cyan(name)} not found.`);
|
|
2160
2370
|
process.exit(1);
|
|
2161
2371
|
}
|
|
2162
2372
|
const allEnvironments = await getEnvironments();
|
|
@@ -2170,7 +2380,7 @@ var keyRemoveCommand = async (nameArg) => {
|
|
|
2170
2380
|
} catch {}
|
|
2171
2381
|
}
|
|
2172
2382
|
if (affectedEnvironments.length > 0) {
|
|
2173
|
-
console.log(`Key ${
|
|
2383
|
+
console.log(`Key ${chalk15.cyan(name)} has access to the following environments:`);
|
|
2174
2384
|
for (const env of affectedEnvironments) {
|
|
2175
2385
|
console.log(` - ${env}`);
|
|
2176
2386
|
}
|
|
@@ -2183,7 +2393,7 @@ Access will be revoked from these environments automatically.`);
|
|
|
2183
2393
|
return;
|
|
2184
2394
|
}
|
|
2185
2395
|
await fs14.unlink(filePath);
|
|
2186
|
-
console.log(`Public key ${
|
|
2396
|
+
console.log(`Public key ${chalk15.cyan(name)} removed successfully.`);
|
|
2187
2397
|
for (const envName of affectedEnvironments) {
|
|
2188
2398
|
try {
|
|
2189
2399
|
const envJson = await getEnvironmentByName(envName);
|
|
@@ -2191,9 +2401,9 @@ Access will be revoked from these environments automatically.`);
|
|
|
2191
2401
|
await encryptEnvironment(envName, content, {
|
|
2192
2402
|
revokePublicKeys: [name]
|
|
2193
2403
|
});
|
|
2194
|
-
console.log(`Revoked access from ${
|
|
2404
|
+
console.log(`Revoked access from ${chalk15.cyan(envName)} environment.`);
|
|
2195
2405
|
} catch {
|
|
2196
|
-
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.`);
|
|
2197
2407
|
}
|
|
2198
2408
|
}
|
|
2199
2409
|
};
|
|
@@ -2208,9 +2418,9 @@ var init_remove = __esm(() => {
|
|
|
2208
2418
|
|
|
2209
2419
|
// src/commands/textconv.ts
|
|
2210
2420
|
import fs15 from "node:fs/promises";
|
|
2211
|
-
import
|
|
2421
|
+
import path16 from "node:path";
|
|
2212
2422
|
var textconvCommand = async (filePath) => {
|
|
2213
|
-
const absolutePath =
|
|
2423
|
+
const absolutePath = path16.isAbsolute(filePath) ? filePath : path16.join(process.cwd(), filePath);
|
|
2214
2424
|
try {
|
|
2215
2425
|
const environment = await getEnvironmentByPath(absolutePath);
|
|
2216
2426
|
const plaintext = await decryptEnvironmentData(environment);
|
|
@@ -2227,18 +2437,18 @@ var init_textconv = __esm(() => {
|
|
|
2227
2437
|
|
|
2228
2438
|
// src/commands/tools/install-agent-skill.ts
|
|
2229
2439
|
import { spawn as spawn2 } from "node:child_process";
|
|
2230
|
-
import
|
|
2440
|
+
import chalk16 from "chalk";
|
|
2231
2441
|
import inquirer10 from "inquirer";
|
|
2232
|
-
var SKILL_SOURCE = "ivanfilhoz/dotenc", SKILL_NAME = "dotenc", runNpx = (args) => new Promise((resolve, reject) => {
|
|
2233
|
-
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, {
|
|
2234
2444
|
stdio: "inherit",
|
|
2235
2445
|
shell: process.platform === "win32"
|
|
2236
2446
|
});
|
|
2237
2447
|
child.on("error", reject);
|
|
2238
2448
|
child.on("exit", (code) => resolve(code ?? 1));
|
|
2239
|
-
}),
|
|
2449
|
+
}), defaultDeps2, _runInstallAgentSkillCommand = async (options, depsOverrides = {}) => {
|
|
2240
2450
|
const deps = {
|
|
2241
|
-
...
|
|
2451
|
+
...defaultDeps2,
|
|
2242
2452
|
...depsOverrides
|
|
2243
2453
|
};
|
|
2244
2454
|
const { scope } = await deps.prompt([
|
|
@@ -2264,21 +2474,21 @@ var SKILL_SOURCE = "ivanfilhoz/dotenc", SKILL_NAME = "dotenc", runNpx = (args) =
|
|
|
2264
2474
|
try {
|
|
2265
2475
|
exitCode = await deps.runNpx(args);
|
|
2266
2476
|
} catch (error) {
|
|
2267
|
-
deps.logError(`${
|
|
2268
|
-
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)}`);
|
|
2269
2479
|
deps.exit(1);
|
|
2270
2480
|
}
|
|
2271
2481
|
if (exitCode !== 0) {
|
|
2272
|
-
deps.logError(`${
|
|
2482
|
+
deps.logError(`${chalk16.red("Error:")} skill installation command exited with code ${exitCode}.`);
|
|
2273
2483
|
deps.exit(exitCode);
|
|
2274
2484
|
}
|
|
2275
|
-
deps.log(`${
|
|
2276
|
-
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.`);
|
|
2277
2487
|
}, installAgentSkillCommand = async (options) => {
|
|
2278
2488
|
await _runInstallAgentSkillCommand(options);
|
|
2279
2489
|
};
|
|
2280
2490
|
var init_install_agent_skill = __esm(() => {
|
|
2281
|
-
|
|
2491
|
+
defaultDeps2 = {
|
|
2282
2492
|
prompt: inquirer10.prompt,
|
|
2283
2493
|
runNpx,
|
|
2284
2494
|
log: console.log,
|
|
@@ -2291,12 +2501,12 @@ var init_install_agent_skill = __esm(() => {
|
|
|
2291
2501
|
import { exec, execFile } from "node:child_process";
|
|
2292
2502
|
import { existsSync as existsSync10 } from "node:fs";
|
|
2293
2503
|
import fs16 from "node:fs/promises";
|
|
2294
|
-
import
|
|
2504
|
+
import path17 from "node:path";
|
|
2295
2505
|
import { promisify } from "node:util";
|
|
2296
|
-
import
|
|
2506
|
+
import chalk17 from "chalk";
|
|
2297
2507
|
import inquirer11 from "inquirer";
|
|
2298
2508
|
async function addToExtensionsJson() {
|
|
2299
|
-
const extensionsJsonPath =
|
|
2509
|
+
const extensionsJsonPath = path17.join(process.cwd(), ".vscode", "extensions.json");
|
|
2300
2510
|
let json = {};
|
|
2301
2511
|
if (existsSync10(extensionsJsonPath)) {
|
|
2302
2512
|
const content = await fs16.readFile(extensionsJsonPath, "utf-8");
|
|
@@ -2306,7 +2516,7 @@ async function addToExtensionsJson() {
|
|
|
2306
2516
|
json = {};
|
|
2307
2517
|
}
|
|
2308
2518
|
} else {
|
|
2309
|
-
await fs16.mkdir(
|
|
2519
|
+
await fs16.mkdir(path17.join(process.cwd(), ".vscode"), { recursive: true });
|
|
2310
2520
|
}
|
|
2311
2521
|
if (!Array.isArray(json.recommendations)) {
|
|
2312
2522
|
json.recommendations = [];
|
|
@@ -2314,9 +2524,9 @@ async function addToExtensionsJson() {
|
|
|
2314
2524
|
if (!json.recommendations.includes(EXTENSION_ID)) {
|
|
2315
2525
|
json.recommendations.push(EXTENSION_ID);
|
|
2316
2526
|
await fs16.writeFile(extensionsJsonPath, JSON.stringify(json, null, 2), "utf-8");
|
|
2317
|
-
console.log(`${
|
|
2527
|
+
console.log(`${chalk17.green("✓")} Added dotenc to ${chalk17.gray(".vscode/extensions.json")}`);
|
|
2318
2528
|
} else {
|
|
2319
|
-
console.log(`${
|
|
2529
|
+
console.log(`${chalk17.green("✓")} dotenc already in ${chalk17.gray(".vscode/extensions.json")}`);
|
|
2320
2530
|
}
|
|
2321
2531
|
}
|
|
2322
2532
|
async function which(bin) {
|
|
@@ -2329,11 +2539,11 @@ async function which(bin) {
|
|
|
2329
2539
|
}
|
|
2330
2540
|
async function detectEditors() {
|
|
2331
2541
|
const detected = [];
|
|
2332
|
-
if (existsSync10(
|
|
2542
|
+
if (existsSync10(path17.join(process.cwd(), ".cursor")))
|
|
2333
2543
|
detected.push("cursor");
|
|
2334
|
-
if (existsSync10(
|
|
2544
|
+
if (existsSync10(path17.join(process.cwd(), ".windsurf")))
|
|
2335
2545
|
detected.push("windsurf");
|
|
2336
|
-
if (existsSync10(
|
|
2546
|
+
if (existsSync10(path17.join(process.cwd(), ".vscode")))
|
|
2337
2547
|
detected.push("vscode");
|
|
2338
2548
|
const checks = [
|
|
2339
2549
|
{ key: "cursor", bins: ["cursor"] },
|
|
@@ -2380,7 +2590,7 @@ async function _runInstallVscodeExtension(getEditors = detectEditors, _openUrl =
|
|
|
2380
2590
|
await addToExtensionsJson();
|
|
2381
2591
|
if (editors.length === 0) {
|
|
2382
2592
|
console.log(`
|
|
2383
|
-
Install the extension in VS Code: ${
|
|
2593
|
+
Install the extension in VS Code: ${chalk17.cyan(EDITOR_PROTOCOL_URLS.vscode)}`);
|
|
2384
2594
|
return;
|
|
2385
2595
|
}
|
|
2386
2596
|
if (editors.length === 1) {
|
|
@@ -2399,10 +2609,10 @@ Install the extension in VS Code: ${chalk16.cyan(EDITOR_PROTOCOL_URLS.vscode)}`)
|
|
|
2399
2609
|
try {
|
|
2400
2610
|
await _openUrl(url);
|
|
2401
2611
|
} catch {
|
|
2402
|
-
console.log(`Open manually: ${
|
|
2612
|
+
console.log(`Open manually: ${chalk17.cyan(url)}`);
|
|
2403
2613
|
}
|
|
2404
2614
|
} else {
|
|
2405
|
-
console.log(`Install manually: ${
|
|
2615
|
+
console.log(`Install manually: ${chalk17.cyan(url)}`);
|
|
2406
2616
|
}
|
|
2407
2617
|
return;
|
|
2408
2618
|
}
|
|
@@ -2411,7 +2621,7 @@ Install the extension in your editor:`);
|
|
|
2411
2621
|
for (const editor of editors) {
|
|
2412
2622
|
const name = EDITOR_NAMES[editor] ?? editor;
|
|
2413
2623
|
const url = EDITOR_PROTOCOL_URLS[editor];
|
|
2414
|
-
console.log(` ${name}: ${
|
|
2624
|
+
console.log(` ${name}: ${chalk17.cyan(url)}`);
|
|
2415
2625
|
}
|
|
2416
2626
|
}
|
|
2417
2627
|
var execFileAsync, execAsync, EXTENSION_ID = "dotenc.dotenc", EDITOR_PROTOCOL_URLS, EDITOR_NAMES, installVscodeExtensionCommand = async () => {
|
|
@@ -2518,31 +2728,31 @@ var init_update = () => {};
|
|
|
2518
2728
|
|
|
2519
2729
|
// src/commands/update.ts
|
|
2520
2730
|
import { spawn as spawn3 } from "node:child_process";
|
|
2521
|
-
import
|
|
2522
|
-
var runPackageManagerCommand = (command, args) => new Promise((resolve, reject) => {
|
|
2523
|
-
const child =
|
|
2731
|
+
import chalk18 from "chalk";
|
|
2732
|
+
var runPackageManagerCommand = (command, args, spawnImpl = spawn3) => new Promise((resolve, reject) => {
|
|
2733
|
+
const child = spawnImpl(command, args, {
|
|
2524
2734
|
stdio: "inherit",
|
|
2525
2735
|
shell: process.platform === "win32"
|
|
2526
2736
|
});
|
|
2527
2737
|
child.on("error", reject);
|
|
2528
2738
|
child.on("exit", (code) => resolve(code ?? 1));
|
|
2529
|
-
}),
|
|
2739
|
+
}), defaultDeps3, updateCommands, _runUpdateCommand = async (depsOverrides = {}) => {
|
|
2530
2740
|
const deps = {
|
|
2531
|
-
...
|
|
2741
|
+
...defaultDeps3,
|
|
2532
2742
|
...depsOverrides
|
|
2533
2743
|
};
|
|
2534
2744
|
const method = deps.detectInstallMethod();
|
|
2535
2745
|
if (method === "binary") {
|
|
2536
|
-
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)}.`);
|
|
2537
2747
|
return;
|
|
2538
2748
|
}
|
|
2539
2749
|
if (method === "unknown") {
|
|
2540
2750
|
deps.log("Could not determine installation method automatically.");
|
|
2541
2751
|
deps.log(`Try one of these commands:`);
|
|
2542
|
-
deps.log(` ${
|
|
2543
|
-
deps.log(` ${
|
|
2544
|
-
deps.log(` ${
|
|
2545
|
-
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)}.`);
|
|
2546
2756
|
return;
|
|
2547
2757
|
}
|
|
2548
2758
|
const updater = updateCommands[method];
|
|
@@ -2551,12 +2761,12 @@ var runPackageManagerCommand = (command, args) => new Promise((resolve, reject)
|
|
|
2551
2761
|
try {
|
|
2552
2762
|
exitCode = await deps.runPackageManagerCommand(updater.command, updater.args);
|
|
2553
2763
|
} catch (error) {
|
|
2554
|
-
deps.logError(`${
|
|
2555
|
-
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)}`);
|
|
2556
2766
|
deps.exit(1);
|
|
2557
2767
|
}
|
|
2558
2768
|
if (exitCode !== 0) {
|
|
2559
|
-
deps.logError(`${
|
|
2769
|
+
deps.logError(`${chalk18.red("Error:")} update command exited with code ${exitCode}.`);
|
|
2560
2770
|
deps.exit(exitCode);
|
|
2561
2771
|
}
|
|
2562
2772
|
}, updateCommand = async () => {
|
|
@@ -2564,7 +2774,7 @@ var runPackageManagerCommand = (command, args) => new Promise((resolve, reject)
|
|
|
2564
2774
|
};
|
|
2565
2775
|
var init_update2 = __esm(() => {
|
|
2566
2776
|
init_update();
|
|
2567
|
-
|
|
2777
|
+
defaultDeps3 = {
|
|
2568
2778
|
detectInstallMethod,
|
|
2569
2779
|
runPackageManagerCommand,
|
|
2570
2780
|
log: console.log,
|
|
@@ -2643,8 +2853,8 @@ var init_whoami = __esm(() => {
|
|
|
2643
2853
|
});
|
|
2644
2854
|
|
|
2645
2855
|
// src/helpers/updateNotifier.ts
|
|
2646
|
-
import
|
|
2647
|
-
var CHECK_INTERVAL_MS,
|
|
2856
|
+
import chalk19 from "chalk";
|
|
2857
|
+
var CHECK_INTERVAL_MS, defaultDeps4, shouldSkipCheck = (args, env) => {
|
|
2648
2858
|
if (env.DOTENC_SKIP_UPDATE_CHECK === "1") {
|
|
2649
2859
|
return true;
|
|
2650
2860
|
}
|
|
@@ -2666,7 +2876,7 @@ var CHECK_INTERVAL_MS, defaultDeps3, shouldSkipCheck = (args, env) => {
|
|
|
2666
2876
|
} catch {}
|
|
2667
2877
|
}, maybeNotifyAboutUpdate = async (depsOverrides = {}) => {
|
|
2668
2878
|
const deps = {
|
|
2669
|
-
...
|
|
2879
|
+
...defaultDeps4,
|
|
2670
2880
|
...depsOverrides
|
|
2671
2881
|
};
|
|
2672
2882
|
if (shouldSkipCheck(deps.args, deps.env)) {
|
|
@@ -2699,7 +2909,7 @@ var CHECK_INTERVAL_MS, defaultDeps3, shouldSkipCheck = (args, env) => {
|
|
|
2699
2909
|
if (updateState.notifiedVersion === latestVersion) {
|
|
2700
2910
|
return;
|
|
2701
2911
|
}
|
|
2702
|
-
deps.log(`${
|
|
2912
|
+
deps.log(`${chalk19.yellow("Update available:")} ${chalk19.gray(`dotenc ${deps.currentVersion}`)} -> ${chalk19.cyan(`dotenc ${latestVersion}`)}. Run ${chalk19.gray("dotenc update")}.`);
|
|
2703
2913
|
updateState = {
|
|
2704
2914
|
...updateState,
|
|
2705
2915
|
notifiedVersion: latestVersion
|
|
@@ -2711,7 +2921,7 @@ var init_updateNotifier = __esm(() => {
|
|
|
2711
2921
|
init_homeConfig();
|
|
2712
2922
|
init_update();
|
|
2713
2923
|
CHECK_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
2714
|
-
|
|
2924
|
+
defaultDeps4 = {
|
|
2715
2925
|
getHomeConfig,
|
|
2716
2926
|
setHomeConfig,
|
|
2717
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",
|