@geml/logseq-sync 2.0.3 → 2.0.5
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/package.json +1 -1
- package/watcher/bin/logseq-sync.mjs +41 -14
package/package.json
CHANGED
|
@@ -135,7 +135,9 @@ for (let i = 0; i < args.length; i++) {
|
|
|
135
135
|
} else if (arg === "--api-server-token") {
|
|
136
136
|
needValue(i, "--api-server-token");
|
|
137
137
|
flags.apiServerToken = args[++i];
|
|
138
|
-
} else if (arg.startsWith("
|
|
138
|
+
} else if (arg.startsWith("-")) {
|
|
139
|
+
// One dash included: "-graph demo" once sailed through as a graph literally
|
|
140
|
+
// named "-graph" and a vault named "demo" — a typo must stop, not sync.
|
|
139
141
|
console.error(`Error: Unknown flag "${arg}". Run \`logseq-sync --help\` for usage.`);
|
|
140
142
|
process.exit(2);
|
|
141
143
|
} else if (subcommand === null && positional.length === 0 && (arg === "doctor" || arg === "restore")) {
|
|
@@ -278,13 +280,13 @@ function resolveGraphOrExit() {
|
|
|
278
280
|
if (detected?.candidates) {
|
|
279
281
|
console.error(
|
|
280
282
|
`Error: several graphs and none open in the app — ${detected.candidates.join(", ")}. ` +
|
|
281
|
-
`Pick one with --graph <name
|
|
283
|
+
`Pick one with --graph <name>. Run \`logseq-sync doctor\` for the full picture.`
|
|
282
284
|
);
|
|
283
285
|
process.exit(2);
|
|
284
286
|
}
|
|
285
287
|
console.error(
|
|
286
288
|
`Error: no Logseq graphs found under ${join(logseqRootDir(probe), "graphs")}. ` +
|
|
287
|
-
`Open a graph in Logseq first
|
|
289
|
+
`Open a graph in Logseq first. Run \`logseq-sync doctor\` for the full picture.`
|
|
288
290
|
);
|
|
289
291
|
process.exit(2);
|
|
290
292
|
}
|
|
@@ -293,7 +295,8 @@ function resolveVaultOrExit() {
|
|
|
293
295
|
if (vaultRaw) return resolve(expandHome(vaultRaw));
|
|
294
296
|
console.error(
|
|
295
297
|
`Error: no vault directory. Set it in Logseq — Settings → Plugins → ${PLUGIN_TITLE} → ` +
|
|
296
|
-
`"Vault folder" — or pass one: logseq-sync <vault-dir
|
|
298
|
+
`"Vault folder" — or pass one: logseq-sync <vault-dir>. ` +
|
|
299
|
+
`Run \`logseq-sync doctor\` for the full picture.`
|
|
297
300
|
);
|
|
298
301
|
process.exit(2);
|
|
299
302
|
}
|
|
@@ -395,20 +398,34 @@ if (subcommand === "doctor") doctor();
|
|
|
395
398
|
graphName = resolveGraphOrExit();
|
|
396
399
|
|
|
397
400
|
// Validate graph name to prevent command/path injection
|
|
398
|
-
|
|
401
|
+
// The first character must not be a dash or a dot: the name travels as argv
|
|
402
|
+
// into the exporting CLI, where a leading dash reads as a flag ("-graph"
|
|
403
|
+
// arrived here as a real user typo for --graph), and "." / ".." read as paths.
|
|
404
|
+
if (!/^[a-zA-Z0-9_][a-zA-Z0-9_.-]*$/.test(graphName)) {
|
|
399
405
|
console.error(`Error: Invalid graph name "${graphName}". Only alphanumeric characters, hyphens, and underscores are allowed.`);
|
|
400
406
|
process.exit(2);
|
|
401
407
|
}
|
|
402
408
|
|
|
403
409
|
// `logseq graph export --graph <name>` does not fail on an unknown name — it
|
|
404
410
|
// CREATES that graph and exports the empty result. A typo would then sync
|
|
405
|
-
// emptiness over the vault and commit it. Refuse names we cannot see
|
|
406
|
-
//
|
|
407
|
-
//
|
|
408
|
-
|
|
411
|
+
// emptiness over the vault and commit it. Refuse names we cannot see,
|
|
412
|
+
// INCLUDING when we see none at all: a bare run calls zero graphs a hard
|
|
413
|
+
// error, and naming one does not make graphs exist — treating the same state
|
|
414
|
+
// as "cannot verify, proceed" is how `--graph demo` once sailed past this
|
|
415
|
+
// check straight into the vault error, and reads as a contradiction. The
|
|
416
|
+
// escape hatches are real, not hypothetical: LOGSEQ_ROOT_DIR when the graphs
|
|
417
|
+
// live elsewhere, and the API-server route, which exports whatever graph the
|
|
418
|
+
// app has open and ignores local directories entirely.
|
|
419
|
+
if (!apiServerToken && !knownGraphs.includes(graphName)) {
|
|
409
420
|
console.error(
|
|
410
|
-
|
|
411
|
-
`
|
|
421
|
+
knownGraphs.length > 0
|
|
422
|
+
? `Error: no graph named "${graphName}" — found ${knownGraphs.join(", ")}. ` +
|
|
423
|
+
`(The app CLI would silently create "${graphName}" rather than fail.) ` +
|
|
424
|
+
`Run \`logseq-sync doctor\` for the full picture.`
|
|
425
|
+
: `Error: no graph named "${graphName}" — no graphs found under ` +
|
|
426
|
+
`${join(logseqRootDir(probe), "graphs")} at all, and the app CLI would silently ` +
|
|
427
|
+
`create "${graphName}" and sync emptiness. If your graphs live elsewhere, set ` +
|
|
428
|
+
`LOGSEQ_ROOT_DIR. Run \`logseq-sync doctor\` for the full picture.`
|
|
412
429
|
);
|
|
413
430
|
process.exit(2);
|
|
414
431
|
}
|
|
@@ -476,9 +493,19 @@ function runLogseqCli(...cmdArgs) {
|
|
|
476
493
|
});
|
|
477
494
|
}
|
|
478
495
|
|
|
479
|
-
//
|
|
480
|
-
|
|
481
|
-
|
|
496
|
+
// On Windows the npx fallback is an instruction, not a spawn: Node refuses
|
|
497
|
+
// to run a .cmd without a shell (CVE-2024-27980), and routing a user-typed
|
|
498
|
+
// graph name through cmd.exe to get around that is how injection happens.
|
|
499
|
+
// Every prior attempt died as `spawnSync npx.cmd EINVAL`, once every poll.
|
|
500
|
+
if (process.platform === "win32") {
|
|
501
|
+
throw new Error(
|
|
502
|
+
"@logseq/cli is not installed where I can see it. Install it once\n" +
|
|
503
|
+
" (mkdir logseq-cli && cd logseq-cli && npm init -y && npm i @logseq/cli)\n" +
|
|
504
|
+
"and point LOGSEQ_CLI_DIR at that directory — or pass --app-cli <path>\n" +
|
|
505
|
+
"to the desktop app's CLI."
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
return execFileSync("npx", ["-y", "@logseq/cli", ...cmdArgs], {
|
|
482
509
|
cwd: cliCwd,
|
|
483
510
|
encoding: "utf8",
|
|
484
511
|
shell: false,
|