autho 3.0.1 → 3.0.2
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/dist/autho.js +175 -39
- package/package.json +1 -1
package/dist/autho.js
CHANGED
|
@@ -374,7 +374,7 @@ var init_src2 = __esm(() => {
|
|
|
374
374
|
});
|
|
375
375
|
|
|
376
376
|
// packages/core/src/paths.ts
|
|
377
|
-
import { chmodSync as chmodSync2, mkdirSync as mkdirSync2, writeFileSync } from "fs";
|
|
377
|
+
import { chmodSync as chmodSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "fs";
|
|
378
378
|
import { homedir } from "os";
|
|
379
379
|
import { dirname as dirname2, join, resolve } from "path";
|
|
380
380
|
function normalizePath(path) {
|
|
@@ -388,9 +388,51 @@ function tryChmod2(path, mode) {
|
|
|
388
388
|
chmodSync2(path, mode);
|
|
389
389
|
} catch {}
|
|
390
390
|
}
|
|
391
|
-
function
|
|
391
|
+
function authoConfigDir() {
|
|
392
392
|
return normalizePath(process.env.AUTHO_HOME ?? join(homedir(), ".autho"));
|
|
393
393
|
}
|
|
394
|
+
function configFilePath() {
|
|
395
|
+
return normalizePath(join(authoConfigDir(), "config.json"));
|
|
396
|
+
}
|
|
397
|
+
function loadConfig() {
|
|
398
|
+
if (configCache.loaded)
|
|
399
|
+
return configCache.value ?? {};
|
|
400
|
+
const path = configFilePath();
|
|
401
|
+
if (!existsSync2(path)) {
|
|
402
|
+
configCache.loaded = true;
|
|
403
|
+
configCache.value = {};
|
|
404
|
+
return {};
|
|
405
|
+
}
|
|
406
|
+
try {
|
|
407
|
+
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
408
|
+
configCache.loaded = true;
|
|
409
|
+
configCache.value = raw;
|
|
410
|
+
return raw;
|
|
411
|
+
} catch {
|
|
412
|
+
configCache.loaded = true;
|
|
413
|
+
configCache.value = {};
|
|
414
|
+
return {};
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
function saveConfig(config) {
|
|
418
|
+
const path = configFilePath();
|
|
419
|
+
ensurePrivateParent(path);
|
|
420
|
+
writeFileSync(path, JSON.stringify(config, null, 2) + `
|
|
421
|
+
`, { encoding: "utf8", mode: 384 });
|
|
422
|
+
hardenFilePermissions(path);
|
|
423
|
+
configCache.value = config;
|
|
424
|
+
configCache.loaded = true;
|
|
425
|
+
}
|
|
426
|
+
function authoHomeDir() {
|
|
427
|
+
if (process.env.AUTHO_HOME) {
|
|
428
|
+
return normalizePath(process.env.AUTHO_HOME);
|
|
429
|
+
}
|
|
430
|
+
const config = loadConfig();
|
|
431
|
+
if (config.vaultDir) {
|
|
432
|
+
return normalizePath(config.vaultDir);
|
|
433
|
+
}
|
|
434
|
+
return normalizePath(join(homedir(), ".autho"));
|
|
435
|
+
}
|
|
394
436
|
function defaultVaultPath() {
|
|
395
437
|
return normalizePath(join(authoHomeDir(), "vault.db"));
|
|
396
438
|
}
|
|
@@ -420,13 +462,16 @@ function writeBinaryFileSecure(path, content) {
|
|
|
420
462
|
writeFileSync(path, content, { mode: 384 });
|
|
421
463
|
hardenFilePermissions(path);
|
|
422
464
|
}
|
|
423
|
-
var
|
|
465
|
+
var configCache;
|
|
466
|
+
var init_paths = __esm(() => {
|
|
467
|
+
configCache = { value: null, loaded: false };
|
|
468
|
+
});
|
|
424
469
|
|
|
425
470
|
// packages/core/src/artifacts.ts
|
|
426
471
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
427
472
|
import {
|
|
428
473
|
readdirSync,
|
|
429
|
-
readFileSync,
|
|
474
|
+
readFileSync as readFileSync2,
|
|
430
475
|
statSync
|
|
431
476
|
} from "fs";
|
|
432
477
|
import { basename, join as join2, relative, resolve as resolve2, sep } from "path";
|
|
@@ -462,7 +507,7 @@ function defaultDecryptedFolderPath(inputPath) {
|
|
|
462
507
|
}
|
|
463
508
|
function encryptFileArtifact(inputPath, outputPath, rootKey) {
|
|
464
509
|
const fileKey = randomBytes2(32);
|
|
465
|
-
const payload = encryptWithKey(
|
|
510
|
+
const payload = encryptWithKey(readFileSync2(inputPath), fileKey, `autho:file:${basename(inputPath)}`);
|
|
466
511
|
const envelope = {
|
|
467
512
|
kind: "file",
|
|
468
513
|
originalName: basename(inputPath),
|
|
@@ -474,7 +519,7 @@ function encryptFileArtifact(inputPath, outputPath, rootKey) {
|
|
|
474
519
|
return { outputPath };
|
|
475
520
|
}
|
|
476
521
|
function decryptFileArtifact(inputPath, outputPath, rootKey) {
|
|
477
|
-
const envelope = JSON.parse(
|
|
522
|
+
const envelope = JSON.parse(readFileSync2(inputPath, "utf8"));
|
|
478
523
|
if (envelope.kind !== "file" || envelope.version !== 1) {
|
|
479
524
|
throw new Error(`Unsupported file artifact: ${inputPath}`);
|
|
480
525
|
}
|
|
@@ -492,7 +537,7 @@ function encryptFolderArtifact(inputPath, outputPath, rootKey) {
|
|
|
492
537
|
const relativePath = normalizeRelativePath(relative(inputPath, filePath));
|
|
493
538
|
return {
|
|
494
539
|
path: relativePath,
|
|
495
|
-
payload: encryptWithKey(
|
|
540
|
+
payload: encryptWithKey(readFileSync2(filePath), folderKey, `autho:folder:${relativePath}`)
|
|
496
541
|
};
|
|
497
542
|
}),
|
|
498
543
|
kind: "folder",
|
|
@@ -507,7 +552,7 @@ function encryptFolderArtifact(inputPath, outputPath, rootKey) {
|
|
|
507
552
|
};
|
|
508
553
|
}
|
|
509
554
|
function decryptFolderArtifact(inputPath, outputPath, rootKey) {
|
|
510
|
-
const envelope = JSON.parse(
|
|
555
|
+
const envelope = JSON.parse(readFileSync2(inputPath, "utf8"));
|
|
511
556
|
if (envelope.kind !== "folder" || envelope.version !== 1) {
|
|
512
557
|
throw new Error(`Unsupported folder artifact: ${inputPath}`);
|
|
513
558
|
}
|
|
@@ -548,8 +593,8 @@ var init_artifacts = __esm(() => {
|
|
|
548
593
|
import { spawnSync } from "child_process";
|
|
549
594
|
import { createHmac as createHmac2, randomBytes as randomBytes3 } from "crypto";
|
|
550
595
|
import {
|
|
551
|
-
existsSync as
|
|
552
|
-
readFileSync as
|
|
596
|
+
existsSync as existsSync3,
|
|
597
|
+
readFileSync as readFileSync3
|
|
553
598
|
} from "fs";
|
|
554
599
|
import { basename as basename2 } from "path";
|
|
555
600
|
function requireValue(value, label) {
|
|
@@ -604,7 +649,7 @@ function normalizeSecretType(type) {
|
|
|
604
649
|
throw new Error(`Unsupported secret type: ${type}`);
|
|
605
650
|
}
|
|
606
651
|
function parseProjectMappings(projectFile) {
|
|
607
|
-
const raw = JSON.parse(
|
|
652
|
+
const raw = JSON.parse(readFileSync3(projectFile, "utf8"));
|
|
608
653
|
return Object.entries(raw.env ?? {}).map(([envName, secretRef]) => ({
|
|
609
654
|
envName,
|
|
610
655
|
secretRef
|
|
@@ -682,7 +727,7 @@ function summarizeCommand(cmd) {
|
|
|
682
727
|
};
|
|
683
728
|
}
|
|
684
729
|
function projectMappingsForStatus(projectFile) {
|
|
685
|
-
if (!projectFile || !
|
|
730
|
+
if (!projectFile || !existsSync3(projectFile)) {
|
|
686
731
|
return {
|
|
687
732
|
mappings: [],
|
|
688
733
|
path: projectFile ?? null
|
|
@@ -705,7 +750,7 @@ function resolveMappings(options) {
|
|
|
705
750
|
};
|
|
706
751
|
});
|
|
707
752
|
if (options.projectFile) {
|
|
708
|
-
if (!
|
|
753
|
+
if (!existsSync3(options.projectFile)) {
|
|
709
754
|
throw new Error(`Project mapping file not found: ${options.projectFile}`);
|
|
710
755
|
}
|
|
711
756
|
return [...parseProjectMappings(options.projectFile), ...fromMaps];
|
|
@@ -716,7 +761,7 @@ function writeProjectConfig(input) {
|
|
|
716
761
|
if (input.mappings.length === 0) {
|
|
717
762
|
throw new Error("Provide at least one env mapping");
|
|
718
763
|
}
|
|
719
|
-
if (!input.force &&
|
|
764
|
+
if (!input.force && existsSync3(input.outputPath)) {
|
|
720
765
|
throw new Error(`Project config already exists: ${input.outputPath}`);
|
|
721
766
|
}
|
|
722
767
|
const env = Object.fromEntries(input.mappings.map((mapping) => [mapping.envName, mapping.secretRef]));
|
|
@@ -1157,7 +1202,7 @@ class VaultSession {
|
|
|
1157
1202
|
};
|
|
1158
1203
|
}
|
|
1159
1204
|
importLegacyFile(filePath, options) {
|
|
1160
|
-
const raw = JSON.parse(
|
|
1205
|
+
const raw = JSON.parse(readFileSync3(filePath, "utf8"));
|
|
1161
1206
|
let imported = 0;
|
|
1162
1207
|
let skipped = 0;
|
|
1163
1208
|
for (const entry of raw) {
|
|
@@ -1290,7 +1335,7 @@ class VaultSession {
|
|
|
1290
1335
|
}
|
|
1291
1336
|
syncEnvFile(input) {
|
|
1292
1337
|
const env = this.buildEnv(input.mappings, input.leaseId);
|
|
1293
|
-
if (!input.force &&
|
|
1338
|
+
if (!input.force && existsSync3(input.outputPath)) {
|
|
1294
1339
|
throw new Error(`Env file already exists: ${input.outputPath}`);
|
|
1295
1340
|
}
|
|
1296
1341
|
const createdAt = new Date().toISOString();
|
|
@@ -1342,7 +1387,7 @@ class VaultSession {
|
|
|
1342
1387
|
encryptFile(inputPath, outputPath, options) {
|
|
1343
1388
|
assertPathIsFile(inputPath);
|
|
1344
1389
|
const resolvedOutput = outputPath ?? defaultEncryptedFilePath(inputPath);
|
|
1345
|
-
if (!options?.force &&
|
|
1390
|
+
if (!options?.force && existsSync3(resolvedOutput)) {
|
|
1346
1391
|
throw new Error(`Output file already exists: ${resolvedOutput}`);
|
|
1347
1392
|
}
|
|
1348
1393
|
const result = encryptFileArtifact(inputPath, resolvedOutput, this.rootKey);
|
|
@@ -1354,7 +1399,7 @@ class VaultSession {
|
|
|
1354
1399
|
decryptFile(inputPath, outputPath, options) {
|
|
1355
1400
|
assertPathIsFile(inputPath);
|
|
1356
1401
|
const resolvedOutput = outputPath ?? defaultDecryptedFilePath(inputPath);
|
|
1357
|
-
if (!options?.force &&
|
|
1402
|
+
if (!options?.force && existsSync3(resolvedOutput)) {
|
|
1358
1403
|
throw new Error(`Output file already exists: ${resolvedOutput}`);
|
|
1359
1404
|
}
|
|
1360
1405
|
const result = decryptFileArtifact(inputPath, resolvedOutput, this.rootKey);
|
|
@@ -1366,7 +1411,7 @@ class VaultSession {
|
|
|
1366
1411
|
encryptFolder(inputPath, outputPath, options) {
|
|
1367
1412
|
assertPathIsDirectory(inputPath);
|
|
1368
1413
|
const resolvedOutput = outputPath ?? defaultEncryptedFolderPath(inputPath);
|
|
1369
|
-
if (!options?.force &&
|
|
1414
|
+
if (!options?.force && existsSync3(resolvedOutput)) {
|
|
1370
1415
|
throw new Error(`Output file already exists: ${resolvedOutput}`);
|
|
1371
1416
|
}
|
|
1372
1417
|
const result = encryptFolderArtifact(inputPath, resolvedOutput, this.rootKey);
|
|
@@ -1379,7 +1424,7 @@ class VaultSession {
|
|
|
1379
1424
|
decryptFolder(inputPath, outputPath, options) {
|
|
1380
1425
|
assertPathIsFile(inputPath);
|
|
1381
1426
|
const resolvedOutput = outputPath ?? defaultDecryptedFolderPath(inputPath);
|
|
1382
|
-
if (!options?.force &&
|
|
1427
|
+
if (!options?.force && existsSync3(resolvedOutput)) {
|
|
1383
1428
|
throw new Error(`Output path already exists: ${resolvedOutput}`);
|
|
1384
1429
|
}
|
|
1385
1430
|
const result = decryptFolderArtifact(inputPath, resolvedOutput, this.rootKey);
|
|
@@ -1867,8 +1912,8 @@ function UnlockScreen({ onUnlock, vaultPath }) {
|
|
|
1867
1912
|
const recoveryFile = process.env.AUTHO_RECOVERY_FILE;
|
|
1868
1913
|
if (recoveryFile) {
|
|
1869
1914
|
try {
|
|
1870
|
-
const { readFileSync:
|
|
1871
|
-
const content =
|
|
1915
|
+
const { readFileSync: readFileSync5 } = await import("fs");
|
|
1916
|
+
const content = readFileSync5(recoveryFile, "utf8");
|
|
1872
1917
|
const lines = content.split(`
|
|
1873
1918
|
`);
|
|
1874
1919
|
const idx = lines.findIndex((l) => l.trim() === "RECOVERY TOKEN:");
|
|
@@ -3123,7 +3168,7 @@ var init_tui = __esm(() => {
|
|
|
3123
3168
|
|
|
3124
3169
|
// apps/cli/src/index.ts
|
|
3125
3170
|
import { spawn } from "child_process";
|
|
3126
|
-
import { existsSync as
|
|
3171
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
3127
3172
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
3128
3173
|
import { resolve as resolve4 } from "path";
|
|
3129
3174
|
|
|
@@ -3211,7 +3256,7 @@ init_src3();
|
|
|
3211
3256
|
init_paths();
|
|
3212
3257
|
init_paths();
|
|
3213
3258
|
import { createHash, timingSafeEqual } from "crypto";
|
|
3214
|
-
import { existsSync as
|
|
3259
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, rmSync } from "fs";
|
|
3215
3260
|
var DAEMON_TOKEN_SERVICE = "autho.daemon";
|
|
3216
3261
|
function daemonTokenName(statePath) {
|
|
3217
3262
|
return createHash("sha256").update(statePath).digest("hex");
|
|
@@ -3269,10 +3314,10 @@ async function deleteStoredDaemonToken(state) {
|
|
|
3269
3314
|
} catch {}
|
|
3270
3315
|
}
|
|
3271
3316
|
function readDaemonState(statePath) {
|
|
3272
|
-
if (!
|
|
3317
|
+
if (!existsSync4(statePath)) {
|
|
3273
3318
|
return null;
|
|
3274
3319
|
}
|
|
3275
|
-
const stored = JSON.parse(
|
|
3320
|
+
const stored = JSON.parse(readFileSync4(statePath, "utf8"));
|
|
3276
3321
|
return {
|
|
3277
3322
|
pid: stored.pid,
|
|
3278
3323
|
port: stored.port,
|
|
@@ -3301,7 +3346,7 @@ async function writeDaemonState(statePath, state) {
|
|
|
3301
3346
|
async function deleteDaemonState(statePath) {
|
|
3302
3347
|
const state = readDaemonState(statePath);
|
|
3303
3348
|
await deleteStoredDaemonToken(state);
|
|
3304
|
-
if (
|
|
3349
|
+
if (existsSync4(statePath)) {
|
|
3305
3350
|
rmSync(statePath, { force: true });
|
|
3306
3351
|
}
|
|
3307
3352
|
}
|
|
@@ -3488,12 +3533,12 @@ async function startDaemonServer(options) {
|
|
|
3488
3533
|
}
|
|
3489
3534
|
async function waitForDaemonStateDeletion(statePath) {
|
|
3490
3535
|
for (let attempt = 0;attempt < 20; attempt += 1) {
|
|
3491
|
-
if (!
|
|
3536
|
+
if (!existsSync4(statePath)) {
|
|
3492
3537
|
return true;
|
|
3493
3538
|
}
|
|
3494
3539
|
await Bun.sleep(25);
|
|
3495
3540
|
}
|
|
3496
|
-
return !
|
|
3541
|
+
return !existsSync4(statePath);
|
|
3497
3542
|
}
|
|
3498
3543
|
async function daemonRequest(state, path, body) {
|
|
3499
3544
|
const token = await resolveDaemonToken(state);
|
|
@@ -3922,6 +3967,10 @@ function help() {
|
|
|
3922
3967
|
" prompt [--vault <path>]",
|
|
3923
3968
|
" init [--vault <path>]",
|
|
3924
3969
|
" status [--vault <path>] [--project-file <path>] [--json]",
|
|
3970
|
+
" config [show] Show current configuration",
|
|
3971
|
+
" config set <key> <value> Set a config value",
|
|
3972
|
+
" config unset <key> Remove a config value",
|
|
3973
|
+
" config path Print config file path",
|
|
3925
3974
|
" project init --map <ENV=ref> [--output <path>] [--force] [--json]",
|
|
3926
3975
|
" web serve [--vault <path>] [--host <value>] [--port <value>]",
|
|
3927
3976
|
" daemon serve [--vault <path>] [--state-file <path>] [--host <value>] [--port <value>]",
|
|
@@ -3976,9 +4025,12 @@ function help() {
|
|
|
3976
4025
|
"",
|
|
3977
4026
|
"Notes:",
|
|
3978
4027
|
" Running `autho` with no arguments opens the interactive TUI.",
|
|
3979
|
-
"
|
|
3980
|
-
" The
|
|
3981
|
-
"
|
|
4028
|
+
" Config is stored in ~/.autho/config.json (always at ~/.autho).",
|
|
4029
|
+
" The vault directory can be customized via `autho init` or `autho config set vaultDir <path>`.",
|
|
4030
|
+
" Config keys: vaultDir, defaultLeaseTtl, editor, autoLock, autoLockTimeout",
|
|
4031
|
+
" The default vault path is ~/.autho/vault.db (override with config or AUTHO_HOME).",
|
|
4032
|
+
" The default project file is <vaultDir>/project.json.",
|
|
4033
|
+
" The default daemon state file is <vaultDir>/daemon.json."
|
|
3982
4034
|
].join(`
|
|
3983
4035
|
`);
|
|
3984
4036
|
}
|
|
@@ -3990,7 +4042,7 @@ async function main() {
|
|
|
3990
4042
|
const statePath = absolutePath(getString(args, "state-file") ?? defaultDaemonStatePath());
|
|
3991
4043
|
const explicitProjectFile = getString(args, "project-file");
|
|
3992
4044
|
const fallbackProjectFile = defaultProjectFilePath();
|
|
3993
|
-
const projectFile = explicitProjectFile ?? (
|
|
4045
|
+
const projectFile = explicitProjectFile ?? (existsSync5(fallbackProjectFile) ? fallbackProjectFile : undefined);
|
|
3994
4046
|
let password = getString(args, "password") ?? process.env.AUTHO_MASTER_PASSWORD;
|
|
3995
4047
|
if (!password) {
|
|
3996
4048
|
password = await loadVaultPassword(vaultPath) ?? undefined;
|
|
@@ -4032,17 +4084,35 @@ async function main() {
|
|
|
4032
4084
|
}
|
|
4033
4085
|
}
|
|
4034
4086
|
if (scope === "init") {
|
|
4035
|
-
|
|
4087
|
+
let effectiveVaultPath = vaultPath;
|
|
4088
|
+
if (!VaultService.status(vaultPath).initialized && process.stdin.isTTY && !jsonMode) {
|
|
4089
|
+
const config = loadConfig();
|
|
4090
|
+
const currentDir = config.vaultDir ?? authoConfigDir();
|
|
4091
|
+
console.log(`
|
|
4092
|
+
\x1B[1mVault directory\x1B[0m`);
|
|
4093
|
+
console.log(` Default: ${currentDir}`);
|
|
4094
|
+
console.log(" Tip: Use a cloud-synced folder (e.g. Google Drive) to share the vault across machines.");
|
|
4095
|
+
const customDir = (await readLine(` Path (Enter to keep default): `)).trim();
|
|
4096
|
+
if (customDir && customDir !== currentDir) {
|
|
4097
|
+
const resolved = resolve4(customDir).replace(/\\/g, "/");
|
|
4098
|
+
saveConfig({ ...config, vaultDir: resolved });
|
|
4099
|
+
effectiveVaultPath = resolved + "/vault.db";
|
|
4100
|
+
console.log(` \x1B[32m\u2713\x1B[0m Vault directory set to ${resolved}`);
|
|
4101
|
+
console.log(` Config saved to ${authoConfigDir()}/config.json`);
|
|
4102
|
+
}
|
|
4103
|
+
console.log("");
|
|
4104
|
+
}
|
|
4105
|
+
const existingStatus = VaultService.status(effectiveVaultPath);
|
|
4036
4106
|
if (!existingStatus.initialized) {
|
|
4037
4107
|
const pw = required(password, "--password");
|
|
4038
|
-
output(VaultService.initialize(
|
|
4108
|
+
output(VaultService.initialize(effectiveVaultPath, pw), jsonMode);
|
|
4039
4109
|
if (process.stdin.isTTY && !jsonMode) {
|
|
4040
|
-
await runInitWizard(
|
|
4110
|
+
await runInitWizard(effectiveVaultPath, pw);
|
|
4041
4111
|
}
|
|
4042
4112
|
} else {
|
|
4043
|
-
const creds2 = await resolveUnlockCredentials(
|
|
4113
|
+
const creds2 = await resolveUnlockCredentials(effectiveVaultPath, args, password);
|
|
4044
4114
|
if (process.stdin.isTTY && !jsonMode) {
|
|
4045
|
-
await runInitWizard(
|
|
4115
|
+
await runInitWizard(effectiveVaultPath, creds2.password, creds2);
|
|
4046
4116
|
} else {
|
|
4047
4117
|
console.log("Vault already initialized. Use interactive mode (TTY) to reconfigure.");
|
|
4048
4118
|
}
|
|
@@ -4056,6 +4126,72 @@ async function main() {
|
|
|
4056
4126
|
}), jsonMode);
|
|
4057
4127
|
return;
|
|
4058
4128
|
}
|
|
4129
|
+
if (scope === "config") {
|
|
4130
|
+
const config = loadConfig();
|
|
4131
|
+
if (!action || action === "show") {
|
|
4132
|
+
if (jsonMode) {
|
|
4133
|
+
output({ configDir: authoConfigDir(), config }, jsonMode);
|
|
4134
|
+
} else {
|
|
4135
|
+
console.log(`Config: ${authoConfigDir()}/config.json`);
|
|
4136
|
+
console.log(`Vault dir: ${config.vaultDir ?? authoConfigDir()} ${config.vaultDir ? "(custom)" : "(default)"}`);
|
|
4137
|
+
if (config.defaultLeaseTtl)
|
|
4138
|
+
console.log(`Default lease TTL: ${config.defaultLeaseTtl}`);
|
|
4139
|
+
if (config.editor)
|
|
4140
|
+
console.log(`Editor: ${config.editor}`);
|
|
4141
|
+
if (config.autoLock !== undefined)
|
|
4142
|
+
console.log(`Auto-lock: ${config.autoLock}`);
|
|
4143
|
+
if (config.autoLockTimeout)
|
|
4144
|
+
console.log(`Auto-lock timeout: ${config.autoLockTimeout}`);
|
|
4145
|
+
}
|
|
4146
|
+
return;
|
|
4147
|
+
}
|
|
4148
|
+
if (action === "set") {
|
|
4149
|
+
const key = subaction;
|
|
4150
|
+
const value = process.argv[process.argv.indexOf("set") + 2];
|
|
4151
|
+
if (!key || value === undefined) {
|
|
4152
|
+
console.error("Usage: autho config set <key> <value>");
|
|
4153
|
+
console.error("Keys: vaultDir, defaultLeaseTtl, editor, autoLock, autoLockTimeout");
|
|
4154
|
+
process.exit(1);
|
|
4155
|
+
}
|
|
4156
|
+
const updated = { ...config };
|
|
4157
|
+
if (key === "autoLock") {
|
|
4158
|
+
updated.autoLock = value === "true";
|
|
4159
|
+
} else if (key === "vaultDir") {
|
|
4160
|
+
updated.vaultDir = value;
|
|
4161
|
+
} else if (key === "defaultLeaseTtl") {
|
|
4162
|
+
updated.defaultLeaseTtl = value;
|
|
4163
|
+
} else if (key === "editor") {
|
|
4164
|
+
updated.editor = value;
|
|
4165
|
+
} else if (key === "autoLockTimeout") {
|
|
4166
|
+
updated.autoLockTimeout = value;
|
|
4167
|
+
} else {
|
|
4168
|
+
console.error(`Unknown config key: ${key}`);
|
|
4169
|
+
console.error("Keys: vaultDir, defaultLeaseTtl, editor, autoLock, autoLockTimeout");
|
|
4170
|
+
process.exit(1);
|
|
4171
|
+
}
|
|
4172
|
+
saveConfig(updated);
|
|
4173
|
+
console.log(`Set ${key} = ${value}`);
|
|
4174
|
+
return;
|
|
4175
|
+
}
|
|
4176
|
+
if (action === "unset") {
|
|
4177
|
+
const key = subaction;
|
|
4178
|
+
if (!key) {
|
|
4179
|
+
console.error("Usage: autho config unset <key>");
|
|
4180
|
+
process.exit(1);
|
|
4181
|
+
}
|
|
4182
|
+
const updated = { ...config };
|
|
4183
|
+
delete updated[key];
|
|
4184
|
+
saveConfig(updated);
|
|
4185
|
+
console.log(`Removed ${key}`);
|
|
4186
|
+
return;
|
|
4187
|
+
}
|
|
4188
|
+
if (action === "path") {
|
|
4189
|
+
console.log(authoConfigDir() + "/config.json");
|
|
4190
|
+
return;
|
|
4191
|
+
}
|
|
4192
|
+
console.error(`Unknown config action: ${action}. Use: show, set, unset, path`);
|
|
4193
|
+
process.exit(1);
|
|
4194
|
+
}
|
|
4059
4195
|
if (scope === "project" && action === "init") {
|
|
4060
4196
|
output(writeProjectConfig({
|
|
4061
4197
|
force: getBoolean(args, "force"),
|
|
@@ -4167,7 +4303,7 @@ async function main() {
|
|
|
4167
4303
|
}
|
|
4168
4304
|
if (scope === "unlock" && getString(args, "recovery-file")) {
|
|
4169
4305
|
const recoveryFilePath = absolutePath(getString(args, "recovery-file"));
|
|
4170
|
-
const content =
|
|
4306
|
+
const content = readFileSync5(recoveryFilePath, "utf8");
|
|
4171
4307
|
const lines = content.split(`
|
|
4172
4308
|
`);
|
|
4173
4309
|
const tokenLineIdx = lines.findIndex((l) => l.trim() === "RECOVERY TOKEN:");
|