@indigoai-us/hq-cloud 5.1.0
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/auth.d.ts +21 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +116 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli/accept.d.ts +29 -0
- package/dist/cli/accept.d.ts.map +1 -0
- package/dist/cli/accept.js +67 -0
- package/dist/cli/accept.js.map +1 -0
- package/dist/cli/conflict.d.ts +33 -0
- package/dist/cli/conflict.d.ts.map +1 -0
- package/dist/cli/conflict.js +91 -0
- package/dist/cli/conflict.js.map +1 -0
- package/dist/cli/index.d.ts +19 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/invite.d.ts +51 -0
- package/dist/cli/invite.d.ts.map +1 -0
- package/dist/cli/invite.js +120 -0
- package/dist/cli/invite.js.map +1 -0
- package/dist/cli/invite.test.d.ts +5 -0
- package/dist/cli/invite.test.d.ts.map +1 -0
- package/dist/cli/invite.test.js +175 -0
- package/dist/cli/invite.test.js.map +1 -0
- package/dist/cli/promote.d.ts +30 -0
- package/dist/cli/promote.d.ts.map +1 -0
- package/dist/cli/promote.js +79 -0
- package/dist/cli/promote.js.map +1 -0
- package/dist/cli/share.d.ts +33 -0
- package/dist/cli/share.d.ts.map +1 -0
- package/dist/cli/share.js +153 -0
- package/dist/cli/share.js.map +1 -0
- package/dist/cli/share.test.d.ts +5 -0
- package/dist/cli/share.test.d.ts.map +1 -0
- package/dist/cli/share.test.js +121 -0
- package/dist/cli/share.test.js.map +1 -0
- package/dist/cli/sync.d.ts +30 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +138 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli/sync.test.d.ts +5 -0
- package/dist/cli/sync.test.d.ts.map +1 -0
- package/dist/cli/sync.test.js +172 -0
- package/dist/cli/sync.test.js.map +1 -0
- package/dist/cognito-auth.d.ts +70 -0
- package/dist/cognito-auth.d.ts.map +1 -0
- package/dist/cognito-auth.js +280 -0
- package/dist/cognito-auth.js.map +1 -0
- package/dist/context.d.ts +30 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +117 -0
- package/dist/context.js.map +1 -0
- package/dist/context.test.d.ts +7 -0
- package/dist/context.test.d.ts.map +1 -0
- package/dist/context.test.js +148 -0
- package/dist/context.test.js.map +1 -0
- package/dist/daemon-worker.d.ts +6 -0
- package/dist/daemon-worker.d.ts.map +1 -0
- package/dist/daemon-worker.js +26 -0
- package/dist/daemon-worker.js.map +1 -0
- package/dist/daemon.d.ts +10 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +88 -0
- package/dist/daemon.js.map +1 -0
- package/dist/ignore.d.ts +10 -0
- package/dist/ignore.d.ts.map +1 -0
- package/dist/ignore.js +54 -0
- package/dist/ignore.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +138 -0
- package/dist/index.js.map +1 -0
- package/dist/journal.d.ts +12 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +42 -0
- package/dist/journal.js.map +1 -0
- package/dist/s3.d.ts +15 -0
- package/dist/s3.d.ts.map +1 -0
- package/dist/s3.js +129 -0
- package/dist/s3.js.map +1 -0
- package/dist/types.d.ts +52 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/vault-client.d.ts +164 -0
- package/dist/vault-client.d.ts.map +1 -0
- package/dist/vault-client.js +209 -0
- package/dist/vault-client.js.map +1 -0
- package/dist/vault-client.test.d.ts +7 -0
- package/dist/vault-client.test.d.ts.map +1 -0
- package/dist/vault-client.test.js +257 -0
- package/dist/vault-client.test.js.map +1 -0
- package/dist/watcher.d.ts +18 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +106 -0
- package/dist/watcher.js.map +1 -0
- package/package.json +32 -0
- package/src/auth.ts +146 -0
- package/src/cognito-auth.ts +375 -0
- package/src/daemon-worker.ts +32 -0
- package/src/daemon.ts +97 -0
- package/src/ignore.ts +61 -0
- package/src/index.ts +182 -0
- package/src/journal.ts +63 -0
- package/src/s3.ts +178 -0
- package/src/types.ts +59 -0
- package/src/watcher.ts +130 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon worker — runs as a detached child process
|
|
3
|
+
* Watches HQ directory and syncs changes to S3
|
|
4
|
+
*/
|
|
5
|
+
import { SyncWatcher } from "./watcher.js";
|
|
6
|
+
const hqRoot = process.argv[2];
|
|
7
|
+
if (!hqRoot) {
|
|
8
|
+
console.error("Usage: daemon-worker <hq-root>");
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
const watcher = new SyncWatcher(hqRoot);
|
|
12
|
+
watcher.start();
|
|
13
|
+
// Handle graceful shutdown
|
|
14
|
+
process.on("SIGTERM", () => {
|
|
15
|
+
watcher.stop();
|
|
16
|
+
process.exit(0);
|
|
17
|
+
});
|
|
18
|
+
process.on("SIGINT", () => {
|
|
19
|
+
watcher.stop();
|
|
20
|
+
process.exit(0);
|
|
21
|
+
});
|
|
22
|
+
// Keep process alive
|
|
23
|
+
setInterval(() => {
|
|
24
|
+
// Heartbeat — could add remote change polling here
|
|
25
|
+
}, 30_000);
|
|
26
|
+
//# sourceMappingURL=daemon-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-worker.js","sourceRoot":"","sources":["../src/daemon-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAE/B,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;AACxC,OAAO,CAAC,KAAK,EAAE,CAAC;AAEhB,2BAA2B;AAC3B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,OAAO,CAAC,IAAI,EAAE,CAAC;IACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,OAAO,CAAC,IAAI,EAAE,CAAC;IACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,qBAAqB;AACrB,WAAW,CAAC,GAAG,EAAE;IACf,mDAAmD;AACrD,CAAC,EAAE,MAAM,CAAC,CAAC"}
|
package/dist/daemon.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background sync daemon management
|
|
3
|
+
* Manages a child process that runs the file watcher
|
|
4
|
+
*/
|
|
5
|
+
import type { DaemonState } from "./types.js";
|
|
6
|
+
export declare function isDaemonRunning(hqRoot: string): boolean;
|
|
7
|
+
export declare function startDaemon(hqRoot: string): void;
|
|
8
|
+
export declare function stopDaemon(hqRoot: string): void;
|
|
9
|
+
export declare function getDaemonState(hqRoot: string): DaemonState | null;
|
|
10
|
+
//# sourceMappingURL=daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAa9C,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAcvD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA2BhD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAkB/C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CASjE"}
|
package/dist/daemon.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background sync daemon management
|
|
3
|
+
* Manages a child process that runs the file watcher
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import { fork } from "child_process";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
function getPidFile(hqRoot) {
|
|
12
|
+
return path.join(hqRoot, ".hq-sync.pid");
|
|
13
|
+
}
|
|
14
|
+
function getStateFile(hqRoot) {
|
|
15
|
+
return path.join(hqRoot, ".hq-sync-daemon.json");
|
|
16
|
+
}
|
|
17
|
+
export function isDaemonRunning(hqRoot) {
|
|
18
|
+
const pidFile = getPidFile(hqRoot);
|
|
19
|
+
if (!fs.existsSync(pidFile))
|
|
20
|
+
return false;
|
|
21
|
+
const pid = parseInt(fs.readFileSync(pidFile, "utf-8").trim(), 10);
|
|
22
|
+
try {
|
|
23
|
+
// signal 0 tests if process exists without killing it
|
|
24
|
+
process.kill(pid, 0);
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Process not running, clean up stale PID file
|
|
29
|
+
fs.unlinkSync(pidFile);
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function startDaemon(hqRoot) {
|
|
34
|
+
if (isDaemonRunning(hqRoot)) {
|
|
35
|
+
console.log(" Sync daemon is already running.");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const workerScript = path.join(__dirname, "daemon-worker.js");
|
|
39
|
+
const child = fork(workerScript, [hqRoot], {
|
|
40
|
+
detached: true,
|
|
41
|
+
stdio: "ignore",
|
|
42
|
+
});
|
|
43
|
+
child.unref();
|
|
44
|
+
if (child.pid) {
|
|
45
|
+
// Write PID file
|
|
46
|
+
fs.writeFileSync(getPidFile(hqRoot), String(child.pid));
|
|
47
|
+
// Write state
|
|
48
|
+
const state = {
|
|
49
|
+
pid: child.pid,
|
|
50
|
+
startedAt: new Date().toISOString(),
|
|
51
|
+
hqRoot,
|
|
52
|
+
};
|
|
53
|
+
fs.writeFileSync(getStateFile(hqRoot), JSON.stringify(state, null, 2));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function stopDaemon(hqRoot) {
|
|
57
|
+
const pidFile = getPidFile(hqRoot);
|
|
58
|
+
if (!fs.existsSync(pidFile)) {
|
|
59
|
+
console.log(" No sync daemon running.");
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const pid = parseInt(fs.readFileSync(pidFile, "utf-8").trim(), 10);
|
|
63
|
+
try {
|
|
64
|
+
process.kill(pid, "SIGTERM");
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Already dead
|
|
68
|
+
}
|
|
69
|
+
// Clean up files
|
|
70
|
+
if (fs.existsSync(pidFile))
|
|
71
|
+
fs.unlinkSync(pidFile);
|
|
72
|
+
const stateFile = getStateFile(hqRoot);
|
|
73
|
+
if (fs.existsSync(stateFile))
|
|
74
|
+
fs.unlinkSync(stateFile);
|
|
75
|
+
}
|
|
76
|
+
export function getDaemonState(hqRoot) {
|
|
77
|
+
const stateFile = getStateFile(hqRoot);
|
|
78
|
+
if (!fs.existsSync(stateFile))
|
|
79
|
+
return null;
|
|
80
|
+
try {
|
|
81
|
+
const content = fs.readFileSync(stateFile, "utf-8");
|
|
82
|
+
return JSON.parse(content);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
|
package/dist/ignore.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ignore file parser for .hqsyncignore
|
|
3
|
+
* Uses gitignore-compatible syntax
|
|
4
|
+
*/
|
|
5
|
+
export declare function createIgnoreFilter(hqRoot: string): (filePath: string) => boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Check if a file exceeds the max sync size (50MB default)
|
|
8
|
+
*/
|
|
9
|
+
export declare function isWithinSizeLimit(filePath: string, maxBytes?: number): boolean;
|
|
10
|
+
//# sourceMappingURL=ignore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore.d.ts","sourceRoot":"","sources":["../src/ignore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwBH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAkBhF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,QAAQ,SAAmB,GAC1B,OAAO,CAOT"}
|
package/dist/ignore.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ignore file parser for .hqsyncignore
|
|
3
|
+
* Uses gitignore-compatible syntax
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import ignore from "ignore";
|
|
8
|
+
// Default patterns that should never sync
|
|
9
|
+
const DEFAULT_IGNORES = [
|
|
10
|
+
".git/",
|
|
11
|
+
".git",
|
|
12
|
+
"node_modules/",
|
|
13
|
+
"dist/",
|
|
14
|
+
".DS_Store",
|
|
15
|
+
"Thumbs.db",
|
|
16
|
+
"*.pid",
|
|
17
|
+
".hq-sync.pid",
|
|
18
|
+
".hq-sync-journal.json",
|
|
19
|
+
".hq-sync-state.json",
|
|
20
|
+
"modules.lock",
|
|
21
|
+
"repos/",
|
|
22
|
+
".env",
|
|
23
|
+
".env.*",
|
|
24
|
+
];
|
|
25
|
+
export function createIgnoreFilter(hqRoot) {
|
|
26
|
+
const ig = ignore();
|
|
27
|
+
// Add defaults
|
|
28
|
+
ig.add(DEFAULT_IGNORES);
|
|
29
|
+
// Read .hqsyncignore if it exists
|
|
30
|
+
const ignorePath = path.join(hqRoot, ".hqsyncignore");
|
|
31
|
+
if (fs.existsSync(ignorePath)) {
|
|
32
|
+
const content = fs.readFileSync(ignorePath, "utf-8");
|
|
33
|
+
ig.add(content);
|
|
34
|
+
}
|
|
35
|
+
return (filePath) => {
|
|
36
|
+
const relative = path.relative(hqRoot, filePath);
|
|
37
|
+
if (!relative || relative.startsWith(".."))
|
|
38
|
+
return true; // outside HQ root
|
|
39
|
+
return !ig.ignores(relative);
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if a file exceeds the max sync size (50MB default)
|
|
44
|
+
*/
|
|
45
|
+
export function isWithinSizeLimit(filePath, maxBytes = 50 * 1024 * 1024) {
|
|
46
|
+
try {
|
|
47
|
+
const stat = fs.statSync(filePath);
|
|
48
|
+
return stat.size <= maxBytes;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=ignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore.js","sourceRoot":"","sources":["../src/ignore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,0CAA0C;AAC1C,MAAM,eAAe,GAAG;IACtB,OAAO;IACP,MAAM;IACN,eAAe;IACf,OAAO;IACP,WAAW;IACX,WAAW;IACX,OAAO;IACP,cAAc;IACd,uBAAuB;IACvB,qBAAqB;IACrB,cAAc;IACd,QAAQ;IACR,MAAM;IACN,QAAQ;CACT,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAEpB,eAAe;IACf,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAExB,kCAAkC;IAClC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACtD,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACrD,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,QAAgB,EAAW,EAAE;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,CAAC,kBAAkB;QAC3E,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,QAAQ,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI;IAE3B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @indigoai-us/hq-cloud — public API
|
|
3
|
+
* Used by @indigoai-us/hq-cli to manage cloud sync
|
|
4
|
+
*/
|
|
5
|
+
import type { SyncStatus, PushResult, PullResult } from "./types.js";
|
|
6
|
+
export type { SyncStatus, PushResult, PullResult } from "./types.js";
|
|
7
|
+
export { browserLogin, refreshTokens, getValidAccessToken, loadCachedTokens, saveCachedTokens, clearCachedTokens, isExpiring, CognitoAuthError, } from "./cognito-auth.js";
|
|
8
|
+
export type { CognitoAuthConfig, CognitoTokens } from "./cognito-auth.js";
|
|
9
|
+
/**
|
|
10
|
+
* Initialize cloud sync — authenticate and provision bucket
|
|
11
|
+
*/
|
|
12
|
+
export declare function initSync(hqRoot: string): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Start the background sync daemon
|
|
15
|
+
*/
|
|
16
|
+
export declare function startDaemon(hqRoot: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Stop the background sync daemon
|
|
19
|
+
*/
|
|
20
|
+
export declare function stopDaemon(hqRoot: string): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Get current sync status
|
|
23
|
+
*/
|
|
24
|
+
export declare function getStatus(hqRoot: string): Promise<SyncStatus>;
|
|
25
|
+
/**
|
|
26
|
+
* Force push all local files to S3
|
|
27
|
+
*/
|
|
28
|
+
export declare function pushAll(hqRoot: string): Promise<PushResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Force pull all remote files to local
|
|
31
|
+
*/
|
|
32
|
+
export declare function pullAll(hqRoot: string): Promise<PullResult>;
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAErE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIrE,OAAO,EACL,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE1E;;GAEG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAa5D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/D;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAiBnE;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA4BjE;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAyBjE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @indigoai-us/hq-cloud — public API
|
|
3
|
+
* Used by @indigoai-us/hq-cli to manage cloud sync
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import { authenticate, hasCredentials, readCredentials } from "./auth.js";
|
|
8
|
+
import { startDaemon as _startDaemon, stopDaemon as _stopDaemon, isDaemonRunning, } from "./daemon.js";
|
|
9
|
+
import { readJournal, writeJournal, hashFile, updateEntry } from "./journal.js";
|
|
10
|
+
import { uploadFile, downloadFile, listRemoteFiles } from "./s3.js";
|
|
11
|
+
import { createIgnoreFilter, isWithinSizeLimit } from "./ignore.js";
|
|
12
|
+
// Cognito identity helpers — used by `hq auth refresh` and any consumer
|
|
13
|
+
// that needs a valid HQ access token (deploy skill, onboarding, etc.).
|
|
14
|
+
export { browserLogin, refreshTokens, getValidAccessToken, loadCachedTokens, saveCachedTokens, clearCachedTokens, isExpiring, CognitoAuthError, } from "./cognito-auth.js";
|
|
15
|
+
/**
|
|
16
|
+
* Initialize cloud sync — authenticate and provision bucket
|
|
17
|
+
*/
|
|
18
|
+
export async function initSync(hqRoot) {
|
|
19
|
+
if (hasCredentials()) {
|
|
20
|
+
console.log(" Already authenticated. Use 'hq sync start' to begin syncing.");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
console.log(" Setting up IndigoAI cloud sync...");
|
|
24
|
+
const creds = await authenticate();
|
|
25
|
+
console.log(` ✓ Authenticated as ${creds.userId}`);
|
|
26
|
+
console.log(` ✓ Bucket: ${creds.bucket}`);
|
|
27
|
+
console.log(` ✓ Region: ${creds.region}`);
|
|
28
|
+
console.log();
|
|
29
|
+
console.log(" Run 'hq sync start' to begin syncing.");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Start the background sync daemon
|
|
33
|
+
*/
|
|
34
|
+
export async function startDaemon(hqRoot) {
|
|
35
|
+
if (!hasCredentials()) {
|
|
36
|
+
throw new Error("Not authenticated. Run 'hq sync init' first.");
|
|
37
|
+
}
|
|
38
|
+
_startDaemon(hqRoot);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Stop the background sync daemon
|
|
42
|
+
*/
|
|
43
|
+
export async function stopDaemon(hqRoot) {
|
|
44
|
+
_stopDaemon(hqRoot);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get current sync status
|
|
48
|
+
*/
|
|
49
|
+
export async function getStatus(hqRoot) {
|
|
50
|
+
const journal = readJournal(hqRoot);
|
|
51
|
+
const creds = readCredentials();
|
|
52
|
+
const running = isDaemonRunning(hqRoot);
|
|
53
|
+
const errors = [];
|
|
54
|
+
if (!creds) {
|
|
55
|
+
errors.push("Not authenticated — run 'hq sync init'");
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
running,
|
|
59
|
+
lastSync: journal.lastSync || null,
|
|
60
|
+
fileCount: Object.keys(journal.files).length,
|
|
61
|
+
bucket: creds?.bucket || null,
|
|
62
|
+
errors,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Force push all local files to S3
|
|
67
|
+
*/
|
|
68
|
+
export async function pushAll(hqRoot) {
|
|
69
|
+
const shouldSync = createIgnoreFilter(hqRoot);
|
|
70
|
+
const journal = readJournal(hqRoot);
|
|
71
|
+
let filesUploaded = 0;
|
|
72
|
+
let bytesUploaded = 0;
|
|
73
|
+
const files = walkDir(hqRoot, hqRoot, shouldSync);
|
|
74
|
+
for (const { absolutePath, relativePath } of files) {
|
|
75
|
+
if (!isWithinSizeLimit(absolutePath))
|
|
76
|
+
continue;
|
|
77
|
+
try {
|
|
78
|
+
const hash = hashFile(absolutePath);
|
|
79
|
+
const stat = fs.statSync(absolutePath);
|
|
80
|
+
await uploadFile(absolutePath, relativePath);
|
|
81
|
+
updateEntry(journal, relativePath, hash, stat.size, "up");
|
|
82
|
+
filesUploaded++;
|
|
83
|
+
bytesUploaded += stat.size;
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
console.error(` Failed: ${relativePath} — ${err instanceof Error ? err.message : err}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
writeJournal(hqRoot, journal);
|
|
90
|
+
return { filesUploaded, bytesUploaded };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Force pull all remote files to local
|
|
94
|
+
*/
|
|
95
|
+
export async function pullAll(hqRoot) {
|
|
96
|
+
const journal = readJournal(hqRoot);
|
|
97
|
+
let filesDownloaded = 0;
|
|
98
|
+
let bytesDownloaded = 0;
|
|
99
|
+
const remoteFiles = await listRemoteFiles();
|
|
100
|
+
for (const file of remoteFiles) {
|
|
101
|
+
try {
|
|
102
|
+
const localPath = path.join(hqRoot, file.relativePath);
|
|
103
|
+
await downloadFile(file.relativePath, localPath);
|
|
104
|
+
const hash = hashFile(localPath);
|
|
105
|
+
updateEntry(journal, file.relativePath, hash, file.size, "down");
|
|
106
|
+
filesDownloaded++;
|
|
107
|
+
bytesDownloaded += file.size;
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
console.error(` Failed: ${file.relativePath} — ${err instanceof Error ? err.message : err}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
writeJournal(hqRoot, journal);
|
|
114
|
+
return { filesDownloaded, bytesDownloaded };
|
|
115
|
+
}
|
|
116
|
+
// Helper: recursively walk a directory
|
|
117
|
+
function walkDir(dir, root, filter) {
|
|
118
|
+
const results = [];
|
|
119
|
+
if (!fs.existsSync(dir))
|
|
120
|
+
return results;
|
|
121
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
122
|
+
for (const entry of entries) {
|
|
123
|
+
const absolutePath = path.join(dir, entry.name);
|
|
124
|
+
if (!filter(absolutePath))
|
|
125
|
+
continue;
|
|
126
|
+
if (entry.isDirectory()) {
|
|
127
|
+
results.push(...walkDir(absolutePath, root, filter));
|
|
128
|
+
}
|
|
129
|
+
else if (entry.isFile()) {
|
|
130
|
+
results.push({
|
|
131
|
+
absolutePath,
|
|
132
|
+
relativePath: path.relative(root, absolutePath),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return results;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync journal — tracks file state for conflict detection
|
|
3
|
+
*/
|
|
4
|
+
import type { SyncJournal, JournalEntry } from "./types.js";
|
|
5
|
+
export declare function getJournalPath(hqRoot: string): string;
|
|
6
|
+
export declare function readJournal(hqRoot: string): SyncJournal;
|
|
7
|
+
export declare function writeJournal(hqRoot: string, journal: SyncJournal): void;
|
|
8
|
+
export declare function hashFile(filePath: string): string;
|
|
9
|
+
export declare function updateEntry(journal: SyncJournal, relativePath: string, hash: string, size: number, direction: "up" | "down"): void;
|
|
10
|
+
export declare function getEntry(journal: SyncJournal, relativePath: string): JournalEntry | undefined;
|
|
11
|
+
export declare function removeEntry(journal: SyncJournal, relativePath: string): void;
|
|
12
|
+
//# sourceMappingURL=journal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../src/journal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI5D,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAOvD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAGvE;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED,wBAAgB,WAAW,CACzB,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,IAAI,GAAG,MAAM,GACvB,IAAI,CAQN;AAED,wBAAgB,QAAQ,CACtB,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,MAAM,GACnB,YAAY,GAAG,SAAS,CAE1B;AAED,wBAAgB,WAAW,CACzB,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,MAAM,GACnB,IAAI,CAEN"}
|
package/dist/journal.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync journal — tracks file state for conflict detection
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import * as crypto from "crypto";
|
|
7
|
+
const JOURNAL_FILE = ".hq-sync-journal.json";
|
|
8
|
+
export function getJournalPath(hqRoot) {
|
|
9
|
+
return path.join(hqRoot, JOURNAL_FILE);
|
|
10
|
+
}
|
|
11
|
+
export function readJournal(hqRoot) {
|
|
12
|
+
const journalPath = getJournalPath(hqRoot);
|
|
13
|
+
if (fs.existsSync(journalPath)) {
|
|
14
|
+
const content = fs.readFileSync(journalPath, "utf-8");
|
|
15
|
+
return JSON.parse(content);
|
|
16
|
+
}
|
|
17
|
+
return { version: "1", lastSync: "", files: {} };
|
|
18
|
+
}
|
|
19
|
+
export function writeJournal(hqRoot, journal) {
|
|
20
|
+
const journalPath = getJournalPath(hqRoot);
|
|
21
|
+
fs.writeFileSync(journalPath, JSON.stringify(journal, null, 2));
|
|
22
|
+
}
|
|
23
|
+
export function hashFile(filePath) {
|
|
24
|
+
const content = fs.readFileSync(filePath);
|
|
25
|
+
return crypto.createHash("sha256").update(content).digest("hex");
|
|
26
|
+
}
|
|
27
|
+
export function updateEntry(journal, relativePath, hash, size, direction) {
|
|
28
|
+
journal.files[relativePath] = {
|
|
29
|
+
hash,
|
|
30
|
+
size,
|
|
31
|
+
syncedAt: new Date().toISOString(),
|
|
32
|
+
direction,
|
|
33
|
+
};
|
|
34
|
+
journal.lastSync = new Date().toISOString();
|
|
35
|
+
}
|
|
36
|
+
export function getEntry(journal, relativePath) {
|
|
37
|
+
return journal.files[relativePath];
|
|
38
|
+
}
|
|
39
|
+
export function removeEntry(journal, relativePath) {
|
|
40
|
+
delete journal.files[relativePath];
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=journal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal.js","sourceRoot":"","sources":["../src/journal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,MAAM,YAAY,GAAG,uBAAuB,CAAC;AAE7C,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAgB,CAAC;IAC5C,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,OAAoB;IAC/D,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC3C,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,QAAgB;IACvC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,OAAoB,EACpB,YAAoB,EACpB,IAAY,EACZ,IAAY,EACZ,SAAwB;IAExB,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG;QAC5B,IAAI;QACJ,IAAI;QACJ,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAClC,SAAS;KACV,CAAC;IACF,OAAO,CAAC,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,QAAQ,CACtB,OAAoB,EACpB,YAAoB;IAEpB,OAAO,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,OAAoB,EACpB,YAAoB;IAEpB,OAAO,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/s3.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3 operations — upload, download, list, delete
|
|
3
|
+
*/
|
|
4
|
+
export declare function uploadFile(localPath: string, relativePath: string): Promise<void>;
|
|
5
|
+
export declare function downloadFile(relativePath: string, localPath: string): Promise<void>;
|
|
6
|
+
export interface RemoteFile {
|
|
7
|
+
key: string;
|
|
8
|
+
relativePath: string;
|
|
9
|
+
size: number;
|
|
10
|
+
lastModified: Date;
|
|
11
|
+
etag: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function listRemoteFiles(): Promise<RemoteFile[]>;
|
|
14
|
+
export declare function deleteRemoteFile(relativePath: string): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=s3.d.ts.map
|
package/dist/s3.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../src/s3.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqDH,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAgC7D;AAED,wBAAsB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU1E"}
|
package/dist/s3.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3 operations — upload, download, list, delete
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import { S3Client, PutObjectCommand, GetObjectCommand, ListObjectsV2Command, DeleteObjectCommand, } from "@aws-sdk/client-s3";
|
|
7
|
+
import { readCredentials, refreshAwsCredentials } from "./auth.js";
|
|
8
|
+
let s3Client = null;
|
|
9
|
+
function getConfig(creds) {
|
|
10
|
+
const prefix = creds.teamId
|
|
11
|
+
? `teams/${creds.teamId}/users/${creds.userId}/hq/`
|
|
12
|
+
: `users/${creds.userId}/hq/`;
|
|
13
|
+
return {
|
|
14
|
+
bucket: creds.bucket,
|
|
15
|
+
region: creds.region,
|
|
16
|
+
userId: creds.userId,
|
|
17
|
+
prefix,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async function getClient() {
|
|
21
|
+
let creds = readCredentials();
|
|
22
|
+
if (!creds) {
|
|
23
|
+
throw new Error("Not authenticated. Run 'hq sync init' first.");
|
|
24
|
+
}
|
|
25
|
+
// Refresh if expired or missing access key
|
|
26
|
+
if (!creds.accessKeyId || (creds.expiration && new Date(creds.expiration) < new Date())) {
|
|
27
|
+
creds = await refreshAwsCredentials(creds);
|
|
28
|
+
}
|
|
29
|
+
if (!s3Client) {
|
|
30
|
+
s3Client = new S3Client({
|
|
31
|
+
region: creds.region,
|
|
32
|
+
credentials: {
|
|
33
|
+
accessKeyId: creds.accessKeyId,
|
|
34
|
+
secretAccessKey: creds.secretAccessKey,
|
|
35
|
+
sessionToken: creds.sessionToken,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return { client: s3Client, config: getConfig(creds) };
|
|
40
|
+
}
|
|
41
|
+
export async function uploadFile(localPath, relativePath) {
|
|
42
|
+
const { client, config } = await getClient();
|
|
43
|
+
const key = `${config.prefix}${relativePath}`;
|
|
44
|
+
const body = fs.readFileSync(localPath);
|
|
45
|
+
await client.send(new PutObjectCommand({
|
|
46
|
+
Bucket: config.bucket,
|
|
47
|
+
Key: key,
|
|
48
|
+
Body: body,
|
|
49
|
+
ContentType: getMimeType(relativePath),
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
export async function downloadFile(relativePath, localPath) {
|
|
53
|
+
const { client, config } = await getClient();
|
|
54
|
+
const key = `${config.prefix}${relativePath}`;
|
|
55
|
+
const response = await client.send(new GetObjectCommand({
|
|
56
|
+
Bucket: config.bucket,
|
|
57
|
+
Key: key,
|
|
58
|
+
}));
|
|
59
|
+
if (!response.Body) {
|
|
60
|
+
throw new Error(`Empty response for ${key}`);
|
|
61
|
+
}
|
|
62
|
+
const dir = path.dirname(localPath);
|
|
63
|
+
if (!fs.existsSync(dir)) {
|
|
64
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
65
|
+
}
|
|
66
|
+
const chunks = [];
|
|
67
|
+
const stream = response.Body;
|
|
68
|
+
for await (const chunk of stream) {
|
|
69
|
+
chunks.push(Buffer.from(chunk));
|
|
70
|
+
}
|
|
71
|
+
fs.writeFileSync(localPath, Buffer.concat(chunks));
|
|
72
|
+
}
|
|
73
|
+
export async function listRemoteFiles() {
|
|
74
|
+
const { client, config } = await getClient();
|
|
75
|
+
const files = [];
|
|
76
|
+
let continuationToken;
|
|
77
|
+
do {
|
|
78
|
+
const response = await client.send(new ListObjectsV2Command({
|
|
79
|
+
Bucket: config.bucket,
|
|
80
|
+
Prefix: config.prefix,
|
|
81
|
+
ContinuationToken: continuationToken,
|
|
82
|
+
}));
|
|
83
|
+
for (const obj of response.Contents || []) {
|
|
84
|
+
if (!obj.Key || !obj.Size)
|
|
85
|
+
continue;
|
|
86
|
+
const relativePath = obj.Key.replace(config.prefix, "");
|
|
87
|
+
if (!relativePath)
|
|
88
|
+
continue;
|
|
89
|
+
files.push({
|
|
90
|
+
key: obj.Key,
|
|
91
|
+
relativePath,
|
|
92
|
+
size: obj.Size,
|
|
93
|
+
lastModified: obj.LastModified || new Date(),
|
|
94
|
+
etag: obj.ETag || "",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
continuationToken = response.NextContinuationToken;
|
|
98
|
+
} while (continuationToken);
|
|
99
|
+
return files;
|
|
100
|
+
}
|
|
101
|
+
export async function deleteRemoteFile(relativePath) {
|
|
102
|
+
const { client, config } = await getClient();
|
|
103
|
+
const key = `${config.prefix}${relativePath}`;
|
|
104
|
+
await client.send(new DeleteObjectCommand({
|
|
105
|
+
Bucket: config.bucket,
|
|
106
|
+
Key: key,
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
function getMimeType(filePath) {
|
|
110
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
111
|
+
const mimeTypes = {
|
|
112
|
+
".md": "text/markdown",
|
|
113
|
+
".json": "application/json",
|
|
114
|
+
".yaml": "text/yaml",
|
|
115
|
+
".yml": "text/yaml",
|
|
116
|
+
".ts": "text/typescript",
|
|
117
|
+
".js": "text/javascript",
|
|
118
|
+
".txt": "text/plain",
|
|
119
|
+
".html": "text/html",
|
|
120
|
+
".css": "text/css",
|
|
121
|
+
".png": "image/png",
|
|
122
|
+
".jpg": "image/jpeg",
|
|
123
|
+
".jpeg": "image/jpeg",
|
|
124
|
+
".svg": "image/svg+xml",
|
|
125
|
+
".pdf": "application/pdf",
|
|
126
|
+
};
|
|
127
|
+
return mimeTypes[ext] || "application/octet-stream";
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=s3.js.map
|
package/dist/s3.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.js","sourceRoot":"","sources":["../src/s3.ts"],"names":[],"mappings":"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"}
|