@indigoai-us/hq-cloud 5.3.0 → 5.4.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/bin/sync-runner.d.ts +45 -16
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js +76 -13
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/bin/sync-runner.test.js +65 -11
- package/dist/bin/sync-runner.test.js.map +1 -1
- package/dist/cli/share.d.ts +6 -0
- package/dist/cli/share.d.ts.map +1 -1
- package/dist/cli/share.js +25 -2
- package/dist/cli/share.js.map +1 -1
- package/dist/cli/share.test.js +45 -0
- package/dist/cli/share.test.js.map +1 -1
- package/dist/cli/sync.d.ts +12 -1
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +27 -2
- package/dist/cli/sync.js.map +1 -1
- package/dist/cli/sync.test.js +34 -0
- package/dist/cli/sync.test.js.map +1 -1
- package/package.json +1 -1
- package/src/bin/sync-runner.test.ts +80 -17
- package/src/bin/sync-runner.ts +91 -17
- package/src/cli/share.test.ts +56 -0
- package/src/cli/share.ts +34 -2
- package/src/cli/sync.test.ts +44 -0
- package/src/cli/sync.ts +43 -4
package/src/cli/sync.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { downloadFile, listRemoteFiles } from "../s3.js";
|
|
|
13
13
|
import { readJournal, writeJournal, hashFile, updateEntry, getEntry } from "../journal.js";
|
|
14
14
|
import { createIgnoreFilter } from "../ignore.js";
|
|
15
15
|
import { resolveConflict } from "./conflict.js";
|
|
16
|
-
import type { ConflictStrategy } from "./conflict.js";
|
|
16
|
+
import type { ConflictStrategy, ConflictResolution } from "./conflict.js";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Per-file events emitted by `sync()` as it progresses.
|
|
@@ -28,7 +28,13 @@ import type { ConflictStrategy } from "./conflict.js";
|
|
|
28
28
|
*/
|
|
29
29
|
export type SyncProgressEvent =
|
|
30
30
|
| { type: "progress"; path: string; bytes: number; message?: string }
|
|
31
|
-
| { type: "error"; path: string; message: string }
|
|
31
|
+
| { type: "error"; path: string; message: string }
|
|
32
|
+
| {
|
|
33
|
+
type: "conflict";
|
|
34
|
+
path: string;
|
|
35
|
+
direction: "pull" | "push";
|
|
36
|
+
resolution: ConflictResolution;
|
|
37
|
+
};
|
|
32
38
|
|
|
33
39
|
export interface SyncOptions {
|
|
34
40
|
/** Company slug or UID (defaults to active company from config) */
|
|
@@ -66,6 +72,12 @@ export interface SyncResult {
|
|
|
66
72
|
bytesDownloaded: number;
|
|
67
73
|
filesSkipped: number;
|
|
68
74
|
conflicts: number;
|
|
75
|
+
/**
|
|
76
|
+
* Paths (remote keys) that were detected as conflicts during this run.
|
|
77
|
+
* Always populated when `conflicts > 0` so callers can surface them in UI
|
|
78
|
+
* or logs without re-streaming the per-file events.
|
|
79
|
+
*/
|
|
80
|
+
conflictPaths: string[];
|
|
69
81
|
aborted: boolean;
|
|
70
82
|
}
|
|
71
83
|
|
|
@@ -106,6 +118,7 @@ export async function sync(options: SyncOptions): Promise<SyncResult> {
|
|
|
106
118
|
let bytesDownloaded = 0;
|
|
107
119
|
let filesSkipped = 0;
|
|
108
120
|
let conflicts = 0;
|
|
121
|
+
const conflictPaths: string[] = [];
|
|
109
122
|
|
|
110
123
|
// List all remote files (IAM session policy filters at the AWS layer)
|
|
111
124
|
const remoteFiles = await listRemoteFiles(ctx);
|
|
@@ -138,6 +151,7 @@ export async function sync(options: SyncOptions): Promise<SyncResult> {
|
|
|
138
151
|
// If local file has changed since last sync, it's a conflict
|
|
139
152
|
if (journalEntry && journalEntry.hash !== localHash) {
|
|
140
153
|
conflicts++;
|
|
154
|
+
conflictPaths.push(remoteFile.key);
|
|
141
155
|
|
|
142
156
|
const resolution = await resolveConflict(
|
|
143
157
|
{
|
|
@@ -150,9 +164,23 @@ export async function sync(options: SyncOptions): Promise<SyncResult> {
|
|
|
150
164
|
onConflict,
|
|
151
165
|
);
|
|
152
166
|
|
|
167
|
+
emit({
|
|
168
|
+
type: "conflict",
|
|
169
|
+
path: remoteFile.key,
|
|
170
|
+
direction: "pull",
|
|
171
|
+
resolution,
|
|
172
|
+
});
|
|
173
|
+
|
|
153
174
|
if (resolution === "abort") {
|
|
154
175
|
writeJournal(journalSlug, journal);
|
|
155
|
-
return {
|
|
176
|
+
return {
|
|
177
|
+
filesDownloaded,
|
|
178
|
+
bytesDownloaded,
|
|
179
|
+
filesSkipped,
|
|
180
|
+
conflicts,
|
|
181
|
+
conflictPaths,
|
|
182
|
+
aborted: true,
|
|
183
|
+
};
|
|
156
184
|
}
|
|
157
185
|
if (resolution === "keep" || resolution === "skip") {
|
|
158
186
|
filesSkipped++;
|
|
@@ -208,7 +236,14 @@ export async function sync(options: SyncOptions): Promise<SyncResult> {
|
|
|
208
236
|
|
|
209
237
|
writeJournal(journalSlug, journal);
|
|
210
238
|
|
|
211
|
-
return {
|
|
239
|
+
return {
|
|
240
|
+
filesDownloaded,
|
|
241
|
+
bytesDownloaded,
|
|
242
|
+
filesSkipped,
|
|
243
|
+
conflicts,
|
|
244
|
+
conflictPaths,
|
|
245
|
+
aborted: false,
|
|
246
|
+
};
|
|
212
247
|
}
|
|
213
248
|
|
|
214
249
|
/**
|
|
@@ -251,5 +286,9 @@ function defaultConsoleLogger(event: SyncProgressEvent): void {
|
|
|
251
286
|
}
|
|
252
287
|
} else if (event.type === "error") {
|
|
253
288
|
console.error(` ✗ ${event.path} — ${event.message}`);
|
|
289
|
+
} else if (event.type === "conflict") {
|
|
290
|
+
console.error(
|
|
291
|
+
` ⚠ conflict (${event.direction}): ${event.path} — ${event.resolution}`,
|
|
292
|
+
);
|
|
254
293
|
}
|
|
255
294
|
}
|