mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-10-26 11:03:21 +00:00
Merge main and verify Setup URI command compatibility
This commit is contained in:
commit
0b0be8f367
107 files changed
+6288
-695
No files matched your search
@@ -1,6 +1,8 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
import {
|
||||
decodeSettingsFromSetupURI,
|
||||
DEFAULT_SETTINGS,
|
||||
PREFERRED_JOURNAL_SYNC,
|
||||
} from "./livesync-commonlib.ts";
|
||||
import { generateSetupURI } from "./generate_setup_uri.ts";
|
||||
|
||||
@@ -125,8 +127,8 @@ Deno.test("generates an Object Storage Setup URI with a selected S3 profile", as
|
||||
"the Setup URI left the imported device unconfigured",
|
||||
);
|
||||
assert(
|
||||
effective.customChunkSize === 10,
|
||||
"the journal chunk-size preset was not applied",
|
||||
effective.customChunkSize === PREFERRED_JOURNAL_SYNC.customChunkSize,
|
||||
"the Object Storage Setup URI did not use its Commonlib journal chunk-size preference",
|
||||
);
|
||||
assert(
|
||||
effective.liveSync,
|
||||
@@ -192,7 +194,7 @@ Deno.test("generates a random-room P2P Setup URI without copying a device identi
|
||||
);
|
||||
assert(
|
||||
effective.customChunkSize === 0,
|
||||
"the P2P profile inherited the self-hosted CouchDB chunk-size recommendation",
|
||||
"the P2P Setup URI did not retain its zero chunk-size value",
|
||||
);
|
||||
assert(
|
||||
effective.sendChunksBulkMaxSize === 1,
|
||||
@@ -328,3 +330,171 @@ for (const mode of ["ephemeral", "persistent"] as const) {
|
||||
assert(rejected, "legacy mode silently ignored a recovery code");
|
||||
});
|
||||
}
|
||||
|
||||
const couchDBConnection = {
|
||||
hostname: "https://couch.example.test",
|
||||
username: "alice",
|
||||
password: "couch-secret",
|
||||
database: "notes",
|
||||
passphrase: "vault-secret",
|
||||
};
|
||||
const prefixedCouchDBConnection = {
|
||||
LIVESYNC_HOST: couchDBConnection.hostname,
|
||||
LIVESYNC_USER: couchDBConnection.username,
|
||||
LIVESYNC_PASS: couchDBConnection.password,
|
||||
LIVESYNC_DB: couchDBConnection.database,
|
||||
LIVESYNC_PASSPHRASE: couchDBConnection.passphrase,
|
||||
};
|
||||
const commandEnvironments: { name: string; values: Record<string, string> }[] =
|
||||
[
|
||||
{ name: "prefixed values only", values: prefixedCouchDBConnection },
|
||||
{
|
||||
name: "prefixed values before conflicting legacy values",
|
||||
values: {
|
||||
...prefixedCouchDBConnection,
|
||||
hostname: "https://shell.example.test",
|
||||
username: "shell-user",
|
||||
password: "shell-password",
|
||||
database: "shell-database",
|
||||
passphrase: "shell-passphrase",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "blank prefixed values fall back to legacy values",
|
||||
values: {
|
||||
...couchDBConnection,
|
||||
LIVESYNC_HOST: " ",
|
||||
LIVESYNC_USER: "\t",
|
||||
LIVESYNC_PASS: " ",
|
||||
LIVESYNC_DB: "\t",
|
||||
LIVESYNC_PASSPHRASE: " ",
|
||||
},
|
||||
},
|
||||
{ name: "compatibility: legacy values only", values: couchDBConnection },
|
||||
];
|
||||
|
||||
async function runGeneratorCommand(
|
||||
script: URL,
|
||||
values: Record<string, string>,
|
||||
) {
|
||||
const environment = Deno.env.toObject();
|
||||
const inputNames = new Set([
|
||||
...Object.keys(couchDBConnection),
|
||||
...Object.keys(prefixedCouchDBConnection),
|
||||
"remote_type",
|
||||
"uri_passphrase",
|
||||
"uri_mode",
|
||||
"id_mode",
|
||||
"id_recovery_code",
|
||||
"endpoint",
|
||||
"access_key",
|
||||
"secret_key",
|
||||
"bucket",
|
||||
"region",
|
||||
"bucket_prefix",
|
||||
"bucket_custom_headers",
|
||||
"use_custom_request_handler",
|
||||
"force_path_style",
|
||||
"p2p_room_id",
|
||||
"p2p_passphrase",
|
||||
"p2p_relays",
|
||||
"p2p_app_id",
|
||||
"p2p_auto_start",
|
||||
"p2p_auto_broadcast",
|
||||
].map((name) => name.toLowerCase()));
|
||||
for (const name of Object.keys(environment)) {
|
||||
if (inputNames.has(name.toLowerCase())) delete environment[name];
|
||||
}
|
||||
const result = await new Deno.Command(Deno.execPath(), {
|
||||
args: [
|
||||
"run",
|
||||
"--config",
|
||||
fileURLToPath(new URL("../flyio/deno.jsonc", import.meta.url)),
|
||||
"--frozen",
|
||||
"--lock",
|
||||
fileURLToPath(new URL("../flyio/deno.lock", import.meta.url)),
|
||||
"--allow-env",
|
||||
script.href,
|
||||
],
|
||||
clearEnv: true,
|
||||
env: {
|
||||
...environment,
|
||||
uri_passphrase: "setup-secret",
|
||||
uri_mode: "persistent",
|
||||
...values,
|
||||
},
|
||||
stdout: "piped",
|
||||
stderr: "piped",
|
||||
}).output();
|
||||
assert(
|
||||
result.success,
|
||||
`generator failed: ${new TextDecoder().decode(result.stderr)}`,
|
||||
);
|
||||
const output = new TextDecoder().decode(result.stdout);
|
||||
const uri = output.match(/obsidian:\/\/setuplivesync\?settings=\S+/u)?.[0];
|
||||
assert(uri, "the command did not print a Setup URI");
|
||||
const decoded = await decodeSettingsFromSetupURI(uri, "setup-secret");
|
||||
assert(decoded, "the command output could not be decoded");
|
||||
return { ...DEFAULT_SETTINGS, ...decoded };
|
||||
}
|
||||
|
||||
for (
|
||||
const [name, path] of [
|
||||
["Setup generator", "./generate_setup_uri.ts"],
|
||||
["Fly.io wrapper", "../flyio/generate_setupuri.ts"],
|
||||
]
|
||||
) {
|
||||
for (const scenario of commandEnvironments) {
|
||||
Deno.test(`E2E ${name}: ${scenario.name}`, async () => {
|
||||
const settings = await runGeneratorCommand(
|
||||
new URL(path, import.meta.url),
|
||||
scenario.values,
|
||||
);
|
||||
assert(
|
||||
settings.couchDB_URI === couchDBConnection.hostname &&
|
||||
settings.couchDB_USER === couchDBConnection.username &&
|
||||
settings.couchDB_PASSWORD === couchDBConnection.password &&
|
||||
settings.couchDB_DBNAME === couchDBConnection.database &&
|
||||
settings.passphrase === couchDBConnection.passphrase,
|
||||
"the command did not preserve the selected connection and Vault passphrase",
|
||||
);
|
||||
const profileId = settings.activeConfigurationId;
|
||||
const profile = profileId
|
||||
? settings.remoteConfigurations?.[profileId]
|
||||
: undefined;
|
||||
assert(
|
||||
profile?.uri.startsWith("sls+https://"),
|
||||
"the generated URI did not select its CouchDB profile",
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const remoteType of ["s3", "p2p"]) {
|
||||
Deno.test(`E2E Setup generator: prefixed Vault passphrase for ${remoteType}`, async () => {
|
||||
const settings = await runGeneratorCommand(
|
||||
new URL("./generate_setup_uri.ts", import.meta.url),
|
||||
{
|
||||
remote_type: remoteType,
|
||||
endpoint: "https://objects.example.test",
|
||||
access_key: "access-key",
|
||||
secret_key: "secret-key",
|
||||
bucket: "vault-data",
|
||||
LIVESYNC_PASSPHRASE: "vault-secret",
|
||||
passphrase: "shell-passphrase",
|
||||
},
|
||||
);
|
||||
assert(
|
||||
settings.passphrase === "vault-secret",
|
||||
"the command did not prefer LIVESYNC_PASSPHRASE",
|
||||
);
|
||||
const profileId = settings.activeConfigurationId;
|
||||
const profile = profileId
|
||||
? settings.remoteConfigurations?.[profileId]
|
||||
: undefined;
|
||||
assert(
|
||||
profile?.uri.startsWith(`sls+${remoteType}://`),
|
||||
"the command did not select the requested remote profile",
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -5,10 +5,10 @@ export {
|
||||
decodeSettingsFromSetupURI,
|
||||
encodeTimeBoundSetupURI,
|
||||
isTimeBoundSetupURIUsableNow,
|
||||
} from "npm:@vrtmrz/livesync-commonlib@0.1.34/setup-uri";
|
||||
export type { TimeBoundSetupURIMode } from "npm:@vrtmrz/livesync-commonlib@0.1.34/setup-uri";
|
||||
export { generateP2PRoomId } from "npm:@vrtmrz/livesync-commonlib@0.1.34/compat/common/utils";
|
||||
export { upsertRemoteConfigurationInPlace } from "npm:@vrtmrz/livesync-commonlib@0.1.34/remote-configurations";
|
||||
} from "npm:@vrtmrz/livesync-commonlib@0.2.0/setup-uri";
|
||||
export type { TimeBoundSetupURIMode } from "npm:@vrtmrz/livesync-commonlib@0.2.0/setup-uri";
|
||||
export { generateP2PRoomId } from "npm:@vrtmrz/livesync-commonlib@0.2.0/compat/common/utils";
|
||||
export { upsertRemoteConfigurationInPlace } from "npm:@vrtmrz/livesync-commonlib@0.2.0/remote-configurations";
|
||||
export {
|
||||
createNewVaultSettings,
|
||||
DEFAULT_SETTINGS,
|
||||
@@ -16,5 +16,5 @@ export {
|
||||
PREFERRED_BASE,
|
||||
PREFERRED_JOURNAL_SYNC,
|
||||
PREFERRED_SETTING_SELF_HOSTED,
|
||||
} from "npm:@vrtmrz/livesync-commonlib@0.1.34/settings";
|
||||
export type { ObsidianLiveSyncSettings } from "npm:@vrtmrz/livesync-commonlib@0.1.34/settings";
|
||||
} from "npm:@vrtmrz/livesync-commonlib@0.2.0/settings";
|
||||
export type { ObsidianLiveSyncSettings } from "npm:@vrtmrz/livesync-commonlib@0.2.0/settings";
|
||||
Reference in new issue
Block a user