@hydra-acp/archiver 0.1.12 → 0.1.14
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/README.md +32 -35
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/setup/conf-writer.js +86 -0
- package/dist/setup/conf-writer.js.map +1 -0
- package/dist/setup/downloads-scan.js +44 -0
- package/dist/setup/downloads-scan.js.map +1 -0
- package/dist/setup/prompts.js +123 -0
- package/dist/setup/prompts.js.map +1 -0
- package/dist/setup/wizard.js +415 -0
- package/dist/setup/wizard.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,8 +23,6 @@ From npm (recommended once published):
|
|
|
23
23
|
npm install -g @hydra-acp/archiver
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Drops a `hydra-acp-archiver` binary on your PATH.
|
|
27
|
-
|
|
28
26
|
Or from source:
|
|
29
27
|
|
|
30
28
|
```sh
|
|
@@ -34,37 +32,18 @@ npm install
|
|
|
34
32
|
npm run build
|
|
35
33
|
```
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
```sh
|
|
40
|
-
hydra-acp extensions add hydra-acp-archiver
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Or pointed at a local build:
|
|
35
|
+
## Setup
|
|
44
36
|
|
|
45
37
|
```sh
|
|
46
|
-
hydra-acp
|
|
47
|
-
--command node \
|
|
48
|
-
--args ~/dev/hydra-acp-archiver/dist/index.js
|
|
38
|
+
hydra-acp-archiver setup
|
|
49
39
|
```
|
|
50
40
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
```json
|
|
54
|
-
{
|
|
55
|
-
"extensions": {
|
|
56
|
-
"hydra-acp-archiver": {
|
|
57
|
-
"command": ["node"],
|
|
58
|
-
"args": ["/home/you/dev/hydra-acp-archiver/dist/index.js"],
|
|
59
|
-
"enabled": true
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
```
|
|
41
|
+
The wizard walks you through picking a backend (Google Drive / S3 / Filesystem), configuring credentials, optionally generating an AES-256-GCM key for encryption, writing `~/.hydra-acp/archiver.conf`, and registering the archiver as a hydra extension. About 1 minute for S3/Filesystem; about 5–8 minutes for Google Drive (the GCP Console click-through is the long pole).
|
|
64
42
|
|
|
65
|
-
|
|
43
|
+
Re-run `hydra-acp-archiver setup` any time to switch backends or rotate keys — it preserves existing custom config keys.
|
|
66
44
|
|
|
67
|
-
|
|
45
|
+
<details>
|
|
46
|
+
<summary>Manual Google Drive setup (if you prefer not to run the wizard)</summary>
|
|
68
47
|
|
|
69
48
|
The Google Drive backend uses OAuth 2.0 with the **`drive.file`** scope — the archiver can only see files it creates plus those you explicitly hand it via a picker. Your other Drive contents stay invisible to it.
|
|
70
49
|
|
|
@@ -75,21 +54,39 @@ You provide your own OAuth client (Google's terms make it impractical to ship a
|
|
|
75
54
|
3. Configure the **OAuth consent screen**. User type: **External**. Add your Google account under **Test Users**.
|
|
76
55
|
4. **Credentials → Create credentials → OAuth client ID**. Application type: **Desktop app**.
|
|
77
56
|
5. Download the resulting JSON and save it to `~/.hydra-acp/archiver-google-credentials.json` (or anywhere, and set `HYDRA_ACP_ARCHIVER_GOOGLE_CREDENTIALS`).
|
|
78
|
-
6. Run
|
|
57
|
+
6. Run `hydra-acp-archiver gdrive login`. Your browser opens to Google's consent screen. The "Google hasn't verified this app" interstitial is expected for an unverified personal-use client — click **Advanced → Go to (unsafe)** and approve. The redirect lands on a transient local server, the archiver writes `~/.hydra-acp/archiver-google-token.json` (mode 0600), and you're done.
|
|
58
|
+
7. Register: `hydra-acp extensions add hydra-acp-archiver`.
|
|
79
59
|
|
|
80
|
-
|
|
81
|
-
hydra-acp-archiver gdrive login
|
|
82
|
-
```
|
|
60
|
+
After this, restart the daemon. The archiver process starts up, creates a `hydra-acp-archive/` folder in your Drive on first upload, and begins syncing.
|
|
83
61
|
|
|
84
|
-
|
|
62
|
+
</details>
|
|
85
63
|
|
|
86
|
-
|
|
64
|
+
<details>
|
|
65
|
+
<summary>Manual extension registration</summary>
|
|
66
|
+
|
|
67
|
+
If you skip the wizard's registration step, run:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
hydra-acp extensions add hydra-acp-archiver
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Or pointed at a local build:
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
hydra-acp extensions add hydra-acp-archiver \
|
|
77
|
+
--command node \
|
|
78
|
+
--args ~/dev/hydra-acp-archiver/dist/index.js
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
That writes the equivalent entry into `~/.hydra-acp/config.json`. On `hydra-acp daemon start`, hydra spawns hydra-acp-archiver as a managed subprocess. Stdout/stderr land in `~/.hydra-acp/extensions/hydra-acp-archiver.log`.
|
|
82
|
+
|
|
83
|
+
</details>
|
|
87
84
|
|
|
88
85
|
## Multi-machine setup
|
|
89
86
|
|
|
90
|
-
|
|
87
|
+
Run `hydra-acp-archiver setup` on each machine that should sync. For Google Drive, log in with the **same Google account** and use the **same Drive folder name** so each machine points at the shared archive. For S3, point each machine at the same bucket. For filesystem, point each at a directory that some external sync tool (Syncthing, Dropbox, iCloud) mirrors.
|
|
91
88
|
|
|
92
|
-
If you
|
|
89
|
+
If you turned on encryption, copy `~/.hydra-acp/archiver-key` from your first machine to each peer; the wizard's fingerprint output lets you verify they match.
|
|
93
90
|
|
|
94
91
|
## S3 backend
|
|
95
92
|
|
package/dist/index.js
CHANGED
|
@@ -23,6 +23,9 @@ const log = logger("main");
|
|
|
23
23
|
const USAGE = `usage: hydra-acp-archiver [<command>]
|
|
24
24
|
|
|
25
25
|
Commands:
|
|
26
|
+
setup Interactive first-run wizard — picks a backend, sets up
|
|
27
|
+
OAuth/credentials/encryption, writes archiver.conf, and
|
|
28
|
+
(optionally) registers the extension with hydra.
|
|
26
29
|
(no args) Run as a daemon-managed extension (the daemon spawns it
|
|
27
30
|
this way automatically when registered).
|
|
28
31
|
gdrive login Interactive Google OAuth flow — opens a browser and writes
|
|
@@ -226,6 +229,11 @@ async function main() {
|
|
|
226
229
|
await runKeygen();
|
|
227
230
|
return;
|
|
228
231
|
}
|
|
232
|
+
if (cmd === "setup") {
|
|
233
|
+
const { runSetup } = await import("./setup/wizard.js");
|
|
234
|
+
await runSetup();
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
229
237
|
if (cmd === "-h" || cmd === "--help" || cmd === "help") {
|
|
230
238
|
process.stdout.write(USAGE);
|
|
231
239
|
return;
|
|
@@ -234,7 +242,13 @@ async function main() {
|
|
|
234
242
|
process.exit(2);
|
|
235
243
|
}
|
|
236
244
|
main().catch((err) => {
|
|
237
|
-
|
|
245
|
+
const msg = err.message;
|
|
246
|
+
process.stderr.write(`hydra-acp-archiver: ${msg}\n`);
|
|
247
|
+
if (/invalid_grant/i.test(msg)) {
|
|
248
|
+
process.stderr.write("Google refresh token is invalid. Run `hydra-acp-archiver gdrive login` to re-authorize.\n");
|
|
249
|
+
// sysexits EX_CONFIG — tells the daemon supervisor not to restart us.
|
|
250
|
+
process.exit(78);
|
|
251
|
+
}
|
|
238
252
|
process.exit(1);
|
|
239
253
|
});
|
|
240
254
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAqB,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AAE3B,MAAM,KAAK,GAAG
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
export const PRIMARY_CONF_PATH = resolve(homedir(), ".hydra-acp", "archiver.conf");
|
|
5
|
+
function parseLines(text) {
|
|
6
|
+
return text.split(/\r?\n/).map((raw) => {
|
|
7
|
+
const trimmed = raw.trim();
|
|
8
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
9
|
+
return { raw };
|
|
10
|
+
const eq = raw.indexOf("=");
|
|
11
|
+
if (eq === -1)
|
|
12
|
+
return { raw };
|
|
13
|
+
const key = raw.slice(0, eq).trim();
|
|
14
|
+
let value = raw.slice(eq + 1).trim();
|
|
15
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
16
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
17
|
+
value = value.slice(1, -1);
|
|
18
|
+
}
|
|
19
|
+
return { raw, key, value };
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function readExisting(path) {
|
|
23
|
+
if (!existsSync(path))
|
|
24
|
+
return { text: "", map: new Map() };
|
|
25
|
+
const text = readFileSync(path, "utf8");
|
|
26
|
+
const map = new Map();
|
|
27
|
+
for (const line of parseLines(text)) {
|
|
28
|
+
if (line.key !== undefined && line.value !== undefined)
|
|
29
|
+
map.set(line.key, line.value);
|
|
30
|
+
}
|
|
31
|
+
return { text, map };
|
|
32
|
+
}
|
|
33
|
+
const HEADER = `# hydra-acp-archiver config — written by 'hydra-acp-archiver setup'.
|
|
34
|
+
# Lock this file: chmod 600.
|
|
35
|
+
`;
|
|
36
|
+
function quoteIfNeeded(value) {
|
|
37
|
+
if (/[\s#'"]/.test(value))
|
|
38
|
+
return `"${value.replace(/"/g, '\\"')}"`;
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
export function mergeConf(existing, updates) {
|
|
42
|
+
const lines = parseLines(existing);
|
|
43
|
+
const remaining = new Map();
|
|
44
|
+
for (const [k, v] of Object.entries(updates)) {
|
|
45
|
+
if (v !== undefined)
|
|
46
|
+
remaining.set(k, v);
|
|
47
|
+
}
|
|
48
|
+
const out = [];
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
if (line.key && remaining.has(line.key)) {
|
|
51
|
+
const newVal = remaining.get(line.key);
|
|
52
|
+
out.push(`${line.key}=${quoteIfNeeded(newVal)}`);
|
|
53
|
+
remaining.delete(line.key);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
out.push(line.raw);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!existing) {
|
|
60
|
+
out.length = 0;
|
|
61
|
+
out.push(HEADER.trimEnd());
|
|
62
|
+
out.push("");
|
|
63
|
+
}
|
|
64
|
+
while (out.length > 0 && out[out.length - 1] === "")
|
|
65
|
+
out.pop();
|
|
66
|
+
if (remaining.size > 0) {
|
|
67
|
+
if (out.length > 0)
|
|
68
|
+
out.push("");
|
|
69
|
+
for (const [k, v] of remaining)
|
|
70
|
+
out.push(`${k}=${quoteIfNeeded(v)}`);
|
|
71
|
+
}
|
|
72
|
+
return out.join("\n") + "\n";
|
|
73
|
+
}
|
|
74
|
+
export function writeConf(path, updates) {
|
|
75
|
+
const { text } = readExisting(path);
|
|
76
|
+
const merged = mergeConf(text, updates);
|
|
77
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
78
|
+
writeFileSync(path, merged, { encoding: "utf8" });
|
|
79
|
+
try {
|
|
80
|
+
chmodSync(path, 0o600);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// chmod isn't meaningful on Windows; ignore.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=conf-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conf-writer.js","sourceRoot":"","sources":["../../src/setup/conf-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;AAYnF,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YACrC,OAAO,EAAE,GAAG,EAAE,CAAC;QACjB,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,EAAE,KAAK,CAAC,CAAC;YACX,OAAO,EAAE,GAAG,EAAE,CAAC;QACjB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,IACE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC9C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAC9C,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QACnB,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YACpD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,MAAM,GAAG;;CAEd,CAAC;AAEF,SAAS,aAAa,CAAC,KAAa;IAClC,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;QACvB,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;IAC3C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,OAAmB;IAC7D,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC,KAAK,SAAS;YACjB,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAE,CAAC;YACxC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACjD,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;QACf,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,CAAC;IAED,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE;QACjD,GAAG,CAAC,GAAG,EAAE,CAAC;IAEZ,IAAI,SAAS,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;YAChB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS;YAC5B,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,OAAmB;IACzD,MAAM,EAAE,IAAI,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,6CAA6C;IAC/C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
export function scanDownloadsForGoogleCredentials(maxAgeMs = 60 * 60 * 1000) {
|
|
5
|
+
const dir = resolve(homedir(), "Downloads");
|
|
6
|
+
let entries;
|
|
7
|
+
try {
|
|
8
|
+
entries = readdirSync(dir);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
const now = Date.now();
|
|
14
|
+
let best;
|
|
15
|
+
for (const name of entries) {
|
|
16
|
+
if (!name.startsWith("client_secret_") || !name.endsWith(".json"))
|
|
17
|
+
continue;
|
|
18
|
+
const full = resolve(dir, name);
|
|
19
|
+
let mtimeMs;
|
|
20
|
+
try {
|
|
21
|
+
mtimeMs = statSync(full).mtimeMs;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const age = now - mtimeMs;
|
|
27
|
+
if (age < 0 || age > maxAgeMs)
|
|
28
|
+
continue;
|
|
29
|
+
if (!best || age < best.ageMs)
|
|
30
|
+
best = { path: full, ageMs: age };
|
|
31
|
+
}
|
|
32
|
+
return best;
|
|
33
|
+
}
|
|
34
|
+
export function formatAge(ms) {
|
|
35
|
+
const sec = Math.floor(ms / 1000);
|
|
36
|
+
if (sec < 60)
|
|
37
|
+
return `${sec}s ago`;
|
|
38
|
+
const min = Math.floor(sec / 60);
|
|
39
|
+
if (min < 60)
|
|
40
|
+
return `${min} min ago`;
|
|
41
|
+
const hr = Math.floor(min / 60);
|
|
42
|
+
return `${hr}h ago`;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=downloads-scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"downloads-scan.js","sourceRoot":"","sources":["../../src/setup/downloads-scan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,MAAM,UAAU,iCAAiC,CAAC,QAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;IACzE,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;IAC5C,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,IAA6B,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC/D,SAAS;QACX,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAChC,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,GAAG,GAAG,OAAO,CAAC;QAC1B,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,QAAQ;YAC3B,SAAS;QACX,IAAI,CAAC,IAAI,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK;YAC3B,IAAI,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAU;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAClC,IAAI,GAAG,GAAG,EAAE;QACV,OAAO,GAAG,GAAG,OAAO,CAAC;IACvB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC;IACjC,IAAI,GAAG,GAAG,EAAE;QACV,OAAO,GAAG,GAAG,UAAU,CAAC;IAC1B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC;IAChC,OAAO,GAAG,EAAE,OAAO,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
import { platform } from "node:os";
|
|
4
|
+
function isTTY() {
|
|
5
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
6
|
+
}
|
|
7
|
+
export async function ask(label, fallback = "") {
|
|
8
|
+
const suffix = fallback ? ` [${fallback}]` : "";
|
|
9
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
10
|
+
try {
|
|
11
|
+
const answer = await new Promise((resolve) => {
|
|
12
|
+
rl.question(` ${label}${suffix}: `, resolve);
|
|
13
|
+
});
|
|
14
|
+
return answer.trim() || fallback;
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
rl.close();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export async function confirm(label, defaultYes = false) {
|
|
21
|
+
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
22
|
+
for (;;) {
|
|
23
|
+
const reply = (await ask(`${label} ${hint}`)).toLowerCase();
|
|
24
|
+
if (!reply)
|
|
25
|
+
return defaultYes;
|
|
26
|
+
if (reply.startsWith("y"))
|
|
27
|
+
return true;
|
|
28
|
+
if (reply.startsWith("n"))
|
|
29
|
+
return false;
|
|
30
|
+
process.stdout.write(" Please answer y or n.\n");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export async function pickFromList(label, items, render) {
|
|
34
|
+
if (items.length === 0)
|
|
35
|
+
return undefined;
|
|
36
|
+
process.stdout.write(`\n ${label}\n\n`);
|
|
37
|
+
items.forEach((item, idx) => {
|
|
38
|
+
process.stdout.write(` ${idx + 1}. ${render(item)}\n`);
|
|
39
|
+
});
|
|
40
|
+
process.stdout.write(" s. Skip\n\n");
|
|
41
|
+
for (;;) {
|
|
42
|
+
const reply = (await ask("Choice")).toLowerCase();
|
|
43
|
+
if (reply === "s" || reply === "")
|
|
44
|
+
return undefined;
|
|
45
|
+
const n = Number.parseInt(reply, 10);
|
|
46
|
+
if (Number.isInteger(n) && n >= 1 && n <= items.length)
|
|
47
|
+
return items[n - 1];
|
|
48
|
+
process.stdout.write(" Enter a number from the list, or 's' to skip.\n");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export async function askSecret(label) {
|
|
52
|
+
process.stdout.write(` ${label}: `);
|
|
53
|
+
if (!isTTY()) {
|
|
54
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout, terminal: false });
|
|
55
|
+
try {
|
|
56
|
+
const line = await new Promise((resolve) => {
|
|
57
|
+
rl.question("", resolve);
|
|
58
|
+
});
|
|
59
|
+
return line.trim();
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
rl.close();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const stdin = process.stdin;
|
|
66
|
+
const wasRaw = stdin.isRaw;
|
|
67
|
+
stdin.setRawMode(true);
|
|
68
|
+
stdin.resume();
|
|
69
|
+
stdin.setEncoding("utf8");
|
|
70
|
+
let buf = "";
|
|
71
|
+
try {
|
|
72
|
+
for await (const chunk of stdin) {
|
|
73
|
+
let done = false;
|
|
74
|
+
for (const ch of chunk) {
|
|
75
|
+
const code = ch.charCodeAt(0);
|
|
76
|
+
if (ch === "\r" || ch === "\n") {
|
|
77
|
+
done = true;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
if (code === 3) {
|
|
81
|
+
process.stdout.write("\n");
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
if (code === 127 || code === 8) {
|
|
85
|
+
buf = buf.slice(0, -1);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
buf += ch;
|
|
89
|
+
}
|
|
90
|
+
if (done)
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
stdin.setRawMode(wasRaw);
|
|
96
|
+
stdin.pause();
|
|
97
|
+
process.stdout.write("\n");
|
|
98
|
+
}
|
|
99
|
+
return buf.trim();
|
|
100
|
+
}
|
|
101
|
+
export function maskToken(t) {
|
|
102
|
+
if (t.length > 16)
|
|
103
|
+
return `${t.slice(0, 8)}...${t.slice(-4)}`;
|
|
104
|
+
return `${t.slice(0, 4)}...`;
|
|
105
|
+
}
|
|
106
|
+
export function openBrowser(url) {
|
|
107
|
+
const p = platform();
|
|
108
|
+
const cmd = p === "darwin" ? "open" : p === "win32" ? "start" : "xdg-open";
|
|
109
|
+
try {
|
|
110
|
+
const child = spawn(cmd, [url], { stdio: "ignore", detached: true });
|
|
111
|
+
child.on("error", () => {
|
|
112
|
+
process.stdout.write(` Open this URL: ${url}\n`);
|
|
113
|
+
});
|
|
114
|
+
child.unref();
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
process.stdout.write(` Open this URL: ${url}\n`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export async function pause(label = "Press Enter to continue...") {
|
|
121
|
+
await ask(label);
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/setup/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { delimiter, join, resolve } from "node:path";
|
|
6
|
+
import { loadLoginConfig } from "../config.js";
|
|
7
|
+
import { runKeygen } from "../keygen.js";
|
|
8
|
+
import { runGoogleLogin } from "../oauth/google.js";
|
|
9
|
+
import { loadAwsCredentials } from "../util/aws-credentials.js";
|
|
10
|
+
import { PRIMARY_CONF_PATH, readExisting, writeConf } from "./conf-writer.js";
|
|
11
|
+
import { formatAge, scanDownloadsForGoogleCredentials } from "./downloads-scan.js";
|
|
12
|
+
import { ask, confirm, openBrowser, pause, pickFromList } from "./prompts.js";
|
|
13
|
+
const TOTAL_STEPS = 6;
|
|
14
|
+
const BOLD = "\x1b[1m";
|
|
15
|
+
const GREEN = "\x1b[32m";
|
|
16
|
+
const YELLOW = "\x1b[33m";
|
|
17
|
+
const RED = "\x1b[31m";
|
|
18
|
+
const DIM = "\x1b[2m";
|
|
19
|
+
const RESET = "\x1b[0m";
|
|
20
|
+
function header(num, total, title) {
|
|
21
|
+
process.stdout.write(`\n ${BOLD}[${num}/${total}] ${title}${RESET}\n\n`);
|
|
22
|
+
}
|
|
23
|
+
function ok(msg) {
|
|
24
|
+
process.stdout.write(` ${GREEN}✓${RESET} ${msg}\n`);
|
|
25
|
+
}
|
|
26
|
+
function warn(msg) {
|
|
27
|
+
process.stdout.write(` ${YELLOW}⚠${RESET} ${msg}\n`);
|
|
28
|
+
}
|
|
29
|
+
function fail(msg) {
|
|
30
|
+
process.stderr.write(` ${RED}✗ ${msg}${RESET}\n`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
function info(msg) {
|
|
34
|
+
process.stdout.write(` ${msg}\n`);
|
|
35
|
+
}
|
|
36
|
+
function blank() {
|
|
37
|
+
process.stdout.write("\n");
|
|
38
|
+
}
|
|
39
|
+
function hasBin(name) {
|
|
40
|
+
const dirs = (process.env.PATH ?? "").split(delimiter);
|
|
41
|
+
const exts = process.platform === "win32" ? [".exe", ".cmd", ".bat", ""] : [""];
|
|
42
|
+
for (const dir of dirs) {
|
|
43
|
+
if (!dir)
|
|
44
|
+
continue;
|
|
45
|
+
for (const ext of exts) {
|
|
46
|
+
const full = join(dir, name + ext);
|
|
47
|
+
try {
|
|
48
|
+
if (statSync(full).isFile())
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// ignore
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const HYDRA_HOME = resolve(homedir(), ".hydra-acp");
|
|
59
|
+
const HYDRA_CONFIG_PATH = resolve(HYDRA_HOME, "config.json");
|
|
60
|
+
const DEFAULT_KEY_PATH = resolve(HYDRA_HOME, "archiver-key");
|
|
61
|
+
const DEFAULT_FS_DIR = resolve(HYDRA_HOME, "archive");
|
|
62
|
+
const DEFAULT_DRIVE_FOLDER = "hydra-acp-archive";
|
|
63
|
+
function readHydraConfigExtensions() {
|
|
64
|
+
try {
|
|
65
|
+
const cfg = JSON.parse(readFileSync(HYDRA_CONFIG_PATH, "utf8"));
|
|
66
|
+
return new Set(Object.keys(cfg.extensions ?? {}));
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return new Set();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function keyFingerprint(keyPath) {
|
|
73
|
+
try {
|
|
74
|
+
const hex = readFileSync(keyPath, "utf8").trim();
|
|
75
|
+
if (!/^[0-9a-f]+$/i.test(hex))
|
|
76
|
+
return undefined;
|
|
77
|
+
const bytes = Buffer.from(hex, "hex");
|
|
78
|
+
if (bytes.length !== 32)
|
|
79
|
+
return undefined;
|
|
80
|
+
return createHash("sha256").update(bytes).digest().subarray(0, 8).toString("hex");
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function step1ExistingCheck() {
|
|
87
|
+
header(1, TOTAL_STEPS, "Checking existing setup");
|
|
88
|
+
info("This wizard configures a backend (Google Drive / S3 / Filesystem),");
|
|
89
|
+
info("optional encryption, and registers the archiver with hydra.");
|
|
90
|
+
blank();
|
|
91
|
+
const { map } = readExisting(PRIMARY_CONF_PATH);
|
|
92
|
+
if (map.size === 0) {
|
|
93
|
+
ok("No existing archiver config found.");
|
|
94
|
+
return { reconfigure: true };
|
|
95
|
+
}
|
|
96
|
+
const backend = map.get("BACKEND") ?? "google-drive";
|
|
97
|
+
info(`Existing config at ${PRIMARY_CONF_PATH}`);
|
|
98
|
+
info(` Backend: ${backend}`);
|
|
99
|
+
if (backend === "google-drive")
|
|
100
|
+
info(` Drive folder: ${map.get("DRIVE_FOLDER") ?? DEFAULT_DRIVE_FOLDER}`);
|
|
101
|
+
else if (backend === "s3")
|
|
102
|
+
info(` S3 bucket: ${map.get("S3_BUCKET") ?? "(missing)"}`);
|
|
103
|
+
else if (backend === "fs")
|
|
104
|
+
info(` FS dir: ${map.get("FS_DIR") ?? DEFAULT_FS_DIR}`);
|
|
105
|
+
const keyPath = map.get("KEY_PATH") ?? (existsSync(DEFAULT_KEY_PATH) ? DEFAULT_KEY_PATH : undefined);
|
|
106
|
+
if (map.get("KEY_PATH")) {
|
|
107
|
+
const fp = keyFingerprint(map.get("KEY_PATH"));
|
|
108
|
+
info(` Encryption: on${fp ? ` (fingerprint ${fp})` : ""}`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
info(` Encryption: off`);
|
|
112
|
+
}
|
|
113
|
+
const registered = readHydraConfigExtensions().has("hydra-acp-archiver");
|
|
114
|
+
info(` Registered with hydra: ${registered ? "yes" : "no"}`);
|
|
115
|
+
blank();
|
|
116
|
+
if (!(await confirm("Reconfigure from scratch?", false))) {
|
|
117
|
+
info("Edit ~/.hydra-acp/archiver.conf directly to tune individual settings.");
|
|
118
|
+
return { reconfigure: false };
|
|
119
|
+
}
|
|
120
|
+
return { reconfigure: true };
|
|
121
|
+
}
|
|
122
|
+
async function step2PickBackend() {
|
|
123
|
+
header(2, TOTAL_STEPS, "Pick a backend");
|
|
124
|
+
const choices = [
|
|
125
|
+
{
|
|
126
|
+
backend: "google-drive",
|
|
127
|
+
label: "Google Drive\n Easiest cross-machine sync. Free up to 15 GB. One-time GCP\n setup (~5 min in the Cloud Console).",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
backend: "s3",
|
|
131
|
+
label: "S3 / S3-compatible (R2, B2, MinIO, Wasabi)\n Best for larger archives. Needs AWS-style creds and an\n existing bucket.",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
backend: "fs",
|
|
135
|
+
label: "Filesystem\n Useful with Syncthing/Dropbox mirroring a folder, or for\n local-only testing.",
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
const picked = await pickFromList("Choose:", choices, (c) => c.label);
|
|
139
|
+
if (!picked)
|
|
140
|
+
fail("A backend is required.");
|
|
141
|
+
ok(`Backend: ${picked.backend}`);
|
|
142
|
+
return { backend: picked.backend };
|
|
143
|
+
}
|
|
144
|
+
async function step3aGoogleDrive() {
|
|
145
|
+
header(3, TOTAL_STEPS, "Configure Google Drive");
|
|
146
|
+
const login = loadLoginConfig();
|
|
147
|
+
const credentialsPath = login.credentialsPath;
|
|
148
|
+
if (existsSync(credentialsPath)) {
|
|
149
|
+
ok(`Google OAuth credentials found at ${credentialsPath}.`);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
info("First-time setup. You need an OAuth client from Google Cloud Console.");
|
|
153
|
+
blank();
|
|
154
|
+
info(" 1. Pick or create a project");
|
|
155
|
+
info(" 2. APIs & Services → Library → enable Google Drive API");
|
|
156
|
+
info(" 3. OAuth consent screen → User type: External → add yourself as a Test User");
|
|
157
|
+
info(" 4. Credentials → Create credentials → OAuth client ID → Application: Desktop app");
|
|
158
|
+
info(" 5. Download the JSON (lands in ~/Downloads)");
|
|
159
|
+
blank();
|
|
160
|
+
await pause("Press Enter to open the Cloud Console...");
|
|
161
|
+
openBrowser("https://console.cloud.google.com/");
|
|
162
|
+
blank();
|
|
163
|
+
await pause("Press Enter once you've downloaded the JSON...");
|
|
164
|
+
const hit = scanDownloadsForGoogleCredentials();
|
|
165
|
+
let srcPath;
|
|
166
|
+
if (hit) {
|
|
167
|
+
blank();
|
|
168
|
+
info(`Found ${hit.path} (${formatAge(hit.ageMs)}).`);
|
|
169
|
+
if (await confirm("Use this file?", true))
|
|
170
|
+
srcPath = hit.path;
|
|
171
|
+
}
|
|
172
|
+
if (!srcPath) {
|
|
173
|
+
blank();
|
|
174
|
+
const manual = await ask("Path to the downloaded JSON");
|
|
175
|
+
if (!manual)
|
|
176
|
+
fail("A credentials file is required.");
|
|
177
|
+
srcPath = manual.startsWith("~/") ? manual.replace(/^~/, homedir()) : manual;
|
|
178
|
+
}
|
|
179
|
+
if (!existsSync(srcPath))
|
|
180
|
+
fail(`File not found: ${srcPath}`);
|
|
181
|
+
mkdirSync(HYDRA_HOME, { recursive: true });
|
|
182
|
+
copyFileSync(srcPath, credentialsPath);
|
|
183
|
+
try {
|
|
184
|
+
const { chmodSync } = await import("node:fs");
|
|
185
|
+
chmodSync(credentialsPath, 0o600);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// chmod not meaningful on win32
|
|
189
|
+
}
|
|
190
|
+
ok(`Saved to ${credentialsPath} (chmod 600).`);
|
|
191
|
+
}
|
|
192
|
+
blank();
|
|
193
|
+
const driveFolder = await ask("Drive folder name", DEFAULT_DRIVE_FOLDER);
|
|
194
|
+
blank();
|
|
195
|
+
info("Now we run Google's OAuth flow. Your browser will open to a consent");
|
|
196
|
+
info("screen. The 'Google hasn't verified this app' interstitial is expected");
|
|
197
|
+
info("for a personal OAuth client — click 'Advanced' → 'Go to (unsafe)' → 'Allow'.");
|
|
198
|
+
blank();
|
|
199
|
+
await pause("Press Enter to start OAuth...");
|
|
200
|
+
try {
|
|
201
|
+
await runGoogleLogin({ credentialsPath, tokenPath: login.tokenPath });
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
fail(`Google OAuth failed: ${err.message}`);
|
|
205
|
+
}
|
|
206
|
+
ok(`OAuth complete. Token saved to ${login.tokenPath}.`);
|
|
207
|
+
return { driveFolder, credentialsPath };
|
|
208
|
+
}
|
|
209
|
+
async function step3bS3() {
|
|
210
|
+
header(3, TOTAL_STEPS, "Configure S3");
|
|
211
|
+
blank();
|
|
212
|
+
info("S3 endpoint hints:");
|
|
213
|
+
info(` ${DIM}AWS S3${RESET} leave Endpoint blank, set Region`);
|
|
214
|
+
info(` ${DIM}Cloudflare R2${RESET} https://<accountid>.r2.cloudflarestorage.com`);
|
|
215
|
+
info(` ${DIM}Backblaze B2${RESET} https://s3.<region>.backblazeb2.com`);
|
|
216
|
+
info(` ${DIM}MinIO${RESET} your MinIO endpoint URL`);
|
|
217
|
+
blank();
|
|
218
|
+
const bucket = await ask("S3 bucket name");
|
|
219
|
+
if (!bucket)
|
|
220
|
+
fail("A bucket name is required for S3.");
|
|
221
|
+
const region = (await ask("Region (blank for SDK default)")) || undefined;
|
|
222
|
+
const endpoint = (await ask("Endpoint URL (blank for AWS S3)")) || undefined;
|
|
223
|
+
blank();
|
|
224
|
+
try {
|
|
225
|
+
const creds = loadAwsCredentials();
|
|
226
|
+
const masked = `${creds.accessKeyId.slice(0, 4)}…${creds.accessKeyId.slice(-4)}`;
|
|
227
|
+
const source = process.env.AWS_ACCESS_KEY_ID ? "env vars" : `~/.aws/credentials (profile: ${process.env.AWS_PROFILE ?? "default"})`;
|
|
228
|
+
ok(`AWS creds found via ${source} — access key ${masked}.`);
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
warn(`${err.message}`);
|
|
232
|
+
info("The archiver will fail to start until creds are in place.");
|
|
233
|
+
}
|
|
234
|
+
return { bucket, region, endpoint };
|
|
235
|
+
}
|
|
236
|
+
async function step3cFilesystem() {
|
|
237
|
+
header(3, TOTAL_STEPS, "Configure Filesystem");
|
|
238
|
+
const suggestions = [];
|
|
239
|
+
for (const candidate of ["Syncthing", "Dropbox", "iCloud Drive", "OneDrive"]) {
|
|
240
|
+
const full = resolve(homedir(), candidate);
|
|
241
|
+
if (existsSync(full))
|
|
242
|
+
suggestions.push(full);
|
|
243
|
+
}
|
|
244
|
+
let dir;
|
|
245
|
+
if (suggestions.length > 0) {
|
|
246
|
+
info("Found sync folders that could host the archive:");
|
|
247
|
+
blank();
|
|
248
|
+
suggestions.forEach((s, i) => info(` ${i + 1}. ${s}/hydra-acp-archive`));
|
|
249
|
+
info(` c. Custom path`);
|
|
250
|
+
info(` d. Default (${DEFAULT_FS_DIR})`);
|
|
251
|
+
blank();
|
|
252
|
+
const reply = (await ask("Choice", "d")).toLowerCase();
|
|
253
|
+
if (reply === "d" || reply === "") {
|
|
254
|
+
dir = DEFAULT_FS_DIR;
|
|
255
|
+
}
|
|
256
|
+
else if (reply === "c") {
|
|
257
|
+
const custom = await ask("Archive directory", DEFAULT_FS_DIR);
|
|
258
|
+
dir = custom.startsWith("~/") ? custom.replace(/^~/, homedir()) : custom;
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
const n = Number.parseInt(reply, 10);
|
|
262
|
+
if (Number.isInteger(n) && n >= 1 && n <= suggestions.length)
|
|
263
|
+
dir = resolve(suggestions[n - 1], "hydra-acp-archive");
|
|
264
|
+
}
|
|
265
|
+
if (!dir)
|
|
266
|
+
fail("Invalid choice.");
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
const raw = await ask("Archive directory", DEFAULT_FS_DIR);
|
|
270
|
+
dir = raw.startsWith("~/") ? raw.replace(/^~/, homedir()) : raw;
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
mkdirSync(dir, { recursive: true });
|
|
274
|
+
const probe = resolve(dir, ".hydra-acp-archiver-test");
|
|
275
|
+
writeFileSync(probe, "ok");
|
|
276
|
+
rmSync(probe);
|
|
277
|
+
ok(`Directory writable: ${dir}`);
|
|
278
|
+
}
|
|
279
|
+
catch (err) {
|
|
280
|
+
fail(`Cannot write to ${dir}: ${err.message}`);
|
|
281
|
+
}
|
|
282
|
+
return { dir };
|
|
283
|
+
}
|
|
284
|
+
async function step4Encryption(backend) {
|
|
285
|
+
header(4, TOTAL_STEPS, "Encryption");
|
|
286
|
+
const defaultYes = backend !== "fs";
|
|
287
|
+
if (backend === "fs")
|
|
288
|
+
info("Filesystem backend — encryption is optional (you already control the disk).");
|
|
289
|
+
else
|
|
290
|
+
info(`${backend === "google-drive" ? "Google Drive" : "S3"} backend — encryption is recommended (data leaves your machine).`);
|
|
291
|
+
blank();
|
|
292
|
+
if (!(await confirm("Enable AES-256-GCM encryption at rest?", defaultYes))) {
|
|
293
|
+
return { enabled: false, keyPath: undefined };
|
|
294
|
+
}
|
|
295
|
+
const existingFp = keyFingerprint(DEFAULT_KEY_PATH);
|
|
296
|
+
if (existingFp) {
|
|
297
|
+
info(`Existing key at ${DEFAULT_KEY_PATH} (fingerprint ${existingFp}).`);
|
|
298
|
+
if (await confirm("Use this key?", true))
|
|
299
|
+
return { enabled: true, keyPath: DEFAULT_KEY_PATH };
|
|
300
|
+
blank();
|
|
301
|
+
warn("Rotating the key makes the existing archive unreadable until re-uploaded.");
|
|
302
|
+
if (!(await confirm("Generate a new key (overwrites the existing file)?", false)))
|
|
303
|
+
return { enabled: true, keyPath: DEFAULT_KEY_PATH };
|
|
304
|
+
}
|
|
305
|
+
blank();
|
|
306
|
+
await runKeygen();
|
|
307
|
+
blank();
|
|
308
|
+
info(`Copy ${DEFAULT_KEY_PATH} to each machine that should share this archive.`);
|
|
309
|
+
return { enabled: true, keyPath: DEFAULT_KEY_PATH };
|
|
310
|
+
}
|
|
311
|
+
async function step5WriteConfig(args) {
|
|
312
|
+
header(5, TOTAL_STEPS, "Writing config");
|
|
313
|
+
const login = loadLoginConfig();
|
|
314
|
+
const updates = {
|
|
315
|
+
BACKEND: args.backend,
|
|
316
|
+
};
|
|
317
|
+
if (args.backend === "google-drive" && args.google) {
|
|
318
|
+
if (args.google.driveFolder !== DEFAULT_DRIVE_FOLDER)
|
|
319
|
+
updates.DRIVE_FOLDER = args.google.driveFolder;
|
|
320
|
+
if (args.google.credentialsPath !== login.credentialsPath)
|
|
321
|
+
updates.GOOGLE_CREDENTIALS = args.google.credentialsPath;
|
|
322
|
+
}
|
|
323
|
+
else if (args.backend === "s3" && args.s3) {
|
|
324
|
+
updates.S3_BUCKET = args.s3.bucket;
|
|
325
|
+
if (args.s3.region)
|
|
326
|
+
updates.S3_REGION = args.s3.region;
|
|
327
|
+
if (args.s3.endpoint)
|
|
328
|
+
updates.S3_ENDPOINT = args.s3.endpoint;
|
|
329
|
+
}
|
|
330
|
+
else if (args.backend === "fs" && args.fs) {
|
|
331
|
+
if (args.fs.dir !== DEFAULT_FS_DIR)
|
|
332
|
+
updates.FS_DIR = args.fs.dir;
|
|
333
|
+
}
|
|
334
|
+
if (args.encryption.enabled && args.encryption.keyPath)
|
|
335
|
+
updates.KEY_PATH = args.encryption.keyPath;
|
|
336
|
+
writeConf(PRIMARY_CONF_PATH, updates);
|
|
337
|
+
ok(`Wrote ${PRIMARY_CONF_PATH} (chmod 600).`);
|
|
338
|
+
blank();
|
|
339
|
+
info("Final config:");
|
|
340
|
+
const { map } = readExisting(PRIMARY_CONF_PATH);
|
|
341
|
+
for (const [k, v] of map)
|
|
342
|
+
info(` ${k}=${v}`);
|
|
343
|
+
}
|
|
344
|
+
async function step6RegisterExtension() {
|
|
345
|
+
header(6, TOTAL_STEPS, "Register with hydra (optional)");
|
|
346
|
+
if (!hasBin("hydra-acp")) {
|
|
347
|
+
info("hydra-acp not found on PATH. Register manually later with:");
|
|
348
|
+
info(" hydra-acp extensions add hydra-acp-archiver");
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (readHydraConfigExtensions().has("hydra-acp-archiver")) {
|
|
352
|
+
ok("Already registered as a hydra extension.");
|
|
353
|
+
info("Restart the daemon to pick up the new config: hydra-acp daemon restart");
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
info("hydra can manage hydra-acp-archiver as a subprocess that auto-starts");
|
|
357
|
+
info("with the daemon. This adds an entry to ~/.hydra-acp/config.json.");
|
|
358
|
+
blank();
|
|
359
|
+
if (!(await confirm("Register hydra-acp-archiver as a hydra extension?", true))) {
|
|
360
|
+
info("Skipping. Register later with:");
|
|
361
|
+
info(" hydra-acp extensions add hydra-acp-archiver");
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const cmdArgs = ["extensions", "add", "hydra-acp-archiver"];
|
|
365
|
+
if (!hasBin("hydra-acp-archiver")) {
|
|
366
|
+
const scriptPath = process.argv[1] ?? "";
|
|
367
|
+
if (!scriptPath) {
|
|
368
|
+
warn("Couldn't determine script path; falling back to bare command.");
|
|
369
|
+
}
|
|
370
|
+
else if (scriptPath.includes("/.npm/_npx/")) {
|
|
371
|
+
warn("Looks like you're running via npx — registering this transient path");
|
|
372
|
+
warn("would break on the next npx cache cleanup. Install globally first:");
|
|
373
|
+
info(" npm install -g @hydra-acp/archiver");
|
|
374
|
+
info("Then register with: hydra-acp extensions add hydra-acp-archiver");
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
cmdArgs.push("--command", "node", "--args", scriptPath);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
info(`Running: hydra-acp ${cmdArgs.join(" ")}`);
|
|
382
|
+
const result = spawnSync("hydra-acp", cmdArgs, { stdio: "inherit" });
|
|
383
|
+
if (result.status === 0) {
|
|
384
|
+
ok("Registered.");
|
|
385
|
+
info("Start the daemon (or restart if already running): hydra-acp daemon restart");
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
blank();
|
|
389
|
+
warn(`hydra-acp exited with code ${result.status ?? "?"}.`);
|
|
390
|
+
info("Register manually later with:");
|
|
391
|
+
info(` hydra-acp ${cmdArgs.join(" ")}`);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
export async function runSetup() {
|
|
395
|
+
process.stdout.write(`\n ${BOLD}hydra-acp-archiver setup${RESET}\n`);
|
|
396
|
+
const step1 = await step1ExistingCheck();
|
|
397
|
+
if (!step1.reconfigure)
|
|
398
|
+
return;
|
|
399
|
+
const { backend } = await step2PickBackend();
|
|
400
|
+
let google;
|
|
401
|
+
let s3;
|
|
402
|
+
let fs;
|
|
403
|
+
if (backend === "google-drive")
|
|
404
|
+
google = await step3aGoogleDrive();
|
|
405
|
+
else if (backend === "s3")
|
|
406
|
+
s3 = await step3bS3();
|
|
407
|
+
else
|
|
408
|
+
fs = await step3cFilesystem();
|
|
409
|
+
const encryption = await step4Encryption(backend);
|
|
410
|
+
await step5WriteConfig({ backend, google, s3, fs, encryption });
|
|
411
|
+
await step6RegisterExtension();
|
|
412
|
+
blank();
|
|
413
|
+
ok("Setup complete.");
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=wizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../src/setup/wizard.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hydra-acp/archiver",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "Session sync extension for hydra-acp — uploads session bundles to a shared backend (Google Drive, fs) and imports peers' bundles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|