Read Setup URI generator values from LIVESYNC_ variables

hostname, username, and the other unprefixed names collide with shell
and system variables (fish makes hostname read-only, Windows already
defines USERNAME). The generator now reads LIVESYNC_HOST, LIVESYNC_USER,
LIVESYNC_PASS, LIVESYNC_DB, and LIVESYNC_PASSPHRASE first and falls back
to the old names, so existing instructions keep working.

Co-authored-by: rwbru <59871009+rwbru@users.noreply.github.com>
This commit is contained in:
Junker der Provinzandrwbru committed 2026-10-22 11:25:44 +02:00
1 parent ce0524d49f
commit b35ac635d0
7 files changed
+114 -24

No files matched your search

+70
View File
@@ -8,6 +8,76 @@ function assert(condition: unknown, message: string): asserts condition {
if (!condition) throw new Error(message);
}
Deno.test("reads LIVESYNC_ variables before the unprefixed names", async () => {
const generated = await generateSetupURI({
LIVESYNC_HOST: "https://couch.example.test",
LIVESYNC_USER: "alice",
LIVESYNC_PASS: "couch-secret",
LIVESYNC_DB: "notes",
LIVESYNC_PASSPHRASE: "vault-secret",
hostname: "https://shell.example.test",
username: "shell-user",
password: "shell-secret",
database: "shell-db",
passphrase: "shell-passphrase",
uri_passphrase: "setup-secret",
});
const decoded = await decodeSettingsFromSetupURI(
generated.setupURI,
generated.setupPassphrase,
);
assert(decoded, "Commonlib could not decode the CouchDB Setup URI");
const effective = { ...DEFAULT_SETTINGS, ...decoded };
assert(
effective.couchDB_URI === "https://couch.example.test" &&
effective.couchDB_USER === "alice" &&
effective.couchDB_PASSWORD === "couch-secret" &&
effective.couchDB_DBNAME === "notes",
"the CouchDB connection did not come from the LIVESYNC_ variables",
);
assert(
effective.passphrase === "vault-secret",
"the Vault passphrase did not come from LIVESYNC_PASSPHRASE",
);
});
Deno.test("falls back to the unprefixed names when LIVESYNC_ variables are blank", async () => {
const generated = await generateSetupURI({
LIVESYNC_HOST: " ",
hostname: "https://couch.example.test",
username: "alice",
password: "couch-secret",
database: "notes",
passphrase: "vault-secret",
uri_passphrase: "setup-secret",
});
const decoded = await decodeSettingsFromSetupURI(
generated.setupURI,
generated.setupPassphrase,
);
assert(decoded, "Commonlib could not decode the CouchDB Setup URI");
const effective = { ...DEFAULT_SETTINGS, ...decoded };
assert(
effective.couchDB_URI === "https://couch.example.test" &&
effective.couchDB_USER === "alice" &&
effective.couchDB_PASSWORD === "couch-secret" &&
effective.couchDB_DBNAME === "notes" &&
effective.passphrase === "vault-secret",
"the generator did not fall back to the unprefixed names",
);
});
Deno.test("names both variables when a CouchDB value is missing", async () => {
let rejected = false;
try {
await generateSetupURI({ uri_passphrase: "setup-secret" });
} catch (error) {
rejected = error instanceof Error &&
error.message === "LIVESYNC_HOST (or hostname) is required";
}
assert(rejected, "the generator did not name both host variables");
});
Deno.test("generates an Object Storage Setup URI with a selected S3 profile", async () => {
const generated = await generateSetupURI({
remote_type: "s3",
+15 -7
View File
@@ -64,9 +64,17 @@ function configureIdDerivation(
function requireValue(
environment: SetupGeneratorEnvironment,
name: string,
legacyName?: string,
): string {
const value = environment[name]?.trim();
if (!value) throw new Error(`${name} is required`);
const value = environment[name]?.trim() ||
(legacyName && environment[legacyName]?.trim());
if (!value) {
throw new Error(
legacyName
? `${name} (or ${legacyName}) is required`
: `${name} is required`,
);
}
return value;
}
@@ -97,7 +105,7 @@ function applyEncryptedVaultSettings(
Object.assign(settings, {
isConfigured: true,
encrypt: true,
passphrase: requireValue(environment, "passphrase"),
passphrase: requireValue(environment, "LIVESYNC_PASSPHRASE", "passphrase"),
usePathObfuscation: true,
});
}
@@ -107,10 +115,10 @@ function createCouchDBSettings(
): ObsidianLiveSyncSettings {
const settings = createNewVaultSettings();
Object.assign(settings, PREFERRED_SETTING_SELF_HOSTED, {
couchDB_URI: requireValue(environment, "hostname"),
couchDB_USER: requireValue(environment, "username"),
couchDB_PASSWORD: requireValue(environment, "password"),
couchDB_DBNAME: requireValue(environment, "database"),
couchDB_URI: requireValue(environment, "LIVESYNC_HOST", "hostname"),
couchDB_USER: requireValue(environment, "LIVESYNC_USER", "username"),
couchDB_PASSWORD: requireValue(environment, "LIVESYNC_PASS", "password"),
couchDB_DBNAME: requireValue(environment, "LIVESYNC_DB", "database"),
batchSave: true,
periodicReplication: true,
syncOnStart: true,