@indigoai-us/hq-cloud 6.14.20 → 6.14.22
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/cli/reindex.d.ts.map +1 -1
- package/dist/cli/reindex.js +54 -20
- package/dist/cli/reindex.js.map +1 -1
- package/dist/cli/reindex.test.js +66 -4
- package/dist/cli/reindex.test.js.map +1 -1
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +15 -1
- package/dist/cli/sync.js.map +1 -1
- package/dist/s3.d.ts +23 -0
- package/dist/s3.d.ts.map +1 -1
- package/dist/s3.js +51 -1
- package/dist/s3.js.map +1 -1
- package/dist/s3.test.js +38 -1
- package/dist/s3.test.js.map +1 -1
- package/package.json +2 -2
- package/src/cli/reindex.test.ts +74 -6
- package/src/cli/reindex.ts +59 -22
- package/src/cli/sync.ts +14 -0
- package/src/s3.test.ts +45 -0
- package/src/s3.ts +54 -1
package/src/s3.ts
CHANGED
|
@@ -1003,6 +1003,59 @@ export interface DownloadModeWarning {
|
|
|
1003
1003
|
fallback?: "preserved-local-mode" | "receiver-default";
|
|
1004
1004
|
}
|
|
1005
1005
|
|
|
1006
|
+
/**
|
|
1007
|
+
* A download whose parent directory exists as a DANGLING symlink.
|
|
1008
|
+
*
|
|
1009
|
+
* The vault stores directory symlinks as first-class objects (e.g.
|
|
1010
|
+
* `companies/<co>/.obsidian -> ../../.obsidian`) AND stores files beneath them.
|
|
1011
|
+
* When the link's target is absent on this machine, the child write fails —
|
|
1012
|
+
* and it fails as ENOENT rather than EEXIST, because `mkdir(2)` returns EEXIST
|
|
1013
|
+
* for the link and Node's `recursive: true` implementation then stats it, which
|
|
1014
|
+
* fails on a dangling link. Raw, that surfaced as a hard error that marked the
|
|
1015
|
+
* WHOLE company `errored`/`partial` on every sync cycle (2026-07-24 dogfood box:
|
|
1016
|
+
* `.obsidian/hotkeys.json: ENOENT ... mkdir '.../companies/indigo/.obsidian'`).
|
|
1017
|
+
*
|
|
1018
|
+
* It is a per-object condition, not a company-level failure, so it is typed and
|
|
1019
|
+
* the pull loop skips the object loudly instead of failing the run. We do NOT
|
|
1020
|
+
* materialize the link target: the target is by definition outside the
|
|
1021
|
+
* directory being synced, and creating it would write through a path the
|
|
1022
|
+
* caller's containment guard deliberately refuses.
|
|
1023
|
+
*/
|
|
1024
|
+
export class DanglingSymlinkParentError extends Error {
|
|
1025
|
+
readonly key: string;
|
|
1026
|
+
readonly dir: string;
|
|
1027
|
+
constructor(key: string, dir: string) {
|
|
1028
|
+
super(
|
|
1029
|
+
`download skipped: parent directory is a dangling symlink (${dir}) — ` +
|
|
1030
|
+
`the vault stores it as a link whose target is absent locally`,
|
|
1031
|
+
);
|
|
1032
|
+
this.name = "DanglingSymlinkParentError";
|
|
1033
|
+
this.key = key;
|
|
1034
|
+
this.dir = dir;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
/**
|
|
1039
|
+
* Create the parent directory for a download, distinguishing the
|
|
1040
|
+
* dangling-symlink case from a genuine mkdir failure.
|
|
1041
|
+
*
|
|
1042
|
+
* Callers must have already established that `dir` does not resolve
|
|
1043
|
+
* (`fs.existsSync(dir) === false`); `existsSync` FOLLOWS symlinks, so a
|
|
1044
|
+
* dangling link reports absent here while `lstat` still sees the link.
|
|
1045
|
+
*/
|
|
1046
|
+
function ensureDownloadParentDir(dir: string, key: string): void {
|
|
1047
|
+
let link: fs.Stats | null = null;
|
|
1048
|
+
try {
|
|
1049
|
+
link = fs.lstatSync(dir);
|
|
1050
|
+
} catch {
|
|
1051
|
+
// Genuinely absent — the ordinary first-write path.
|
|
1052
|
+
}
|
|
1053
|
+
if (link?.isSymbolicLink()) {
|
|
1054
|
+
throw new DanglingSymlinkParentError(key, dir);
|
|
1055
|
+
}
|
|
1056
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1006
1059
|
export async function downloadFile(
|
|
1007
1060
|
ctx: EntityContext,
|
|
1008
1061
|
key: string,
|
|
@@ -1032,7 +1085,7 @@ export async function downloadFile(
|
|
|
1032
1085
|
|
|
1033
1086
|
const dir = path.dirname(localPath);
|
|
1034
1087
|
if (!fs.existsSync(dir)) {
|
|
1035
|
-
|
|
1088
|
+
ensureDownloadParentDir(dir, key);
|
|
1036
1089
|
}
|
|
1037
1090
|
|
|
1038
1091
|
// Symlink path: presence of SYMLINK_TARGET_META_KEY (any non-empty
|