@openclaw/fs-safe 0.10.0 → 0.12.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/CHANGELOG.md +114 -0
- package/LICENSE +1 -0
- package/README.md +39 -6
- package/dist/absolute-path.d.ts.map +1 -1
- package/dist/absolute-path.js +3 -2
- package/dist/advanced.d.ts +5 -1
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +5 -1
- package/dist/archive-durability.d.ts +6 -6
- package/dist/archive-durability.d.ts.map +1 -1
- package/dist/archive-durability.js +1 -1
- package/dist/archive-entry.d.ts.map +1 -1
- package/dist/archive-entry.js +8 -8
- package/dist/archive-gzip-tail.d.ts +1 -0
- package/dist/archive-gzip-tail.d.ts.map +1 -1
- package/dist/archive-gzip-tail.js +16 -9
- package/dist/archive-input.d.ts.map +1 -1
- package/dist/archive-input.js +4 -2
- package/dist/archive-merge.d.ts +5 -1
- package/dist/archive-merge.d.ts.map +1 -1
- package/dist/archive-merge.js +15 -12
- package/dist/archive-native.js +4 -4
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +54 -42
- package/dist/archive-staging.d.ts +6 -3
- package/dist/archive-staging.d.ts.map +1 -1
- package/dist/archive-staging.js +42 -22
- package/dist/archive-tar-stream.d.ts.map +1 -1
- package/dist/archive-tar-stream.js +7 -6
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +16 -13
- package/dist/archive-zip-admission.d.ts +1 -1
- package/dist/archive-zip-admission.d.ts.map +1 -1
- package/dist/archive-zip-admission.js +48 -12
- package/dist/archive-zip-loader.d.ts +6 -0
- package/dist/archive-zip-loader.d.ts.map +1 -0
- package/dist/archive-zip-loader.js +38 -0
- package/dist/archive-zip-names.d.ts.map +1 -1
- package/dist/archive-zip-names.js +26 -9
- package/dist/archive-zip-preflight.d.ts +2 -3
- package/dist/archive-zip-preflight.d.ts.map +1 -1
- package/dist/archive-zip-preflight.js +2 -34
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +12 -10
- package/dist/bounded-read.d.ts +5 -0
- package/dist/bounded-read.d.ts.map +1 -1
- package/dist/bounded-read.js +18 -11
- package/dist/copy-file-input.d.ts +0 -1
- package/dist/copy-file-input.d.ts.map +1 -1
- package/dist/copy-file-input.js +4 -26
- package/dist/copy-tree-portable.d.ts.map +1 -1
- package/dist/copy-tree-portable.js +57 -26
- package/dist/copy.d.ts +1 -1
- package/dist/copy.d.ts.map +1 -1
- package/dist/copy.js +3 -1
- package/dist/device-path.d.ts.map +1 -1
- package/dist/device-path.js +5 -3
- package/dist/directory-durability.d.ts.map +1 -1
- package/dist/directory-durability.js +5 -4
- package/dist/directory-guard.d.ts +11 -1
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-guard.js +53 -11
- package/dist/durability.d.ts +1 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +1 -1
- package/dist/file-handle-transfer.d.ts +14 -0
- package/dist/file-handle-transfer.d.ts.map +1 -0
- package/dist/file-handle-transfer.js +64 -0
- package/dist/file-hash.d.ts +3 -0
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +99 -32
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +8 -4
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +7 -5
- package/dist/file-store-path.d.ts +3 -0
- package/dist/file-store-path.d.ts.map +1 -0
- package/dist/file-store-path.js +27 -0
- package/dist/file-store-prune.d.ts.map +1 -1
- package/dist/file-store-prune.js +15 -5
- package/dist/file-store-sync-write.d.ts.map +1 -1
- package/dist/file-store-sync-write.js +56 -44
- package/dist/file-store.d.ts.map +1 -1
- package/dist/file-store.js +2 -18
- package/dist/filename.d.ts +1 -0
- package/dist/filename.d.ts.map +1 -1
- package/dist/filename.js +32 -14
- package/dist/guarded-mkdir.d.ts +2 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +52 -16
- package/dist/guest-dispatch-python.d.ts +2 -0
- package/dist/guest-dispatch-python.d.ts.map +1 -0
- package/dist/guest-dispatch-python.js +117 -0
- package/dist/guest-native-python.d.ts +4 -0
- package/dist/guest-native-python.d.ts.map +1 -0
- package/dist/guest-native-python.js +135 -0
- package/dist/guest.d.ts +9 -0
- package/dist/guest.d.ts.map +1 -0
- package/dist/guest.js +421 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/install-path.d.ts +6 -0
- package/dist/install-path.d.ts.map +1 -1
- package/dist/install-path.js +16 -2
- package/dist/json-durable-queue-directory.js +3 -3
- package/dist/json-durable-queue-ownership.d.ts +2 -0
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +47 -3
- package/dist/json-durable-queue-read.d.ts +6 -0
- package/dist/json-durable-queue-read.d.ts.map +1 -0
- package/dist/json-durable-queue-read.js +59 -0
- package/dist/json-durable-queue.d.ts +1 -1
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +43 -84
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +2 -1
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +2 -1
- package/dist/move-path-stage.d.ts.map +1 -1
- package/dist/move-path-stage.js +2 -1
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +4 -3
- package/dist/mutation-authority.d.ts +1 -0
- package/dist/mutation-authority.d.ts.map +1 -1
- package/dist/mutation-authority.js +4 -4
- package/dist/native-binding.d.ts +14 -2
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +3 -2
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +2 -1
- package/dist/opened-realpath.d.ts.map +1 -1
- package/dist/opened-realpath.js +5 -4
- package/dist/output.d.ts +2 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +2 -0
- package/dist/overwrite-file-handle.d.ts +8 -0
- package/dist/overwrite-file-handle.d.ts.map +1 -0
- package/dist/overwrite-file-handle.js +42 -0
- package/dist/path-case.d.ts +7 -0
- package/dist/path-case.d.ts.map +1 -0
- package/dist/path-case.js +136 -0
- package/dist/path-scope-lexical.d.ts +14 -0
- package/dist/path-scope-lexical.d.ts.map +1 -0
- package/dist/path-scope-lexical.js +27 -0
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +22 -3
- package/dist/permissions-windows.d.ts +1 -1
- package/dist/permissions-windows.d.ts.map +1 -1
- package/dist/permissions-windows.js +48 -6
- package/dist/pinned-open.d.ts.map +1 -1
- package/dist/pinned-open.js +3 -1
- package/dist/pinned-write.d.ts +2 -2
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +3 -1
- package/dist/private-temp-workspace.d.ts.map +1 -1
- package/dist/private-temp-workspace.js +6 -4
- package/dist/realpath.d.ts +4 -0
- package/dist/realpath.d.ts.map +1 -0
- package/dist/realpath.js +43 -0
- package/dist/recursive-mkdir-path.d.ts +3 -0
- package/dist/recursive-mkdir-path.d.ts.map +1 -0
- package/dist/recursive-mkdir-path.js +8 -0
- package/dist/replace-directory.d.ts.map +1 -1
- package/dist/replace-directory.js +2 -1
- package/dist/replace-file-copy-fallback.d.ts.map +1 -1
- package/dist/replace-file-copy-fallback.js +23 -31
- package/dist/replace-file-copy-source.d.ts.map +1 -1
- package/dist/replace-file-copy-source.js +7 -12
- package/dist/replace-file-mode.d.ts +3 -0
- package/dist/replace-file-mode.d.ts.map +1 -0
- package/dist/replace-file-mode.js +10 -0
- package/dist/replace-file.d.ts +1 -0
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +14 -8
- package/dist/root-boundary.d.ts +25 -0
- package/dist/root-boundary.d.ts.map +1 -0
- package/dist/root-boundary.js +177 -0
- package/dist/root-context.d.ts.map +1 -1
- package/dist/root-context.js +40 -13
- package/dist/root-create-input.d.ts +10 -0
- package/dist/root-create-input.d.ts.map +1 -0
- package/dist/root-create-input.js +80 -0
- package/dist/root-directory-list.d.ts +3 -1
- package/dist/root-directory-list.d.ts.map +1 -1
- package/dist/root-directory-list.js +31 -5
- package/dist/root-entries.d.ts +11 -0
- package/dist/root-entries.d.ts.map +1 -0
- package/dist/root-entries.js +61 -0
- package/dist/root-errors.d.ts +5 -5
- package/dist/root-errors.d.ts.map +1 -1
- package/dist/root-errors.js +13 -12
- package/dist/root-impl.d.ts +13 -3
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +93 -70
- package/dist/root-move-preflight.d.ts +8 -0
- package/dist/root-move-preflight.d.ts.map +1 -0
- package/dist/root-move-preflight.js +16 -0
- package/dist/root-options.d.ts +12 -1
- package/dist/root-options.d.ts.map +1 -1
- package/dist/root-path-existing.d.ts +2 -0
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +14 -5
- package/dist/root-path-symlink.d.ts.map +1 -1
- package/dist/root-path-symlink.js +3 -2
- package/dist/root-path.d.ts +2 -0
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +54 -26
- package/dist/root-paths.d.ts +2 -6
- package/dist/root-paths.d.ts.map +1 -1
- package/dist/root-paths.js +24 -32
- package/dist/root-remove.d.ts +5 -0
- package/dist/root-remove.d.ts.map +1 -0
- package/dist/root-remove.js +286 -0
- package/dist/root-symlink-policy.d.ts +2 -1
- package/dist/root-symlink-policy.d.ts.map +1 -1
- package/dist/root-symlink-policy.js +2 -2
- package/dist/root-walk.d.ts.map +1 -1
- package/dist/root-walk.js +2 -1
- package/dist/root-write-mode.d.ts +2 -0
- package/dist/root-write-mode.d.ts.map +1 -1
- package/dist/root-write-mode.js +21 -7
- package/dist/root-write-verification.d.ts.map +1 -1
- package/dist/root-write-verification.js +12 -3
- package/dist/root.d.ts +2 -1
- package/dist/root.d.ts.map +1 -1
- package/dist/safe-path-segment.d.ts.map +1 -1
- package/dist/safe-path-segment.js +3 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +2 -1
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +2 -1
- package/dist/secure-file-windows.d.ts +10 -0
- package/dist/secure-file-windows.d.ts.map +1 -0
- package/dist/secure-file-windows.js +186 -0
- package/dist/secure-file.d.ts.map +1 -1
- package/dist/secure-file.js +27 -7
- package/dist/secure-temp-dir.d.ts.map +1 -1
- package/dist/secure-temp-dir.js +2 -1
- package/dist/sibling-staged-file.d.ts +2 -0
- package/dist/sibling-staged-file.d.ts.map +1 -1
- package/dist/sibling-staged-file.js +49 -8
- package/dist/sibling-temp.d.ts +2 -0
- package/dist/sibling-temp.d.ts.map +1 -1
- package/dist/sibling-temp.js +8 -5
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +16 -5
- package/dist/sidecar-lock-policy.d.ts +2 -0
- package/dist/sidecar-lock-policy.d.ts.map +1 -1
- package/dist/sidecar-lock-policy.js +17 -0
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +2 -3
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +4 -3
- package/dist/temp-target.d.ts +14 -12
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +15 -7
- package/dist/trash.d.ts.map +1 -1
- package/dist/trash.js +7 -5
- package/dist/unicode-path.d.ts +3 -0
- package/dist/unicode-path.d.ts.map +1 -0
- package/dist/unicode-path.js +13 -0
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +14 -12
- package/dist/write-file-handle.d.ts +1 -0
- package/dist/write-file-handle.d.ts.map +1 -1
- package/dist/write-file-handle.js +3 -2
- package/docs/advanced.md +7 -1
- package/docs/archive.md +31 -5
- package/docs/atomic.md +17 -1
- package/docs/config.md +1 -0
- package/docs/contributing.md +33 -2
- package/docs/copy.md +75 -6
- package/docs/directory-identity.md +85 -0
- package/docs/durability.md +40 -3
- package/docs/entries.md +109 -0
- package/docs/errors.md +3 -3
- package/docs/file-store.md +21 -0
- package/docs/filename.md +9 -2
- package/docs/guest.md +146 -0
- package/docs/in-place-write.md +81 -0
- package/docs/index.md +2 -0
- package/docs/install-path.md +59 -13
- package/docs/install.md +34 -0
- package/docs/native-helper.md +14 -5
- package/docs/native.md +18 -2
- package/docs/output.md +32 -6
- package/docs/path-case.md +64 -0
- package/docs/path-scope.md +1 -1
- package/docs/path.md +1 -1
- package/docs/permissions.md +37 -3
- package/docs/public-api.md +36 -2
- package/docs/root.md +33 -3
- package/docs/secure-file.md +17 -14
- package/docs/security-model.md +1 -1
- package/docs/sidecar-lock.md +12 -3
- package/docs/store.md +22 -1
- package/docs/temp.md +39 -6
- package/docs/types.md +1 -1
- package/docs/writing.md +153 -3
- package/package.json +14 -8
|
@@ -2,6 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { FsSafeError } from "./errors.js";
|
|
4
4
|
import { isNotFoundPathError, isSymlinkOpenError } from "./path.js";
|
|
5
|
+
import { realpathSync } from "./realpath.js";
|
|
5
6
|
import { resolvePathViaExistingAncestor, resolvePathViaExistingAncestorSync, } from "./root-path-existing.js";
|
|
6
7
|
function normalizeSymlinkResolutionError(error, options) {
|
|
7
8
|
if (isSymlinkOpenError(error) ||
|
|
@@ -15,7 +16,7 @@ function normalizeSymlinkResolutionError(error, options) {
|
|
|
15
16
|
}
|
|
16
17
|
export async function resolveSymlinkHopPath(symlinkPath, options = {}) {
|
|
17
18
|
try {
|
|
18
|
-
return path.resolve(
|
|
19
|
+
return path.resolve(realpathSync.native(symlinkPath));
|
|
19
20
|
}
|
|
20
21
|
catch (error) {
|
|
21
22
|
normalizeSymlinkResolutionError(error, options);
|
|
@@ -25,7 +26,7 @@ export async function resolveSymlinkHopPath(symlinkPath, options = {}) {
|
|
|
25
26
|
}
|
|
26
27
|
export function resolveSymlinkHopPathSync(symlinkPath, options = {}) {
|
|
27
28
|
try {
|
|
28
|
-
return path.resolve(
|
|
29
|
+
return path.resolve(realpathSync(symlinkPath));
|
|
29
30
|
}
|
|
30
31
|
catch (error) {
|
|
31
32
|
normalizeSymlinkResolutionError(error, options);
|
package/dist/root-path.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type RootBoundaryIdentity } from "./root-boundary.js";
|
|
1
2
|
export { resolvePathViaExistingAncestorSync } from "./root-path-existing.js";
|
|
2
3
|
type RootPathIntent = "read" | "write" | "create" | "delete" | "stat";
|
|
3
4
|
export type RootPathAliasPolicy = {
|
|
@@ -25,6 +26,7 @@ type ResolveRootPathParams = {
|
|
|
25
26
|
rejectUnresolvedSymlinks?: boolean;
|
|
26
27
|
skipLexicalRootCheck?: boolean;
|
|
27
28
|
rootCanonicalPath?: string;
|
|
29
|
+
rootIdentity?: RootBoundaryIdentity;
|
|
28
30
|
};
|
|
29
31
|
type ResolvedRootPathKind = "missing" | "file" | "directory" | "symlink" | "other";
|
|
30
32
|
export type ResolvedRootPath = {
|
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":"AAeA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAC;AAI5B,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,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC,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;AAcD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,qBAAqB,GAAG,gBAAgB,CAMnF"}
|
package/dist/root-path.js
CHANGED
|
@@ -2,8 +2,9 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { formatErrorDetail, shortPath } from "./error-detail.js";
|
|
4
4
|
import { FsSafeError } from "./errors.js";
|
|
5
|
-
import { assertNoNulPathInput, isNotFoundPathError,
|
|
5
|
+
import { assertNoNulPathInput, isNotFoundPathError, isPathRelativeEscape, } from "./path.js";
|
|
6
6
|
import { absolutePathWithRawSegments, rawPathRelativeToCanonicalRoot, resolvePathViaExistingAncestor, resolvePathViaExistingAncestorSync, } from "./root-path-existing.js";
|
|
7
|
+
import { admitPathInsideRoot, } from "./root-boundary.js";
|
|
7
8
|
import { resolveSymlinkHopPath, resolveSymlinkHopPathSync } from "./root-path-symlink.js";
|
|
8
9
|
import { assertNoDriveRelativePathSegments } from "./safe-path-segment.js";
|
|
9
10
|
export { resolvePathViaExistingAncestorSync } from "./root-path-existing.js";
|
|
@@ -29,11 +30,10 @@ async function resolveRootPathInternal(params) {
|
|
|
29
30
|
assertValidRootPathInputs(params);
|
|
30
31
|
params = { ...params, absolutePath: absolutePathWithRawSegments(params.absolutePath) };
|
|
31
32
|
const rootPath = path.resolve(params.rootPath);
|
|
32
|
-
const absolutePath = path.resolve(params.absolutePath);
|
|
33
33
|
const rootCanonicalPath = params.rootCanonicalPath
|
|
34
34
|
? path.resolve(params.rootCanonicalPath)
|
|
35
35
|
: await resolvePathViaExistingAncestor(rootPath);
|
|
36
|
-
return resolveRootPathLexicalAsync(prepareRootTraversal(params, rootPath, rootCanonicalPath
|
|
36
|
+
return resolveRootPathLexicalAsync(prepareRootTraversal(params, rootPath, rootCanonicalPath));
|
|
37
37
|
}
|
|
38
38
|
export function resolveRootPathSync(params) {
|
|
39
39
|
try {
|
|
@@ -47,25 +47,38 @@ function resolveRootPathSyncInternal(params) {
|
|
|
47
47
|
assertValidRootPathInputs(params);
|
|
48
48
|
params = { ...params, absolutePath: absolutePathWithRawSegments(params.absolutePath) };
|
|
49
49
|
const rootPath = path.resolve(params.rootPath);
|
|
50
|
-
const absolutePath = path.resolve(params.absolutePath);
|
|
51
50
|
const rootCanonicalPath = params.rootCanonicalPath
|
|
52
51
|
? path.resolve(params.rootCanonicalPath)
|
|
53
52
|
: resolvePathViaExistingAncestorSync(rootPath);
|
|
54
|
-
return resolveRootPathLexicalSync(prepareRootTraversal(params, rootPath, rootCanonicalPath
|
|
53
|
+
return resolveRootPathLexicalSync(prepareRootTraversal(params, rootPath, rootCanonicalPath));
|
|
55
54
|
}
|
|
56
|
-
function prepareRootTraversal(params, rootPath, rootCanonicalPath
|
|
55
|
+
function prepareRootTraversal(params, rootPath, rootCanonicalPath) {
|
|
56
|
+
const callerAbsolutePath = path.resolve(params.absolutePath);
|
|
57
57
|
let raw = params.absolutePath;
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
let trustedAbsolutePath = false;
|
|
59
|
+
const direct = admitRawPathInsideRoot(rootPath, raw, params.rootIdentity);
|
|
60
|
+
if (direct) {
|
|
61
|
+
raw = direct.path;
|
|
62
|
+
trustedAbsolutePath = direct.admission === "identity";
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const canonical = admitRawPathInsideRoot(rootCanonicalPath, raw, params.rootIdentity);
|
|
66
|
+
const relative = canonical?.relativePath
|
|
60
67
|
?? rawPathRelativeToCanonicalRoot(raw, rootCanonicalPath, params);
|
|
61
68
|
if (relative === undefined) {
|
|
62
69
|
throw pathEscapeError({ rootPath, absolutePath: raw, boundaryLabel: params.boundaryLabel });
|
|
63
70
|
}
|
|
64
|
-
|
|
71
|
+
trustedAbsolutePath = canonical?.admission === "identity";
|
|
72
|
+
raw = relative === "" ? rootPath : `${rootPath}${path.sep}${relative}`;
|
|
65
73
|
}
|
|
66
74
|
return {
|
|
67
75
|
params: raw === params.absolutePath ? params : { ...params, absolutePath: raw },
|
|
68
|
-
rootPath,
|
|
76
|
+
rootPath,
|
|
77
|
+
rootCanonicalPath,
|
|
78
|
+
// Preserve the caller-spelling receipt for ordinary aliases. Only a
|
|
79
|
+
// Windows case-fold admission must return the identity-gated Root spelling,
|
|
80
|
+
// because downstream I/O must not reuse the ambiguous caller prefix.
|
|
81
|
+
absolutePath: trustedAbsolutePath ? path.resolve(raw) : callerAbsolutePath,
|
|
69
82
|
};
|
|
70
83
|
}
|
|
71
84
|
function sanitizeRootPathError(error) {
|
|
@@ -93,7 +106,7 @@ function assertNoEmbeddedDriveRelativeSegment(filePath, label) {
|
|
|
93
106
|
}
|
|
94
107
|
function createLexicalTraversalState(params) {
|
|
95
108
|
const rawAbsolutePath = params.params.absolutePath;
|
|
96
|
-
const relative =
|
|
109
|
+
const relative = admitRawPathInsideRoot(params.rootPath, rawAbsolutePath, params.params.rootIdentity)?.relativePath;
|
|
97
110
|
if (relative === undefined)
|
|
98
111
|
throw new Error("Path traversal must begin at the root");
|
|
99
112
|
const segments = splitTraversalSegments(relative);
|
|
@@ -124,7 +137,7 @@ function splitTraversalSegments(value) {
|
|
|
124
137
|
segments.push(".");
|
|
125
138
|
return segments;
|
|
126
139
|
}
|
|
127
|
-
function
|
|
140
|
+
function admitRawPathInsideRoot(rootPath, candidatePath, rootIdentity) {
|
|
128
141
|
if (!path.isAbsolute(candidatePath)) {
|
|
129
142
|
return undefined;
|
|
130
143
|
}
|
|
@@ -132,30 +145,36 @@ function rawPathRelativeToRoot(rootPath, candidatePath) {
|
|
|
132
145
|
const candidate = process.platform === "win32"
|
|
133
146
|
? candidatePath.replaceAll("/", path.sep)
|
|
134
147
|
: candidatePath;
|
|
148
|
+
if (process.platform === "win32") {
|
|
149
|
+
return admitPathInsideRoot({ rootPath: root, candidatePath: candidate, rootIdentity });
|
|
150
|
+
}
|
|
135
151
|
if (candidate === root) {
|
|
136
|
-
return "";
|
|
152
|
+
return { admission: "exact", path: candidate, relativePath: "" };
|
|
137
153
|
}
|
|
138
154
|
const rootWithSep = root.endsWith(path.sep) ? root : `${root}${path.sep}`;
|
|
139
155
|
const candidatePrefix = candidate.slice(0, rootWithSep.length);
|
|
140
|
-
|
|
141
|
-
?
|
|
142
|
-
|
|
143
|
-
|
|
156
|
+
return candidatePrefix === rootWithSep
|
|
157
|
+
? {
|
|
158
|
+
admission: "exact",
|
|
159
|
+
path: candidate,
|
|
160
|
+
relativePath: candidate.slice(rootWithSep.length),
|
|
161
|
+
}
|
|
162
|
+
: undefined;
|
|
144
163
|
}
|
|
145
164
|
function assertLexicalCursorInsideBoundary(context, candidatePath) {
|
|
146
|
-
assertInsideBoundary({
|
|
165
|
+
return assertInsideBoundary({
|
|
147
166
|
boundaryLabel: context.resolveParams.boundaryLabel,
|
|
148
167
|
rootCanonicalPath: context.rootCanonicalPath,
|
|
168
|
+
rootIdentity: context.resolveParams.rootIdentity,
|
|
149
169
|
candidatePath,
|
|
150
170
|
absolutePath: context.absolutePath,
|
|
151
171
|
});
|
|
152
172
|
}
|
|
153
173
|
function advanceCanonicalCursorForSegment(context, segment) {
|
|
154
|
-
context.state.canonicalCursor = path.resolve(context.state.canonicalCursor, segment);
|
|
155
|
-
assertLexicalCursorInsideBoundary(context, context.state.canonicalCursor);
|
|
174
|
+
context.state.canonicalCursor = assertLexicalCursorInsideBoundary(context, path.resolve(context.state.canonicalCursor, segment));
|
|
156
175
|
}
|
|
157
176
|
function finalizeLexicalResolution(context, kind) {
|
|
158
|
-
assertLexicalCursorInsideBoundary(context, context.state.canonicalCursor);
|
|
177
|
+
context.state.canonicalCursor = assertLexicalCursorInsideBoundary(context, context.state.canonicalCursor);
|
|
159
178
|
return buildResolvedRootPath({
|
|
160
179
|
absolutePath: context.absolutePath,
|
|
161
180
|
canonicalPath: context.state.canonicalCursor,
|
|
@@ -181,15 +200,19 @@ function lexicalStatDisposition(params) {
|
|
|
181
200
|
return params.allowFinalSymlink && params.isLast ? "break" : "resolve-link";
|
|
182
201
|
}
|
|
183
202
|
function applyResolvedSymlinkHop(context, linkCanonical) {
|
|
184
|
-
|
|
203
|
+
let admitted;
|
|
204
|
+
try {
|
|
205
|
+
admitted = assertLexicalCursorInsideBoundary(context, linkCanonical);
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
185
208
|
throw symlinkEscapeError({
|
|
186
209
|
boundaryLabel: context.resolveParams.boundaryLabel,
|
|
187
210
|
rootCanonicalPath: context.rootCanonicalPath,
|
|
188
211
|
symlinkPath: context.state.lexicalCursor,
|
|
189
212
|
});
|
|
190
213
|
}
|
|
191
|
-
context.state.canonicalCursor =
|
|
192
|
-
context.state.lexicalCursor =
|
|
214
|
+
context.state.canonicalCursor = admitted;
|
|
215
|
+
context.state.lexicalCursor = admitted;
|
|
193
216
|
}
|
|
194
217
|
function applyParentTraversalStep(context) {
|
|
195
218
|
context.state.lexicalCursor = path.resolve(context.state.lexicalCursor, "..");
|
|
@@ -380,8 +403,13 @@ function relativeInsideRoot(rootPath, targetPath) {
|
|
|
380
403
|
return relative;
|
|
381
404
|
}
|
|
382
405
|
function assertInsideBoundary(params) {
|
|
383
|
-
|
|
384
|
-
|
|
406
|
+
const admitted = admitPathInsideRoot({
|
|
407
|
+
rootPath: params.rootCanonicalPath,
|
|
408
|
+
candidatePath: params.candidatePath,
|
|
409
|
+
rootIdentity: params.rootIdentity,
|
|
410
|
+
});
|
|
411
|
+
if (admitted) {
|
|
412
|
+
return admitted.path;
|
|
385
413
|
}
|
|
386
414
|
throw new Error(`Path resolves outside ${params.boundaryLabel} (${shortPath(params.rootCanonicalPath)}): ${shortPath(params.absolutePath)}`);
|
|
387
415
|
}
|
package/dist/root-paths.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FsSafeError } from "./errors.js";
|
|
2
|
+
import { type ResolvePathWithinRootParams } from "./path-scope-lexical.js";
|
|
2
3
|
type InvalidPathResult = {
|
|
3
4
|
ok: false;
|
|
4
5
|
error: string;
|
|
@@ -50,12 +51,7 @@ export type PathScope = {
|
|
|
50
51
|
mode?: number;
|
|
51
52
|
}): Promise<DirectoryResult>;
|
|
52
53
|
};
|
|
53
|
-
export declare function resolvePathWithinRoot(params: {
|
|
54
|
-
rootDir: string;
|
|
55
|
-
requestedPath: string;
|
|
56
|
-
scopeLabel: string;
|
|
57
|
-
defaultFileName?: string;
|
|
58
|
-
}): {
|
|
54
|
+
export declare function resolvePathWithinRoot(params: ResolvePathWithinRootParams): {
|
|
59
55
|
ok: true;
|
|
60
56
|
path: string;
|
|
61
57
|
} | {
|
package/dist/root-paths.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-paths.d.ts","sourceRoot":"","sources":["../src/root-paths.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAW1C,KAAK,iBAAiB,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AACtD,KAAK,eAAe,GAChB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC1B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAC3D,KAAK,4BAA4B,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AACF,KAAK,4BAA4B,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,iBAAiB,CAAC;AACtF,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AACF,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CACL,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,uBAAuB,GAChC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,4BAA4B,CAAC;IACnE,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAC1E,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACvE,QAAQ,CACN,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,SAAS,CACP,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,uBAAuB,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GACpD,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7B,CAAC;
|
|
1
|
+
{"version":3,"file":"root-paths.d.ts","sourceRoot":"","sources":["../src/root-paths.ts"],"names":[],"mappings":"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"}
|
package/dist/root-paths.js
CHANGED
|
@@ -5,19 +5,17 @@ import { formatErrorDetail } from "./error-detail.js";
|
|
|
5
5
|
import { FsSafeError } from "./errors.js";
|
|
6
6
|
import { assertNoNulPathInput, hasNodeErrorCode, isNodeError, isNotFoundPathError, isPathInside, isPathRelativeEscape, } from "./path.js";
|
|
7
7
|
import { root as openRoot } from "./root.js";
|
|
8
|
+
import { realpathSync } from "./realpath.js";
|
|
9
|
+
import { resolvePathWithinNormalizedRoot } from "./path-scope-lexical.js";
|
|
8
10
|
function invalidPath(scopeLabel) {
|
|
9
11
|
return {
|
|
10
12
|
ok: false,
|
|
11
13
|
error: `Invalid path: must stay within ${scopeLabel}`,
|
|
12
14
|
};
|
|
13
15
|
}
|
|
14
|
-
function pathStaysWithinRoot(rootDir, candidatePath) {
|
|
15
|
-
const relative = path.relative(rootDir, candidatePath);
|
|
16
|
-
return Boolean(relative) && !isPathRelativeEscape(relative);
|
|
17
|
-
}
|
|
18
16
|
async function resolveRealPathIfExists(targetPath) {
|
|
19
17
|
try {
|
|
20
|
-
return
|
|
18
|
+
return realpathSync.native(targetPath);
|
|
21
19
|
}
|
|
22
20
|
catch {
|
|
23
21
|
return undefined;
|
|
@@ -29,7 +27,7 @@ async function resolveTrustedRootRealPath(rootDir) {
|
|
|
29
27
|
if (!rootLstat.isDirectory() || rootLstat.isSymbolicLink()) {
|
|
30
28
|
return undefined;
|
|
31
29
|
}
|
|
32
|
-
return
|
|
30
|
+
return realpathSync.native(rootDir);
|
|
33
31
|
}
|
|
34
32
|
catch {
|
|
35
33
|
return undefined;
|
|
@@ -50,7 +48,7 @@ async function validateCanonicalPathWithinRoot(params) {
|
|
|
50
48
|
if (params.expect === "file" && candidateLstat.nlink > 1) {
|
|
51
49
|
return "invalid";
|
|
52
50
|
}
|
|
53
|
-
const candidateRealPath =
|
|
51
|
+
const candidateRealPath = realpathSync.native(params.candidatePath);
|
|
54
52
|
return isPathInside(params.rootRealPath, candidateRealPath) ? "ok" : "invalid";
|
|
55
53
|
}
|
|
56
54
|
catch (err) {
|
|
@@ -58,23 +56,7 @@ async function validateCanonicalPathWithinRoot(params) {
|
|
|
58
56
|
}
|
|
59
57
|
}
|
|
60
58
|
export function resolvePathWithinRoot(params) {
|
|
61
|
-
|
|
62
|
-
const raw = params.requestedPath.trim();
|
|
63
|
-
if (!raw) {
|
|
64
|
-
if (!params.defaultFileName) {
|
|
65
|
-
return { ok: false, error: "path is required" };
|
|
66
|
-
}
|
|
67
|
-
const defaultPath = path.resolve(root, params.defaultFileName);
|
|
68
|
-
if (!pathStaysWithinRoot(root, defaultPath)) {
|
|
69
|
-
return { ok: false, error: `Invalid path: must stay within ${params.scopeLabel}` };
|
|
70
|
-
}
|
|
71
|
-
return { ok: true, path: defaultPath };
|
|
72
|
-
}
|
|
73
|
-
const resolved = path.resolve(root, raw);
|
|
74
|
-
if (!pathStaysWithinRoot(root, resolved)) {
|
|
75
|
-
return { ok: false, error: `Invalid path: must stay within ${params.scopeLabel}` };
|
|
76
|
-
}
|
|
77
|
-
return { ok: true, path: resolved };
|
|
59
|
+
return resolvePathWithinNormalizedRoot(params, path.resolve(params.rootDir));
|
|
78
60
|
}
|
|
79
61
|
export async function resolveWritablePathWithinRoot(params) {
|
|
80
62
|
const lexical = resolvePathWithinRoot(params);
|
|
@@ -169,9 +151,9 @@ export async function ensureDirectoryWithinRoot(params) {
|
|
|
169
151
|
return invalidPath(scopeLabel);
|
|
170
152
|
}
|
|
171
153
|
await assertNoSymlinkSegments({ rootDir, targetPath, scopeLabel });
|
|
172
|
-
const rootReal =
|
|
154
|
+
const rootReal = realpathSync.native(rootDir);
|
|
173
155
|
const nearestExistingPath = await resolveNearestExistingPath(targetPath);
|
|
174
|
-
const nearestExistingReal =
|
|
156
|
+
const nearestExistingReal = realpathSync.native(nearestExistingPath);
|
|
175
157
|
if (!isPathInside(rootReal, nearestExistingReal)) {
|
|
176
158
|
return invalidPath(scopeLabel);
|
|
177
159
|
}
|
|
@@ -202,12 +184,12 @@ export async function ensureDirectoryWithinRoot(params) {
|
|
|
202
184
|
}
|
|
203
185
|
}
|
|
204
186
|
}
|
|
205
|
-
const currentReal =
|
|
187
|
+
const currentReal = realpathSync.native(current);
|
|
206
188
|
if (!isPathInside(rootReal, currentReal)) {
|
|
207
189
|
return invalidPath(scopeLabel);
|
|
208
190
|
}
|
|
209
191
|
}
|
|
210
|
-
const targetReal =
|
|
192
|
+
const targetReal = realpathSync.native(targetPath);
|
|
211
193
|
if (!isPathInside(rootReal, targetReal)) {
|
|
212
194
|
return invalidPath(scopeLabel);
|
|
213
195
|
}
|
|
@@ -229,12 +211,22 @@ export async function ensureDirectoryWithinRoot(params) {
|
|
|
229
211
|
}
|
|
230
212
|
export function resolvePathsWithinRoot(params) {
|
|
231
213
|
const resolvedPaths = [];
|
|
214
|
+
let previousRootDir;
|
|
215
|
+
let previousResolvedRoot = "";
|
|
232
216
|
for (const raw of params.requestedPaths) {
|
|
233
|
-
const
|
|
217
|
+
const request = {
|
|
234
218
|
rootDir: params.rootDir,
|
|
235
219
|
requestedPath: raw,
|
|
236
220
|
scopeLabel: params.scopeLabel,
|
|
237
|
-
}
|
|
221
|
+
};
|
|
222
|
+
// Relative roots may follow cwd changes made by an input iterator or getter.
|
|
223
|
+
const resolvedRoot = process.platform !== "win32" && typeof request.rootDir === "string" &&
|
|
224
|
+
request.rootDir.startsWith("/") && request.rootDir === previousRootDir
|
|
225
|
+
? previousResolvedRoot
|
|
226
|
+
: path.resolve(request.rootDir);
|
|
227
|
+
previousRootDir = request.rootDir;
|
|
228
|
+
previousResolvedRoot = resolvedRoot;
|
|
229
|
+
const pathResult = resolvePathWithinNormalizedRoot(request, resolvedRoot);
|
|
238
230
|
if (!pathResult.ok) {
|
|
239
231
|
return { ok: false, error: pathResult.error };
|
|
240
232
|
}
|
|
@@ -309,7 +301,7 @@ async function resolveCheckedPathsWithinRoot(params, allowMissingFallback) {
|
|
|
309
301
|
return lexicalPathResult;
|
|
310
302
|
}
|
|
311
303
|
try {
|
|
312
|
-
const resolvedExistingPath =
|
|
304
|
+
const resolvedExistingPath = realpathSync.native(raw);
|
|
313
305
|
const relativePath = path.relative(rootRealPath, resolvedExistingPath);
|
|
314
306
|
if (!isInRoot(relativePath)) {
|
|
315
307
|
return lexicalPathResult;
|
|
@@ -351,7 +343,7 @@ async function resolveCheckedPathsWithinRoot(params, allowMissingFallback) {
|
|
|
351
343
|
scopeLabel: params.scopeLabel,
|
|
352
344
|
});
|
|
353
345
|
const existingPath = await resolveNearestExistingPath(pathResult.fallbackPath);
|
|
354
|
-
const existingRealPath =
|
|
346
|
+
const existingRealPath = realpathSync.native(existingPath);
|
|
355
347
|
if (!isPathInside(rootRealPath, existingRealPath)) {
|
|
356
348
|
return invalidPath(params.scopeLabel);
|
|
357
349
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type RootContext } from "./root-context.js";
|
|
2
|
+
import type { RootRemoveOptions } from "./root-options.js";
|
|
3
|
+
export declare function validateRemoveOptions(options: RootRemoveOptions): void;
|
|
4
|
+
export declare function removePathInRootFallback(root: RootContext, targetPath: string, options: RootRemoveOptions): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=root-remove.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-remove.d.ts","sourceRoot":"","sources":["../src/root-remove.ts"],"names":[],"mappings":"AAeA,OAAO,EAA6B,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAS3D,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAgBtE;AA0CD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,WAAW,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CA6Lf"}
|