opsidian 0.1.0 → 0.1.1
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/opsidian.mjs +102 -65
- package/package.json +1 -1
package/dist/opsidian.mjs
CHANGED
|
@@ -8059,7 +8059,7 @@ var require_thread_stream = __commonJS({
|
|
|
8059
8059
|
var { version } = require_package();
|
|
8060
8060
|
var { EventEmitter } = __require("events");
|
|
8061
8061
|
var { Worker } = __require("worker_threads");
|
|
8062
|
-
var { join:
|
|
8062
|
+
var { join: join5 } = __require("path");
|
|
8063
8063
|
var { pathToFileURL } = __require("url");
|
|
8064
8064
|
var { wait } = require_wait();
|
|
8065
8065
|
var {
|
|
@@ -8110,7 +8110,7 @@ var require_thread_stream = __commonJS({
|
|
|
8110
8110
|
function createWorker(stream, opts) {
|
|
8111
8111
|
const { filename, workerData } = opts;
|
|
8112
8112
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
8113
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
8113
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join5(__dirname, "lib", "worker.js");
|
|
8114
8114
|
const worker = new Worker(toExecute, {
|
|
8115
8115
|
...opts.workerOpts,
|
|
8116
8116
|
name: opts.workerOpts?.name || "thread-stream",
|
|
@@ -8578,7 +8578,7 @@ var require_transport = __commonJS({
|
|
|
8578
8578
|
var { createRequire } = __require("module");
|
|
8579
8579
|
var { existsSync: existsSync4 } = __require("node:fs");
|
|
8580
8580
|
var getCallers = require_caller();
|
|
8581
|
-
var { join:
|
|
8581
|
+
var { join: join5, isAbsolute, sep } = __require("node:path");
|
|
8582
8582
|
var { fileURLToPath: fileURLToPath2 } = __require("node:url");
|
|
8583
8583
|
var sleep = require_atomic_sleep();
|
|
8584
8584
|
var onExit = require_on_exit_leak_free();
|
|
@@ -8733,7 +8733,7 @@ var require_transport = __commonJS({
|
|
|
8733
8733
|
throw new Error("only one of target or targets can be specified");
|
|
8734
8734
|
}
|
|
8735
8735
|
if (targets) {
|
|
8736
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
8736
|
+
target = bundlerOverrides["pino-worker"] || join5(__dirname, "worker.js");
|
|
8737
8737
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
8738
8738
|
return {
|
|
8739
8739
|
...dest,
|
|
@@ -8754,7 +8754,7 @@ var require_transport = __commonJS({
|
|
|
8754
8754
|
const pipelinesHaveLevel = options.pipelines.some((p) => p.some((t) => t.level != null));
|
|
8755
8755
|
usesMultistream = options.targets.length + options.pipelines.length > 1 || targetsHaveLevel || pipelinesHaveLevel;
|
|
8756
8756
|
} else if (pipeline) {
|
|
8757
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
8757
|
+
target = bundlerOverrides["pino-worker"] || join5(__dirname, "worker.js");
|
|
8758
8758
|
options.pipelines = [pipeline.map((dest) => {
|
|
8759
8759
|
return {
|
|
8760
8760
|
...dest,
|
|
@@ -8781,7 +8781,7 @@ var require_transport = __commonJS({
|
|
|
8781
8781
|
return origin;
|
|
8782
8782
|
}
|
|
8783
8783
|
if (origin === "pino/file") {
|
|
8784
|
-
return
|
|
8784
|
+
return join5(__dirname, "..", "file.js");
|
|
8785
8785
|
}
|
|
8786
8786
|
let fixTarget2;
|
|
8787
8787
|
for (const filePath of callers) {
|
|
@@ -9761,7 +9761,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
9761
9761
|
return circularValue;
|
|
9762
9762
|
}
|
|
9763
9763
|
let res = "";
|
|
9764
|
-
let
|
|
9764
|
+
let join5 = ",";
|
|
9765
9765
|
const originalIndentation = indentation;
|
|
9766
9766
|
if (Array.isArray(value)) {
|
|
9767
9767
|
if (value.length === 0) {
|
|
@@ -9775,7 +9775,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
9775
9775
|
indentation += spacer;
|
|
9776
9776
|
res += `
|
|
9777
9777
|
${indentation}`;
|
|
9778
|
-
|
|
9778
|
+
join5 = `,
|
|
9779
9779
|
${indentation}`;
|
|
9780
9780
|
}
|
|
9781
9781
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -9783,13 +9783,13 @@ ${indentation}`;
|
|
|
9783
9783
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
9784
9784
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
9785
9785
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
9786
|
-
res +=
|
|
9786
|
+
res += join5;
|
|
9787
9787
|
}
|
|
9788
9788
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
9789
9789
|
res += tmp !== void 0 ? tmp : "null";
|
|
9790
9790
|
if (value.length - 1 > maximumBreadth) {
|
|
9791
9791
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
9792
|
-
res += `${
|
|
9792
|
+
res += `${join5}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
9793
9793
|
}
|
|
9794
9794
|
if (spacer !== "") {
|
|
9795
9795
|
res += `
|
|
@@ -9810,7 +9810,7 @@ ${originalIndentation}`;
|
|
|
9810
9810
|
let separator = "";
|
|
9811
9811
|
if (spacer !== "") {
|
|
9812
9812
|
indentation += spacer;
|
|
9813
|
-
|
|
9813
|
+
join5 = `,
|
|
9814
9814
|
${indentation}`;
|
|
9815
9815
|
whitespace = " ";
|
|
9816
9816
|
}
|
|
@@ -9824,13 +9824,13 @@ ${indentation}`;
|
|
|
9824
9824
|
const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
|
|
9825
9825
|
if (tmp !== void 0) {
|
|
9826
9826
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
9827
|
-
separator =
|
|
9827
|
+
separator = join5;
|
|
9828
9828
|
}
|
|
9829
9829
|
}
|
|
9830
9830
|
if (keyLength > maximumBreadth) {
|
|
9831
9831
|
const removedKeys = keyLength - maximumBreadth;
|
|
9832
9832
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
9833
|
-
separator =
|
|
9833
|
+
separator = join5;
|
|
9834
9834
|
}
|
|
9835
9835
|
if (spacer !== "" && separator.length > 1) {
|
|
9836
9836
|
res = `
|
|
@@ -9871,7 +9871,7 @@ ${originalIndentation}`;
|
|
|
9871
9871
|
}
|
|
9872
9872
|
const originalIndentation = indentation;
|
|
9873
9873
|
let res = "";
|
|
9874
|
-
let
|
|
9874
|
+
let join5 = ",";
|
|
9875
9875
|
if (Array.isArray(value)) {
|
|
9876
9876
|
if (value.length === 0) {
|
|
9877
9877
|
return "[]";
|
|
@@ -9884,7 +9884,7 @@ ${originalIndentation}`;
|
|
|
9884
9884
|
indentation += spacer;
|
|
9885
9885
|
res += `
|
|
9886
9886
|
${indentation}`;
|
|
9887
|
-
|
|
9887
|
+
join5 = `,
|
|
9888
9888
|
${indentation}`;
|
|
9889
9889
|
}
|
|
9890
9890
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -9892,13 +9892,13 @@ ${indentation}`;
|
|
|
9892
9892
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
9893
9893
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
9894
9894
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
9895
|
-
res +=
|
|
9895
|
+
res += join5;
|
|
9896
9896
|
}
|
|
9897
9897
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
9898
9898
|
res += tmp !== void 0 ? tmp : "null";
|
|
9899
9899
|
if (value.length - 1 > maximumBreadth) {
|
|
9900
9900
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
9901
|
-
res += `${
|
|
9901
|
+
res += `${join5}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
9902
9902
|
}
|
|
9903
9903
|
if (spacer !== "") {
|
|
9904
9904
|
res += `
|
|
@@ -9911,7 +9911,7 @@ ${originalIndentation}`;
|
|
|
9911
9911
|
let whitespace = "";
|
|
9912
9912
|
if (spacer !== "") {
|
|
9913
9913
|
indentation += spacer;
|
|
9914
|
-
|
|
9914
|
+
join5 = `,
|
|
9915
9915
|
${indentation}`;
|
|
9916
9916
|
whitespace = " ";
|
|
9917
9917
|
}
|
|
@@ -9920,7 +9920,7 @@ ${indentation}`;
|
|
|
9920
9920
|
const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
|
|
9921
9921
|
if (tmp !== void 0) {
|
|
9922
9922
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
9923
|
-
separator =
|
|
9923
|
+
separator = join5;
|
|
9924
9924
|
}
|
|
9925
9925
|
}
|
|
9926
9926
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -9978,20 +9978,20 @@ ${originalIndentation}`;
|
|
|
9978
9978
|
indentation += spacer;
|
|
9979
9979
|
let res2 = `
|
|
9980
9980
|
${indentation}`;
|
|
9981
|
-
const
|
|
9981
|
+
const join6 = `,
|
|
9982
9982
|
${indentation}`;
|
|
9983
9983
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
9984
9984
|
let i = 0;
|
|
9985
9985
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
9986
9986
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
9987
9987
|
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
9988
|
-
res2 +=
|
|
9988
|
+
res2 += join6;
|
|
9989
9989
|
}
|
|
9990
9990
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
9991
9991
|
res2 += tmp !== void 0 ? tmp : "null";
|
|
9992
9992
|
if (value.length - 1 > maximumBreadth) {
|
|
9993
9993
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
9994
|
-
res2 += `${
|
|
9994
|
+
res2 += `${join6}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
9995
9995
|
}
|
|
9996
9996
|
res2 += `
|
|
9997
9997
|
${originalIndentation}`;
|
|
@@ -10007,16 +10007,16 @@ ${originalIndentation}`;
|
|
|
10007
10007
|
return '"[Object]"';
|
|
10008
10008
|
}
|
|
10009
10009
|
indentation += spacer;
|
|
10010
|
-
const
|
|
10010
|
+
const join5 = `,
|
|
10011
10011
|
${indentation}`;
|
|
10012
10012
|
let res = "";
|
|
10013
10013
|
let separator = "";
|
|
10014
10014
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
10015
10015
|
if (isTypedArrayWithEntries(value)) {
|
|
10016
|
-
res += stringifyTypedArray(value,
|
|
10016
|
+
res += stringifyTypedArray(value, join5, maximumBreadth);
|
|
10017
10017
|
keys = keys.slice(value.length);
|
|
10018
10018
|
maximumPropertiesToStringify -= value.length;
|
|
10019
|
-
separator =
|
|
10019
|
+
separator = join5;
|
|
10020
10020
|
}
|
|
10021
10021
|
if (deterministic) {
|
|
10022
10022
|
keys = sort(keys, comparator);
|
|
@@ -10027,13 +10027,13 @@ ${indentation}`;
|
|
|
10027
10027
|
const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
|
|
10028
10028
|
if (tmp !== void 0) {
|
|
10029
10029
|
res += `${separator}${strEscape(key2)}: ${tmp}`;
|
|
10030
|
-
separator =
|
|
10030
|
+
separator = join5;
|
|
10031
10031
|
}
|
|
10032
10032
|
}
|
|
10033
10033
|
if (keyLength > maximumBreadth) {
|
|
10034
10034
|
const removedKeys = keyLength - maximumBreadth;
|
|
10035
10035
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
10036
|
-
separator =
|
|
10036
|
+
separator = join5;
|
|
10037
10037
|
}
|
|
10038
10038
|
if (separator !== "") {
|
|
10039
10039
|
res = `
|
|
@@ -38284,7 +38284,7 @@ ${body}`);
|
|
|
38284
38284
|
import { spawn } from "node:child_process";
|
|
38285
38285
|
import { existsSync as existsSync3 } from "node:fs";
|
|
38286
38286
|
import { copyFile as copyFile2, mkdir as mkdir4, readFile as readFile3, rm as rm3 } from "node:fs/promises";
|
|
38287
|
-
import { dirname as dirname3, resolve } from "node:path";
|
|
38287
|
+
import { dirname as dirname3, join as join4, resolve } from "node:path";
|
|
38288
38288
|
import { fileURLToPath } from "node:url";
|
|
38289
38289
|
|
|
38290
38290
|
// src/host.ts
|
|
@@ -40460,6 +40460,20 @@ function place(home = process.env.OPSIDIAN_HOME || join2(homedir(), ".opsidian")
|
|
|
40460
40460
|
};
|
|
40461
40461
|
}
|
|
40462
40462
|
var DEFAULT_PORT = 4810;
|
|
40463
|
+
var BOOLEAN = /* @__PURE__ */ new Set(["follow", "f", "delete-data", "help", "h", "version", "v"]);
|
|
40464
|
+
function parseArgs(argv) {
|
|
40465
|
+
const flags2 = /* @__PURE__ */ new Map();
|
|
40466
|
+
const words2 = [];
|
|
40467
|
+
for (let position = 0; position < argv.length; position++) {
|
|
40468
|
+
const word = argv[position];
|
|
40469
|
+
const match = word.match(/^--?([a-z][a-z-]*)(?:=(.*))?$/);
|
|
40470
|
+
if (!match) words2.push(word);
|
|
40471
|
+
else if (match[2] !== void 0) flags2.set(match[1], match[2]);
|
|
40472
|
+
else if (BOOLEAN.has(match[1])) flags2.set(match[1], "");
|
|
40473
|
+
else flags2.set(match[1], argv[++position] ?? "");
|
|
40474
|
+
}
|
|
40475
|
+
return { flags: flags2, words: words2 };
|
|
40476
|
+
}
|
|
40463
40477
|
async function readConfig(where2) {
|
|
40464
40478
|
try {
|
|
40465
40479
|
return JSON.parse(await readFile2(where2.config, "utf8"));
|
|
@@ -40605,8 +40619,16 @@ var Launchd = class {
|
|
|
40605
40619
|
await writeFile3(this.file, launchdPlist(this.where));
|
|
40606
40620
|
await run("launchctl", ["bootout", `${this.target}/${LABEL}`]).catch(() => {
|
|
40607
40621
|
});
|
|
40622
|
+
for (let tries = 0; tries < 50 && await this.loaded(); tries++)
|
|
40623
|
+
await new Promise((done) => setTimeout(done, 100));
|
|
40608
40624
|
await run("launchctl", ["bootstrap", this.target, this.file]);
|
|
40609
40625
|
}
|
|
40626
|
+
async loaded() {
|
|
40627
|
+
return run("launchctl", ["print", `${this.target}/${LABEL}`]).then(
|
|
40628
|
+
() => true,
|
|
40629
|
+
() => false
|
|
40630
|
+
);
|
|
40631
|
+
}
|
|
40610
40632
|
async remove() {
|
|
40611
40633
|
await run("launchctl", ["bootout", `${this.target}/${LABEL}`]).catch(() => {
|
|
40612
40634
|
});
|
|
@@ -40689,24 +40711,27 @@ function service(where2) {
|
|
|
40689
40711
|
}
|
|
40690
40712
|
|
|
40691
40713
|
// src/cli.ts
|
|
40692
|
-
var VERSION = "0.1.
|
|
40714
|
+
var VERSION = "0.1.1";
|
|
40693
40715
|
var me = process.env.npm_lifecycle_event === "start" ? "pnpm" : process.env.npm_command === "exec" ? "npx opsidian" : "opsidian";
|
|
40694
|
-
var
|
|
40695
|
-
var flags = /* @__PURE__ */ new Map();
|
|
40696
|
-
var words = [];
|
|
40697
|
-
var argv = process.argv.slice(2);
|
|
40698
|
-
for (let position = 0; position < argv.length; position++) {
|
|
40699
|
-
const word = argv[position];
|
|
40700
|
-
const flag = word.match(/^--?([a-z-]+)$/)?.[1];
|
|
40701
|
-
if (!flag) words.push(word);
|
|
40702
|
-
else if (BOOLEAN.has(flag)) flags.set(flag, "");
|
|
40703
|
-
else flags.set(flag, argv[++position] ?? "");
|
|
40704
|
-
}
|
|
40716
|
+
var { flags, words } = parseArgs(process.argv.slice(2));
|
|
40705
40717
|
var where = place();
|
|
40706
40718
|
var when = (time) => new Date(time).toLocaleString();
|
|
40707
40719
|
var fail = (text) => {
|
|
40708
40720
|
throw new Error(text);
|
|
40709
40721
|
};
|
|
40722
|
+
var whole = (name, fallback, low, high) => {
|
|
40723
|
+
const given = flags.get(name);
|
|
40724
|
+
if (given === void 0) return fallback;
|
|
40725
|
+
const value = Number(given);
|
|
40726
|
+
if (!Number.isInteger(value) || value < low || value > high)
|
|
40727
|
+
fail(`--${name} takes a whole number from ${low} to ${high}.`);
|
|
40728
|
+
return value;
|
|
40729
|
+
};
|
|
40730
|
+
var backupFrom = (folder, before) => ({
|
|
40731
|
+
folder: resolve(folder),
|
|
40732
|
+
keep: whole("keep", before?.keep ?? 14, 1, 1e3),
|
|
40733
|
+
hour: whole("hour", before?.hour ?? 3, 0, 23)
|
|
40734
|
+
});
|
|
40710
40735
|
var HELP = `Opsidian ${VERSION}: a host for your notebooks, so every device syncs through it.
|
|
40711
40736
|
|
|
40712
40737
|
${me} host start Run the host in the background, now and after restarts
|
|
@@ -40753,10 +40778,14 @@ async function withHost(work) {
|
|
|
40753
40778
|
}
|
|
40754
40779
|
async function deviceAddress() {
|
|
40755
40780
|
if (process.env.OPSIDIAN_ADDRESS) return process.env.OPSIDIAN_ADDRESS;
|
|
40781
|
+
if (existsSync3("/.dockerenv"))
|
|
40782
|
+
fail(
|
|
40783
|
+
"Inside Docker the host cannot see the address devices reach it at.\nRun the container with -e OPSIDIAN_ADDRESS=100.x.y.z:4810 (the server\u2019s Tailscale address)."
|
|
40784
|
+
);
|
|
40756
40785
|
const config = await readConfig(where);
|
|
40757
40786
|
return reachableAt({
|
|
40758
40787
|
address: flags.get("address") ?? config?.address ?? "0.0.0.0",
|
|
40759
|
-
port:
|
|
40788
|
+
port: whole("port", config?.port ?? DEFAULT_PORT, 1, 65535)
|
|
40760
40789
|
});
|
|
40761
40790
|
}
|
|
40762
40791
|
async function lastLines(count) {
|
|
@@ -40771,17 +40800,19 @@ function backupLine(config) {
|
|
|
40771
40800
|
async function start() {
|
|
40772
40801
|
const manager = needService();
|
|
40773
40802
|
const before = await readConfig(where);
|
|
40774
|
-
const port =
|
|
40775
|
-
if (!Number.isInteger(port) || port < 1 || port > 65535) fail("--port takes a number.");
|
|
40803
|
+
const port = whole("port", before?.port ?? DEFAULT_PORT, 1, 65535);
|
|
40776
40804
|
let address = flags.get("address");
|
|
40805
|
+
let manual = address !== void 0 || before?.manual === true;
|
|
40777
40806
|
let note;
|
|
40778
40807
|
if (address === "all") {
|
|
40779
40808
|
address = "0.0.0.0";
|
|
40780
40809
|
note = "The host listens on every address. It has no sign-in of its own: make sure a firewall keeps it off the open internet.";
|
|
40781
40810
|
} else if (!address) {
|
|
40782
40811
|
const found = addresses();
|
|
40783
|
-
if (before && found.some((each) => each.ip === before.address))
|
|
40812
|
+
if (manual && before && (before.address === "0.0.0.0" || found.some((each) => each.ip === before.address)))
|
|
40813
|
+
address = before.address;
|
|
40784
40814
|
else {
|
|
40815
|
+
manual = false;
|
|
40785
40816
|
const chosen = chooseAddress(found, process.platform);
|
|
40786
40817
|
if ("error" in chosen) return fail(chosen.error);
|
|
40787
40818
|
address = chosen.ip;
|
|
@@ -40789,15 +40820,18 @@ async function start() {
|
|
|
40789
40820
|
}
|
|
40790
40821
|
}
|
|
40791
40822
|
const config = { ...before, port, address };
|
|
40823
|
+
if (manual) config.manual = true;
|
|
40824
|
+
else delete config.manual;
|
|
40792
40825
|
const folder = flags.get("backup");
|
|
40793
|
-
if (folder)
|
|
40794
|
-
|
|
40795
|
-
|
|
40796
|
-
|
|
40797
|
-
|
|
40798
|
-
|
|
40826
|
+
if (folder) config.backup = backupFrom(folder, before?.backup);
|
|
40827
|
+
else if (flags.has("keep") || flags.has("hour"))
|
|
40828
|
+
config.backup = backupFrom(
|
|
40829
|
+
before?.backup?.folder ?? fail("--keep and --hour go with --backup FOLDER."),
|
|
40830
|
+
before?.backup
|
|
40831
|
+
);
|
|
40799
40832
|
const reach = reachableAt(config);
|
|
40800
|
-
|
|
40833
|
+
const moving = !(await manager.state()).running || before?.port !== port || before.address !== address;
|
|
40834
|
+
if (moving && await answers(reach))
|
|
40801
40835
|
fail(
|
|
40802
40836
|
`Another Opsidian host is already using port ${port} here, perhaps the Opsidian app.
|
|
40803
40837
|
Turn hosting off there, or start this one with --port ${port + 1}.`
|
|
@@ -40900,11 +40934,7 @@ async function backup() {
|
|
|
40900
40934
|
}
|
|
40901
40935
|
let target = config?.backup;
|
|
40902
40936
|
if (what !== "now") {
|
|
40903
|
-
target =
|
|
40904
|
-
folder: resolve(what),
|
|
40905
|
-
keep: Number(flags.get("keep") ?? target?.keep ?? 14),
|
|
40906
|
-
hour: Number(flags.get("hour") ?? target?.hour ?? 3)
|
|
40907
|
-
};
|
|
40937
|
+
target = backupFrom(what, target);
|
|
40908
40938
|
if (config) {
|
|
40909
40939
|
await writeConfig(where, { ...config, backup: target });
|
|
40910
40940
|
console.log(`Backing up: ${backupLine({ ...config, backup: target })}.`);
|
|
@@ -40918,25 +40948,32 @@ async function restore() {
|
|
|
40918
40948
|
const config = await readConfig(where);
|
|
40919
40949
|
const name = words.at(-1);
|
|
40920
40950
|
const folder = words.length > 1 ? resolve(words[0]) : config?.backup?.folder;
|
|
40921
|
-
if (!name || !folder)
|
|
40922
|
-
|
|
40923
|
-
const
|
|
40924
|
-
|
|
40951
|
+
if (!name || !folder)
|
|
40952
|
+
return fail(`Say which: ${me} host restore BACKUP, or restore FOLDER BACKUP`);
|
|
40953
|
+
const data = flags.get("data") ?? where.data;
|
|
40954
|
+
const found = service(where);
|
|
40955
|
+
const manager = "missing" in found ? void 0 : found;
|
|
40956
|
+
const managed = (await manager?.state())?.running === true;
|
|
40957
|
+
const port = config?.port ?? DEFAULT_PORT;
|
|
40958
|
+
const live = [`127.0.0.1:${port}`, ...config ? [reachableAt(config)] : []];
|
|
40959
|
+
if (!managed && (await Promise.all(live.map(answers))).some(Boolean))
|
|
40960
|
+
fail("The host is running. Stop it first (Ctrl+C, or docker stop), then restore.");
|
|
40961
|
+
if (managed) await manager.remove();
|
|
40925
40962
|
try {
|
|
40926
|
-
if (existsSync3(
|
|
40927
|
-
const keep = (
|
|
40963
|
+
if (existsSync3(join4(data, "host.sqlite"))) {
|
|
40964
|
+
const keep = (await listBackups(folder)).length + 1;
|
|
40928
40965
|
const safety = await withHost((host) => host.backup(folder, keep));
|
|
40929
40966
|
console.log(`Backed up what the host held first, as ${safety.name}.`);
|
|
40930
40967
|
}
|
|
40931
|
-
await restoreBackup(
|
|
40968
|
+
await restoreBackup(data, folder, name);
|
|
40932
40969
|
console.log("Restored. Devices catch up by themselves.");
|
|
40933
40970
|
} finally {
|
|
40934
|
-
if (
|
|
40971
|
+
if (managed) await manager.install();
|
|
40935
40972
|
}
|
|
40936
40973
|
}
|
|
40937
40974
|
async function runHere() {
|
|
40938
40975
|
const config = await readConfig(where);
|
|
40939
|
-
const port =
|
|
40976
|
+
const port = whole("port", config?.port ?? DEFAULT_PORT, 1, 65535);
|
|
40940
40977
|
const address = flags.get("address") ?? config?.address ?? "0.0.0.0";
|
|
40941
40978
|
const data = flags.get("data") ?? where.data;
|
|
40942
40979
|
const host = new Host({ dataDir: data });
|