@openclaw/fs-safe 0.8.2 → 0.8.3
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/CHANGELOG.md +9 -0
- package/README.md +1 -1
- package/dist/advanced.d.ts +2 -2
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +2 -2
- package/dist/archive-kind.d.ts +1 -0
- package/dist/archive-kind.d.ts.map +1 -1
- package/dist/archive-kind.js +6 -0
- package/dist/archive-limits.d.ts +0 -1
- package/dist/archive-limits.d.ts.map +1 -1
- package/dist/archive-limits.js +0 -3
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +5 -8
- package/dist/archive-parser-errors.d.ts +2 -0
- package/dist/archive-parser-errors.d.ts.map +1 -0
- package/dist/archive-parser-errors.js +12 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +7 -13
- package/dist/archive-tar-wasm.d.ts +1 -1
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +5 -8
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +43 -6
- package/dist/atomic.d.ts +1 -1
- package/dist/atomic.d.ts.map +1 -1
- package/dist/atomic.js +1 -1
- package/dist/bounded-read-stream.d.ts +1 -5
- package/dist/bounded-read-stream.d.ts.map +1 -1
- package/dist/bounded-read-stream.js +5 -13
- package/dist/byte-budget.d.ts +0 -1
- package/dist/byte-budget.d.ts.map +1 -1
- package/dist/byte-budget.js +1 -1
- package/dist/directory-mode-owner.d.ts.map +1 -1
- package/dist/directory-mode-owner.js +2 -0
- package/dist/error-detail.d.ts +1 -0
- package/dist/error-detail.d.ts.map +1 -1
- package/dist/error-detail.js +6 -0
- package/dist/file-store-boundary.d.ts +1 -1
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +2 -13
- package/dist/file-store.js +1 -1
- package/dist/file-sync.d.ts +5 -0
- package/dist/file-sync.d.ts.map +1 -0
- package/dist/file-sync.js +19 -0
- package/dist/guarded-mutation.d.ts +3 -0
- package/dist/guarded-mutation.d.ts.map +1 -1
- package/dist/guarded-mutation.js +5 -1
- package/dist/home-dir.d.ts +0 -10
- package/dist/home-dir.d.ts.map +1 -1
- package/dist/home-dir.js +0 -28
- package/dist/json-durable-queue-ownership.d.ts +1 -0
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +139 -18
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +5 -10
- package/dist/json-store.d.ts.map +1 -1
- package/dist/json-store.js +1 -1
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +2 -3
- package/dist/move-path-cleanup.d.ts +1 -1
- package/dist/move-path-cleanup.d.ts.map +1 -1
- package/dist/move-path-cleanup.js +4 -2
- package/dist/move-path.d.ts +9 -0
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +53 -16
- package/dist/native-operations.d.ts +0 -1
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +0 -10
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +5 -4
- package/dist/native-staged-file.d.ts +8 -1
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +30 -9
- package/dist/opened-realpath.d.ts +12 -1
- package/dist/opened-realpath.d.ts.map +1 -1
- package/dist/opened-realpath.js +8 -7
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +26 -2
- package/dist/path-policy.js +1 -1
- package/dist/permissions.d.ts +1 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +3 -0
- package/dist/pinned-write.d.ts +1 -2
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +2 -11
- package/dist/private-temp-workspace.js +1 -1
- package/dist/publish-file.js +2 -2
- package/dist/replace-file-copy-source.d.ts.map +1 -1
- package/dist/replace-file-copy-source.js +2 -7
- package/dist/replace-file-descriptor.d.ts.map +1 -1
- package/dist/replace-file-descriptor.js +3 -16
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +2 -7
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +21 -8
- package/dist/root-errors.d.ts +1 -0
- package/dist/root-errors.d.ts.map +1 -1
- package/dist/root-errors.js +9 -0
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +17 -28
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +12 -33
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +49 -94
- package/dist/root-write-mode.d.ts +6 -0
- package/dist/root-write-mode.d.ts.map +1 -0
- package/dist/root-write-mode.js +60 -0
- package/dist/root-write-verification.js +2 -2
- package/dist/safe-path-segment.d.ts +1 -0
- package/dist/safe-path-segment.d.ts.map +1 -1
- package/dist/safe-path-segment.js +1 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +2 -9
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +2 -10
- package/dist/secret-read-policy.d.ts +4 -0
- package/dist/secret-read-policy.d.ts.map +1 -1
- package/dist/secret-read-policy.js +12 -0
- package/dist/sibling-staged-file.d.ts.map +1 -1
- package/dist/sibling-staged-file.js +2 -7
- package/dist/sidecar-lock-policy.d.ts +0 -1
- package/dist/sidecar-lock-policy.d.ts.map +1 -1
- package/dist/sidecar-lock-policy.js +0 -4
- package/dist/string-coerce.d.ts +0 -9
- package/dist/string-coerce.d.ts.map +1 -1
- package/dist/string-coerce.js +0 -56
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +1 -12
- package/docs/atomic.md +53 -19
- package/docs/staged-file.md +6 -2
- package/docs/writing.md +5 -0
- package/package.json +8 -8
- package/dist/archive-tar-extract.d.ts +0 -11
- package/dist/archive-tar-extract.d.ts.map +0 -1
- package/dist/archive-tar-extract.js +0 -49
- package/dist/fsync.d.ts +0 -2
- package/dist/fsync.d.ts.map +0 -1
- package/dist/fsync.js +0 -1
- package/dist/json-durable-queue-retirement.d.ts +0 -9
- package/dist/json-durable-queue-retirement.d.ts.map +0 -1
- package/dist/json-durable-queue-retirement.js +0 -126
- package/dist/json-durable-queue-transfer-lock.d.ts +0 -2
- package/dist/json-durable-queue-transfer-lock.d.ts.map +0 -1
- package/dist/json-durable-queue-transfer-lock.js +0 -19
- package/dist/mode.d.ts +0 -2
- package/dist/mode.d.ts.map +0 -1
- package/dist/mode.js +0 -3
- package/dist/output-sibling.d.ts +0 -8
- package/dist/output-sibling.d.ts.map +0 -1
- package/dist/output-sibling.js +0 -30
- package/dist/read-error.d.ts +0 -2
- package/dist/read-error.d.ts.map +0 -1
- package/dist/read-error.js +0 -11
- package/dist/short-path.d.ts +0 -2
- package/dist/short-path.d.ts.map +0 -1
- package/dist/short-path.js +0 -7
- package/dist/staged-file.d.ts +0 -10
- package/dist/staged-file.d.ts.map +0 -1
- package/dist/staged-file.js +0 -15
package/dist/root-errors.js
CHANGED
|
@@ -64,3 +64,12 @@ export function normalizeRemovePathError(error) {
|
|
|
64
64
|
}
|
|
65
65
|
return new FsSafeError("not-removable", "path could not be removed", { cause });
|
|
66
66
|
}
|
|
67
|
+
export function throwFsSafeReadError(error, label) {
|
|
68
|
+
if (error instanceof FsSafeError) {
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
if (isNodeError(error)) {
|
|
72
|
+
throw new FsSafeError("read-failed", `${label} target could not be read`, { cause: error });
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
package/dist/root-file.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-file.d.ts","sourceRoot":"","sources":["../src/root-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAOzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EACjC,MAAM,kBAAkB,CAAC;AAE1B,KAAK,cAAc,GAAG,IAAI,CACxB,OAAO,EAAE,EACP,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,UAAU,GACV,cAAc,GACd,cAAc,CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,2BAA2B,GAAG,YAAY,CAAC;AAEnF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,yBAAyB,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtE,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAE7E,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,GAAG;IACxD,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B,CAAC;AAQF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAW3D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"root-file.d.ts","sourceRoot":"","sources":["../src/root-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAOzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EACjC,MAAM,kBAAkB,CAAC;AAE1B,KAAK,cAAc,GAAG,IAAI,CACxB,OAAO,EAAE,EACP,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,UAAU,GACV,cAAc,GACd,cAAc,CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,2BAA2B,GAAG,YAAY,CAAC;AAEnF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,yBAAyB,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtE,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAE7E,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,GAAG;IACxD,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B,CAAC;AAQF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAW3D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,kBAAkB,CAuBnF;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE;IACR,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,CAAC,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,CAAC,CAAC;IACjD,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,CAAC,CAAC;IACzC,QAAQ,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,CAAC,CAAC;CAC/C,GACA,CAAC,CAUH;AAoDD,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CAwB7B"}
|
package/dist/root-file.js
CHANGED
|
@@ -14,19 +14,20 @@ export function canUseRootFileOpen(ioFs) {
|
|
|
14
14
|
}
|
|
15
15
|
export function openRootFileSync(params) {
|
|
16
16
|
const ioFs = params.ioFs ?? fs;
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
const absolutePath = path.resolve(params.absolutePath);
|
|
18
|
+
let resolved;
|
|
19
|
+
try {
|
|
20
|
+
resolved = mapResolvedRootPath(absolutePath, resolveRootPathSync({
|
|
20
21
|
absolutePath,
|
|
21
22
|
rootPath: params.rootPath,
|
|
22
23
|
rootCanonicalPath: params.rootRealPath,
|
|
23
24
|
boundaryLabel: params.boundaryLabel,
|
|
24
25
|
rejectSymlinks: params.rejectSymlinks ?? true,
|
|
25
26
|
skipLexicalRootCheck: params.skipLexicalRootCheck,
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
resolved = toBoundaryValidationError(error);
|
|
30
31
|
}
|
|
31
32
|
return finalizeRootFileOpen({
|
|
32
33
|
resolved,
|
|
@@ -83,9 +84,10 @@ function finalizeRootFileOpen(params) {
|
|
|
83
84
|
}
|
|
84
85
|
export async function openRootFile(params) {
|
|
85
86
|
const ioFs = params.ioFs ?? fs;
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
const absolutePath = path.resolve(params.absolutePath);
|
|
88
|
+
let resolved;
|
|
89
|
+
try {
|
|
90
|
+
resolved = mapResolvedRootPath(absolutePath, await resolveRootPath({
|
|
89
91
|
absolutePath,
|
|
90
92
|
rootPath: params.rootPath,
|
|
91
93
|
rootCanonicalPath: params.rootRealPath,
|
|
@@ -93,9 +95,11 @@ export async function openRootFile(params) {
|
|
|
93
95
|
policy: params.aliasPolicy,
|
|
94
96
|
rejectSymlinks: params.rejectSymlinks ?? true,
|
|
95
97
|
skipLexicalRootCheck: params.skipLexicalRootCheck,
|
|
96
|
-
})
|
|
97
|
-
}
|
|
98
|
-
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
resolved = toBoundaryValidationError(error);
|
|
102
|
+
}
|
|
99
103
|
return finalizeRootFileOpen({
|
|
100
104
|
resolved,
|
|
101
105
|
maxBytes: params.maxBytes,
|
|
@@ -114,18 +118,3 @@ function mapResolvedRootPath(absolutePath, resolved) {
|
|
|
114
118
|
rootRealPath: resolved.rootCanonicalPath,
|
|
115
119
|
};
|
|
116
120
|
}
|
|
117
|
-
function resolveRootFilePathGeneric(params) {
|
|
118
|
-
const absolutePath = path.resolve(params.absolutePath);
|
|
119
|
-
try {
|
|
120
|
-
const resolved = params.resolve(absolutePath);
|
|
121
|
-
if (resolved instanceof Promise) {
|
|
122
|
-
return resolved
|
|
123
|
-
.then((value) => mapResolvedRootPath(absolutePath, value))
|
|
124
|
-
.catch((error) => toBoundaryValidationError(error));
|
|
125
|
-
}
|
|
126
|
-
return mapResolvedRootPath(absolutePath, resolved);
|
|
127
|
-
}
|
|
128
|
-
catch (error) {
|
|
129
|
-
return toBoundaryValidationError(error);
|
|
130
|
-
}
|
|
131
|
-
}
|
package/dist/root-impl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,KAAK,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAW7D,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,KAAK,oBAAoB,EAG1B,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAI9E,OAAO,EASL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAa3B,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,KAAK,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAW7D,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,KAAK,oBAAoB,EAG1B,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAI9E,OAAO,EASL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAa3B,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAOpF,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,kCAAkC,EAAE,MAAM,sBAAsB,CAAC;AAC1E,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,oBAAoB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;IACZ,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,oBAAoB,CAAC;AAC5D,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,CAAC;AAChD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/D,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,YAAY,EACZ,WAAW,GAAG,UAAU,GAAG,iBAAiB,GAAG,UAAU,CAC1D,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;AAEhE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,gBAAgB,CAAC,GAAG;IACzG,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,OAAO,GAAG,MAAM,CAAC,GAAG;IAC7F,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC,GAAG;IAClG,eAAe,CAAC,EAAE,cAAc,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG;IACpD,QAAQ,CAAC,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;AACpE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;AAE5E,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG;IACjD,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG;IAClE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;AACpE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;AA+BnE,eAAO,MAAM,sBAAsB,QAAmB,CAAC;AA4JvD,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAEhC,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3E,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3E,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5E,QAAQ,CACN,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,eAAe,GAAG;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAE,GACxD,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,eAAe,GAAG;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAE,GACxD,OAAO,CAAC,CAAC,CAAC,CAAC;IACd,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/E,MAAM,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACzE,YAAY,CACV,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC/B,MAAM,CACJ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,UAAU,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,KAAK,CACH,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,MAAM,CACJ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,SAAS,CACP,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,UAAU,CACR,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3F,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACnF,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,aAAa,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAClF,IAAI,CACF,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAC;CAC5F;AAED,qBAAa,UAAW,YAAW,IAAI;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA8B;IAC3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAEhC,YAAY,OAAO,EAAE,WAAW,EAAE,QAAQ,GAAE,YAAiB,EAM5D;IAED,OAAO,KAAK,OAAO,GAOlB;IAED,OAAO,CAAC,eAAe;IAUjB,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKnD;IAEK,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CAMnF;IAEK,IAAI,CACR,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,UAAU,CAAC,CAKrB;IAEK,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAEpF;IAEK,QAAQ,CACZ,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,eAAe,GAAG;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAO,GAC5D,OAAO,CAAC,MAAM,CAAC,CAGjB;IAEK,QAAQ,CAAC,CAAC,GAAG,OAAO,EACxB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,eAAe,GAAG;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAO,GAC5D,OAAO,CAAC,CAAC,CAAC,CAEZ;IAEK,YAAY,CAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,UAAU,CAAC,CAKrB;IAED,MAAM,CAAC,OAAO,GAAE,eAAoB,cACV,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC,CAGjD;IAEK,YAAY,CAChB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,kBAAkB,CAAC,CAW7B;IAEK,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CASxG;IAEK,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjF;IAEK,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E;IAEK,UAAU,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9D;IAEK,KAAK,CACT,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAUf;IAEK,MAAM,CACV,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAUf;IAEK,SAAS,CACb,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,EACb,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAIf;IAEK,UAAU,CACd,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,EACb,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAIf;IAEK,MAAM,CACV,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAWf;IAEK,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUnD;IAEK,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAIlD;IAEK,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACnF,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,aAAa,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAUlF,IAAI,CACR,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAgBf;IACD,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAGzF;CACF;AAiBD,wBAAsB,IAAI,CACxB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,YAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAGf;AAoED,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,UAAU,CAAC,CAQtB;AAED,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAG3F;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,oBAAoB,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;IACZ,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC"}
|
package/dist/root-impl.js
CHANGED
|
@@ -5,7 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
6
6
|
import { assertAsyncDirectoryGuard, createAsyncDirectoryGuard, createNearestExistingDirectoryGuard } from "./directory-guard.js";
|
|
7
7
|
import { FsSafeError } from "./errors.js";
|
|
8
|
-
import { syncDirectoryBestEffort } from "./
|
|
8
|
+
import { syncDirectoryBestEffort } from "./directory-durability.js";
|
|
9
9
|
import { sameFileIdentity, sameFileIdentityForCleanup, } from "./file-identity.js";
|
|
10
10
|
import { mkdirPathComponentsWithGuards } from "./guarded-mkdir.js";
|
|
11
11
|
import { withAsyncDirectoryGuards } from "./guarded-mutation.js";
|
|
@@ -29,6 +29,7 @@ import { walkRoot } from "./root-walk.js";
|
|
|
29
29
|
import { registerTempPathForExit } from "./temp-cleanup.js";
|
|
30
30
|
import { serializePathWrite } from "./write-queue.js";
|
|
31
31
|
import { verifyAtomicWriteResult } from "./root-write-verification.js";
|
|
32
|
+
import { inheritWriteTargetMode } from "./root-write-mode.js";
|
|
32
33
|
import { inspectFileIdentity } from "./strict-file-identity.js";
|
|
33
34
|
export { resolveOpenedFileRealPathForHandle } from "./opened-realpath.js";
|
|
34
35
|
function logWarn(message) {
|
|
@@ -163,15 +164,20 @@ async function openVerifiedLocalFile(filePath, options) {
|
|
|
163
164
|
return pathStat;
|
|
164
165
|
});
|
|
165
166
|
await fsSafeTestHooks?.afterOpenedPathIdentityCheck?.(filePath, handle);
|
|
166
|
-
const
|
|
167
|
+
const resolved = await resolveOpenedFileRealPathForFd(handle.fd, identity, filePath)
|
|
167
168
|
.catch(async (error) => {
|
|
168
169
|
if (stat.nlink <= 1 && (!preOpenStat || preOpenStat.nlink <= 1n)) {
|
|
169
170
|
await recordOpenedFileFailure(error, handle, filePath, identity);
|
|
170
171
|
}
|
|
171
172
|
throw error;
|
|
172
173
|
});
|
|
174
|
+
const { realPath } = resolved;
|
|
175
|
+
let resolvedStat = resolved.stat;
|
|
173
176
|
await inspectPathIdentity(async () => {
|
|
174
|
-
|
|
177
|
+
// Reuse the post-realpath observation; unknown Windows identities still
|
|
178
|
+
// get a fresh observation on inspectFileIdentity's retry.
|
|
179
|
+
const realStat = resolvedStat ?? await fs.stat(realPath, { bigint: true });
|
|
180
|
+
resolvedStat = undefined;
|
|
175
181
|
if (options?.hardlinks === "reject" && realStat.nlink > 1n) {
|
|
176
182
|
throw hardlinkedPathNotAllowedError();
|
|
177
183
|
}
|
|
@@ -384,7 +390,6 @@ function readDefaults(defaults) {
|
|
|
384
390
|
return {
|
|
385
391
|
hardlinks: defaults.hardlinks,
|
|
386
392
|
maxBytes: normalizeMaxBytes(defaults.maxBytes, { defaultValue: DEFAULT_ROOT_MAX_BYTES }),
|
|
387
|
-
nonBlockingRead: defaults.nonBlockingRead,
|
|
388
393
|
symlinks: defaults.symlinks,
|
|
389
394
|
};
|
|
390
395
|
}
|
|
@@ -393,8 +398,6 @@ function mergeReadOptions(defaults, options) {
|
|
|
393
398
|
if (options.hardlinks !== undefined)
|
|
394
399
|
merged.hardlinks = options.hardlinks;
|
|
395
400
|
merged.maxBytes = normalizeMaxBytes(options.maxBytes, { defaultValue: merged.maxBytes });
|
|
396
|
-
if (options.nonBlockingRead !== undefined)
|
|
397
|
-
merged.nonBlockingRead = options.nonBlockingRead;
|
|
398
401
|
if (options.symlinks !== undefined)
|
|
399
402
|
merged.symlinks = options.symlinks;
|
|
400
403
|
return merged;
|
|
@@ -410,7 +413,6 @@ async function openFileInRoot(root, params) {
|
|
|
410
413
|
rejectSymlinks: params.symlinks !== "follow-within-root",
|
|
411
414
|
});
|
|
412
415
|
const { opened } = await openVerifiedLocalFile(resolved, {
|
|
413
|
-
nonBlockingRead: params.nonBlockingRead,
|
|
414
416
|
symlinks: params.symlinks,
|
|
415
417
|
});
|
|
416
418
|
if (params.hardlinks !== "allow" && opened.stat.nlink > 1) {
|
|
@@ -438,7 +440,6 @@ async function readPathInRoot(root, params) {
|
|
|
438
440
|
relativePath,
|
|
439
441
|
hardlinks: params.hardlinks,
|
|
440
442
|
maxBytes: params.maxBytes,
|
|
441
|
-
nonBlockingRead: params.nonBlockingRead,
|
|
442
443
|
symlinks: params.symlinks,
|
|
443
444
|
});
|
|
444
445
|
}
|
|
@@ -858,31 +859,9 @@ async function resolvePinnedWriteTargetInRoot(root, relativePath, requestedMode,
|
|
|
858
859
|
throw error;
|
|
859
860
|
}
|
|
860
861
|
}
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
const opened = await openFileInRoot(root, {
|
|
865
|
-
relativePath,
|
|
866
|
-
hardlinks: "reject",
|
|
867
|
-
nonBlockingRead: true,
|
|
868
|
-
symlinks: "follow-within-root",
|
|
869
|
-
});
|
|
870
|
-
try {
|
|
871
|
-
mode = requestedMode ?? (opened.stat.mode & 0o777);
|
|
872
|
-
if (!isPathInside(rootWithSep, opened.realPath)) {
|
|
873
|
-
throw outsideWorkspaceError();
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
finally {
|
|
877
|
-
await opened.handle.close().catch(() => { });
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
catch (err) {
|
|
882
|
-
if (!(err instanceof FsSafeError) || err.code !== "not-found") {
|
|
883
|
-
throw err;
|
|
884
|
-
}
|
|
885
|
-
}
|
|
862
|
+
const mode = overwrite
|
|
863
|
+
? await inheritWriteTargetMode({ targetPath: resolved, rootWithSep, requestedMode })
|
|
864
|
+
: requestedMode ?? 0o600;
|
|
886
865
|
return {
|
|
887
866
|
rootReal,
|
|
888
867
|
targetPath: resolved,
|
package/dist/root-path.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-path.d.ts","sourceRoot":"","sources":["../src/root-path.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"root-path.d.ts","sourceRoot":"","sources":["../src/root-path.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,kCAAkC,EAAE,MAAM,yBAAyB,CAAC;AAE7E,KAAK,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtE,MAAM,MAAM,mBAAmB,GAAG;IAChC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC,CAAC;AAEF,eAAO,MAAM,wBAAwB;aACnC,MAAM;;;;aAIN,YAAY;;;;CAIJ,CAAC;AAEX,KAAK,qBAAqB,GAAG;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,KAAK,oBAAoB,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,oBAAoB,CAAC;CAC5B,CAAC;AAEF,wBAAsB,eAAe,CACnC,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAM3B;AAsCD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,qBAAqB,GAAG,gBAAgB,CAMnF"}
|
package/dist/root-path.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import fsp from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { formatErrorDetail } from "./error-detail.js";
|
|
4
|
+
import { formatErrorDetail, shortPath } from "./error-detail.js";
|
|
5
5
|
import { FsSafeError } from "./errors.js";
|
|
6
6
|
import { assertNoNulPathInput, isNotFoundPathError, isPathInside, isPathRelativeEscape, } from "./path.js";
|
|
7
7
|
import { resolvePathViaExistingAncestor, resolvePathViaExistingAncestorSync, } from "./root-path-existing.js";
|
|
8
8
|
import { resolveSymlinkHopPath, resolveSymlinkHopPathSync } from "./root-path-symlink.js";
|
|
9
9
|
import { assertNoDriveRelativePathSegments } from "./safe-path-segment.js";
|
|
10
|
-
import { shortPath } from "./short-path.js";
|
|
11
10
|
export { resolvePathViaExistingAncestorSync } from "./root-path-existing.js";
|
|
12
11
|
export const ROOT_PATH_ALIAS_POLICIES = {
|
|
13
12
|
strict: Object.freeze({
|
|
@@ -120,12 +119,6 @@ function assertNoEmbeddedDriveRelativeSegment(filePath, label) {
|
|
|
120
119
|
const root = path.parse(filePath).root;
|
|
121
120
|
assertNoDriveRelativePathSegments(filePath.slice(root.length).replaceAll("\\", "/"), label);
|
|
122
121
|
}
|
|
123
|
-
function isPromiseLike(value) {
|
|
124
|
-
return Boolean(value &&
|
|
125
|
-
(typeof value === "object" || typeof value === "function") &&
|
|
126
|
-
"then" in value &&
|
|
127
|
-
typeof value.then === "function");
|
|
128
|
-
}
|
|
129
122
|
function createLexicalTraversalState(params) {
|
|
130
123
|
const rawAbsolutePath = params.params.absolutePath;
|
|
131
124
|
const rawRelativePath = rawPathRelativeToRoot(params.rootPath, rawAbsolutePath);
|
|
@@ -205,26 +198,13 @@ function handleLexicalLstatFailure(context, error, missingFromIndex) {
|
|
|
205
198
|
applyMissingSuffixToCanonicalCursor(context, missingFromIndex);
|
|
206
199
|
return true;
|
|
207
200
|
}
|
|
208
|
-
function
|
|
209
|
-
if (
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
212
|
-
throw error;
|
|
213
|
-
}
|
|
214
|
-
function handleLexicalStatDisposition(context, params) {
|
|
215
|
-
if (!params.isSymbolicLink) {
|
|
216
|
-
advanceCanonicalCursorForSegment(context, params.segment);
|
|
201
|
+
function lexicalStatDisposition(params) {
|
|
202
|
+
if (!params.isSymbolicLink)
|
|
217
203
|
return "continue";
|
|
218
|
-
|
|
219
|
-
if (context.resolveParams.rejectSymlinks === true && params.isLast) {
|
|
204
|
+
if (params.rejectSymlinks === true && params.isLast) {
|
|
220
205
|
throw new FsSafeError("symlink", "symlink path component not allowed");
|
|
221
206
|
}
|
|
222
|
-
|
|
223
|
-
context.state.preserveFinalSymlink = true;
|
|
224
|
-
advanceCanonicalCursorForSegment(context, params.segment);
|
|
225
|
-
return "break";
|
|
226
|
-
}
|
|
227
|
-
return "resolve-link";
|
|
207
|
+
return params.allowFinalSymlink && params.isLast ? "break" : "resolve-link";
|
|
228
208
|
}
|
|
229
209
|
function applyResolvedSymlinkHop(context, linkCanonical) {
|
|
230
210
|
if (!isPathInside(context.rootCanonicalPath, linkCanonical)) {
|
|
@@ -237,70 +217,48 @@ function applyResolvedSymlinkHop(context, linkCanonical) {
|
|
|
237
217
|
context.state.canonicalCursor = linkCanonical;
|
|
238
218
|
context.state.lexicalCursor = linkCanonical;
|
|
239
219
|
}
|
|
240
|
-
function readLexicalStat(context, params) {
|
|
241
|
-
try {
|
|
242
|
-
const stat = params.read(context.state.lexicalCursor);
|
|
243
|
-
if (isPromiseLike(stat)) {
|
|
244
|
-
return Promise.resolve(stat).catch((error) => handleLexicalStatReadFailure(context, error, params.missingFromIndex));
|
|
245
|
-
}
|
|
246
|
-
return stat;
|
|
247
|
-
}
|
|
248
|
-
catch (error) {
|
|
249
|
-
return handleLexicalStatReadFailure(context, error, params.missingFromIndex);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
function resolveAndApplySymlinkHop(context, params) {
|
|
253
|
-
const linkCanonical = params.resolveLinkCanonical(context.state.lexicalCursor);
|
|
254
|
-
if (isPromiseLike(linkCanonical)) {
|
|
255
|
-
return Promise.resolve(linkCanonical).then((value) => {
|
|
256
|
-
applyResolvedSymlinkHop(context, value);
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
applyResolvedSymlinkHop(context, linkCanonical);
|
|
260
|
-
}
|
|
261
220
|
function applyParentTraversalStep(context) {
|
|
262
221
|
context.state.lexicalCursor = path.resolve(context.state.lexicalCursor, "..");
|
|
263
222
|
advanceCanonicalCursorForSegment(context, "..");
|
|
264
223
|
}
|
|
265
|
-
function* iterateLexicalTraversal(state) {
|
|
266
|
-
for (let idx = 0; idx < state.segments.length; idx += 1) {
|
|
267
|
-
const segment = state.segments[idx] ?? "";
|
|
268
|
-
const isLast = idx === state.segments.length - 1;
|
|
269
|
-
yield { idx, segment, isLast };
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
224
|
async function resolveRootPathLexicalAsync(params) {
|
|
273
225
|
const context = createLexicalTraversalContext(params);
|
|
274
226
|
const { state } = context;
|
|
275
|
-
for (
|
|
227
|
+
for (let idx = 0; idx < state.segments.length; idx += 1) {
|
|
228
|
+
const segment = state.segments[idx] ?? "";
|
|
229
|
+
const isLast = idx === state.segments.length - 1;
|
|
276
230
|
if (segment === "..") {
|
|
277
231
|
applyParentTraversalStep(context);
|
|
278
232
|
continue;
|
|
279
233
|
}
|
|
280
234
|
state.lexicalCursor = path.join(state.lexicalCursor, segment);
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
});
|
|
285
|
-
if (!stat) {
|
|
286
|
-
break;
|
|
235
|
+
let stat;
|
|
236
|
+
try {
|
|
237
|
+
stat = await fsp.lstat(state.lexicalCursor);
|
|
287
238
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
239
|
+
catch (error) {
|
|
240
|
+
if (handleLexicalLstatFailure(context, error, idx))
|
|
241
|
+
break;
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
const isSymbolicLink = stat.isSymbolicLink();
|
|
245
|
+
const disposition = lexicalStatDisposition({
|
|
246
|
+
isSymbolicLink,
|
|
291
247
|
isLast,
|
|
248
|
+
rejectSymlinks: isSymbolicLink ? context.resolveParams.rejectSymlinks : undefined,
|
|
249
|
+
allowFinalSymlink: state.allowFinalSymlink,
|
|
292
250
|
});
|
|
293
|
-
if (disposition
|
|
251
|
+
if (disposition !== "resolve-link") {
|
|
252
|
+
state.preserveFinalSymlink = disposition === "break";
|
|
253
|
+
advanceCanonicalCursorForSegment(context, segment);
|
|
254
|
+
if (state.preserveFinalSymlink)
|
|
255
|
+
break;
|
|
294
256
|
continue;
|
|
295
257
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
299
|
-
await resolveAndApplySymlinkHop(context, {
|
|
300
|
-
resolveLinkCanonical: (cursor) => resolveSymlinkHopPath(cursor, {
|
|
301
|
-
rejectUnresolved: context.resolveParams.rejectUnresolvedSymlinks,
|
|
302
|
-
}),
|
|
258
|
+
const linkCanonical = await resolveSymlinkHopPath(state.lexicalCursor, {
|
|
259
|
+
rejectUnresolved: context.resolveParams.rejectUnresolvedSymlinks,
|
|
303
260
|
});
|
|
261
|
+
applyResolvedSymlinkHop(context, linkCanonical);
|
|
304
262
|
if (context.resolveParams.rejectSymlinks === true) {
|
|
305
263
|
throw new FsSafeError("symlink", "symlink path component not allowed");
|
|
306
264
|
}
|
|
@@ -319,36 +277,33 @@ function resolveRootPathLexicalSync(params) {
|
|
|
319
277
|
continue;
|
|
320
278
|
}
|
|
321
279
|
state.lexicalCursor = path.join(state.lexicalCursor, segment);
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
});
|
|
326
|
-
if (isPromiseLike(maybeStat)) {
|
|
327
|
-
throw new Error("Unexpected async lexical stat");
|
|
280
|
+
let stat;
|
|
281
|
+
try {
|
|
282
|
+
stat = fs.lstatSync(state.lexicalCursor);
|
|
328
283
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
284
|
+
catch (error) {
|
|
285
|
+
if (handleLexicalLstatFailure(context, error, idx))
|
|
286
|
+
break;
|
|
287
|
+
throw error;
|
|
332
288
|
}
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
289
|
+
const isSymbolicLink = stat.isSymbolicLink();
|
|
290
|
+
const disposition = lexicalStatDisposition({
|
|
291
|
+
isSymbolicLink,
|
|
336
292
|
isLast,
|
|
293
|
+
rejectSymlinks: isSymbolicLink ? context.resolveParams.rejectSymlinks : undefined,
|
|
294
|
+
allowFinalSymlink: state.allowFinalSymlink,
|
|
337
295
|
});
|
|
338
|
-
if (disposition
|
|
296
|
+
if (disposition !== "resolve-link") {
|
|
297
|
+
state.preserveFinalSymlink = disposition === "break";
|
|
298
|
+
advanceCanonicalCursorForSegment(context, segment);
|
|
299
|
+
if (state.preserveFinalSymlink)
|
|
300
|
+
break;
|
|
339
301
|
continue;
|
|
340
302
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
}
|
|
344
|
-
const maybeApplied = resolveAndApplySymlinkHop(context, {
|
|
345
|
-
resolveLinkCanonical: (cursor) => resolveSymlinkHopPathSync(cursor, {
|
|
346
|
-
rejectUnresolved: context.resolveParams.rejectUnresolvedSymlinks,
|
|
347
|
-
}),
|
|
303
|
+
const linkCanonical = resolveSymlinkHopPathSync(state.lexicalCursor, {
|
|
304
|
+
rejectUnresolved: context.resolveParams.rejectUnresolvedSymlinks,
|
|
348
305
|
});
|
|
349
|
-
|
|
350
|
-
throw new Error("Unexpected async symlink resolution");
|
|
351
|
-
}
|
|
306
|
+
applyResolvedSymlinkHop(context, linkCanonical);
|
|
352
307
|
if (context.resolveParams.rejectSymlinks === true) {
|
|
353
308
|
throw new FsSafeError("symlink", "symlink path component not allowed");
|
|
354
309
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-write-mode.d.ts","sourceRoot":"","sources":["../src/root-write-mode.ts"],"names":[],"mappings":"AASA,wBAAsB,sBAAsB,CAAC,MAAM,EAAE;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwClB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { FsSafeError } from "./errors.js";
|
|
3
|
+
import { sameFileIdentity } from "./file-identity.js";
|
|
4
|
+
import { isNotFoundPathError, isPathInside } from "./path.js";
|
|
5
|
+
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
6
|
+
import { hardlinkedPathNotAllowedError, outsideWorkspaceError } from "./root-errors.js";
|
|
7
|
+
import { inspectFileIdentity } from "./strict-file-identity.js";
|
|
8
|
+
// The caller has already resolved and guarded this write target.
|
|
9
|
+
export async function inheritWriteTargetMode(params) {
|
|
10
|
+
try {
|
|
11
|
+
const existing = await inspectFileIdentity(() => fs.lstat(params.targetPath, { bigint: true }));
|
|
12
|
+
if (existing.isSymbolicLink())
|
|
13
|
+
throw new FsSafeError("path-alias", "path alias escape blocked");
|
|
14
|
+
if (!existing.isFile())
|
|
15
|
+
throw new FsSafeError("not-file", "not a file");
|
|
16
|
+
if (existing.nlink > 1n)
|
|
17
|
+
throw hardlinkedPathNotAllowedError();
|
|
18
|
+
if (!isPathInside(params.rootWithSep, params.targetPath))
|
|
19
|
+
throw outsideWorkspaceError();
|
|
20
|
+
// Preserve read-open admission of the pre-existing destination. access(2)
|
|
21
|
+
// is not equivalent: it ignores ACLs on Windows and capabilities on Linux.
|
|
22
|
+
const handle = await fs.open(params.targetPath, resolveReadOpenFlags());
|
|
23
|
+
try {
|
|
24
|
+
// Bind admission to the inode whose metadata is inherited.
|
|
25
|
+
if (!sameFileIdentity(await handle.stat({ bigint: true }), existing)) {
|
|
26
|
+
throw new FsSafeError("path-mismatch", "write target changed during mode inheritance");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await handle.close().catch(() => undefined);
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
// A parent can change after guarded resolution. Do not inherit metadata
|
|
34
|
+
// from an outside inode, even if the parent is restored before publication.
|
|
35
|
+
const realPath = await fs.realpath(params.targetPath);
|
|
36
|
+
if (!isPathInside(params.rootWithSep, realPath))
|
|
37
|
+
throw outsideWorkspaceError();
|
|
38
|
+
await inspectFileIdentity(async () => {
|
|
39
|
+
const current = await fs.stat(realPath, { bigint: true });
|
|
40
|
+
if (!current.isFile())
|
|
41
|
+
throw new FsSafeError("not-file", "not a file");
|
|
42
|
+
if (current.nlink > 1n)
|
|
43
|
+
throw hardlinkedPathNotAllowedError();
|
|
44
|
+
return current;
|
|
45
|
+
}, existing);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (isNotFoundPathError(error)) {
|
|
49
|
+
throw new FsSafeError("path-mismatch", "write target changed during mode inheritance", { cause: error });
|
|
50
|
+
}
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
return params.requestedMode ?? Number(existing.mode & 511n);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (!isNotFoundPathError(error))
|
|
57
|
+
throw error;
|
|
58
|
+
return params.requestedMode ?? 0o600;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -47,7 +47,7 @@ export async function verifyAtomicWriteResult(params) {
|
|
|
47
47
|
// This descriptor remains owned by the writer, even when final mode forbids opens.
|
|
48
48
|
const stat = assertDescriptor();
|
|
49
49
|
assertPath(await fs.lstat(params.targetPath, { bigint: true }));
|
|
50
|
-
const realPath = await resolveOpenedFileRealPathForFd(params.fd, stat, params.targetPath);
|
|
50
|
+
const { realPath } = await resolveOpenedFileRealPathForFd(params.fd, stat, params.targetPath);
|
|
51
51
|
assertPath(await fs.stat(realPath, { bigint: true }));
|
|
52
52
|
if (!isPathInside(params.root.rootWithSep, realPath)) {
|
|
53
53
|
throw outsideWorkspaceError();
|
|
@@ -74,7 +74,7 @@ export async function verifyAtomicWriteResult(params) {
|
|
|
74
74
|
try {
|
|
75
75
|
const reopenedStat = assertDescriptor(opened.fd);
|
|
76
76
|
assertPath(await fs.lstat(params.targetPath, { bigint: true }));
|
|
77
|
-
const reopenedPath = await resolveOpenedFileRealPathForFd(opened.fd, reopenedStat, params.targetPath);
|
|
77
|
+
const { realPath: reopenedPath } = await resolveOpenedFileRealPathForFd(opened.fd, reopenedStat, params.targetPath);
|
|
78
78
|
assertPath(await fs.stat(reopenedPath, { bigint: true }));
|
|
79
79
|
if (!isPathInside(params.root.rootWithSep, reopenedPath)) {
|
|
80
80
|
throw outsideWorkspaceError();
|
|
@@ -4,6 +4,7 @@ export type SafePathSegmentOptions = {
|
|
|
4
4
|
};
|
|
5
5
|
export declare function isDriveRelativePath(value: string): boolean;
|
|
6
6
|
export declare function assertNoDriveRelativePathSegments(value: string, label: string): string;
|
|
7
|
+
export declare function trimHyphenEdges(value: string): string;
|
|
7
8
|
export declare function isSafePathSegment(segment: string, options?: SafePathSegmentOptions): boolean;
|
|
8
9
|
export declare function assertSafePathSegment(segment: string, options?: SafePathSegmentOptions): string;
|
|
9
10
|
export declare function sanitizeSafePathSegment(value: string, fallback: string, options?: SafePathSegmentOptions): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-path-segment.d.ts","sourceRoot":"","sources":["../src/safe-path-segment.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,sBAAsB,GAAG;IACnC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtF;
|
|
1
|
+
{"version":3,"file":"safe-path-segment.d.ts","sourceRoot":"","sources":["../src/safe-path-segment.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,sBAAsB,GAAG;IACnC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUrD;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAaT;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,sBAA2B,GACnC,MAAM,CAUR;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,sBAA2B,GACnC,MAAM,CAWR;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,sBAA2B,GACnC,MAAM,CAeR"}
|
|
@@ -14,7 +14,7 @@ export function assertNoDriveRelativePathSegments(value, label) {
|
|
|
14
14
|
}
|
|
15
15
|
return value;
|
|
16
16
|
}
|
|
17
|
-
function trimHyphenEdges(value) {
|
|
17
|
+
export function trimHyphenEdges(value) {
|
|
18
18
|
let start = 0;
|
|
19
19
|
let end = value.length;
|
|
20
20
|
while (start < end && value.charCodeAt(start) === HYPHEN_CHAR_CODE) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-file.d.ts","sourceRoot":"","sources":["../src/secret-file.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"secret-file.d.ts","sourceRoot":"","sources":["../src/secret-file.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAK/C,OAAO,EAAkF,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAUhJ,OAAO,EAML,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAIjC,eAAO,MAAM,uBAAuB,MAAQ,CAAC;AAC7C,eAAO,MAAM,wBAAwB,MAAQ,CAAC;AAE9C,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,MAAM,CAkER;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,MAAM,GAAG,SAAS,CAUpB;AA8JD,KAAK,qBAAqB,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAYF,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,IAAI,CAAC,qBAAqB,EAAE,SAAS,CAAC,GAC7C,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC5C,WAAW,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAuBD;AAuDD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKxF;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAezF"}
|
package/dist/secret-file.js
CHANGED
|
@@ -3,7 +3,6 @@ import fsp from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { canonicalPathFromExistingAncestor } from "./absolute-path.js";
|
|
5
5
|
import { readFileDescriptorBoundedSync } from "./bounded-read.js";
|
|
6
|
-
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
7
6
|
import { assertAsyncDirectoryGuard, createAsyncDirectoryGuard, inspectDirectoryIdentity } from "./directory-guard.js";
|
|
8
7
|
import { pinNodeDirectoryForMode } from "./directory-mode-node.js";
|
|
9
8
|
import { assertOwnedDirectory } from "./directory-mode-owner.js";
|
|
@@ -14,19 +13,13 @@ import { openPinnedFileSync } from "./pinned-open.js";
|
|
|
14
13
|
import { runPinnedWriteHelper } from "./pinned-write.js";
|
|
15
14
|
import { ensureTrailingSep } from "./root-context.js";
|
|
16
15
|
import { verifyAtomicWriteResult } from "./root-write-verification.js";
|
|
17
|
-
import { assertSecretFilePreview,
|
|
16
|
+
import { assertSecretFilePreview, resolveSecretReadPolicy, secretPathErrorCode, secretReadError, trimSecretFileContent, } from "./secret-read-policy.js";
|
|
18
17
|
import { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
19
18
|
import { serializePathWrite } from "./write-queue.js";
|
|
20
19
|
export const PRIVATE_SECRET_DIR_MODE = 0o700;
|
|
21
20
|
export const PRIVATE_SECRET_FILE_MODE = 0o600;
|
|
22
21
|
export function readSecretFileSync(filePath, label, options = {}) {
|
|
23
|
-
const resolvedPath =
|
|
24
|
-
if (!resolvedPath) {
|
|
25
|
-
throw new FsSafeError("invalid-path", `${label} file path is empty.`, { cause: undefined });
|
|
26
|
-
}
|
|
27
|
-
const maxBytes = normalizeMaxBytes(options.maxBytes, {
|
|
28
|
-
defaultValue: DEFAULT_SECRET_FILE_MAX_BYTES,
|
|
29
|
-
});
|
|
22
|
+
const { resolvedPath, maxBytes } = resolveSecretReadPolicy(filePath, label, options);
|
|
30
23
|
function inspectInput(symlinkMessage) {
|
|
31
24
|
const stat = options.rejectSymlink
|
|
32
25
|
? fs.lstatSync(resolvedPath, { bigint: true })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-read-async.d.ts","sourceRoot":"","sources":["../src/secret-read-async.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"secret-read-async.d.ts","sourceRoot":"","sources":["../src/secret-read-async.ts"],"names":[],"mappings":"AAOA,OAAO,EAML,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAEjC,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,CAAC,CA0DjB;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQ7B"}
|