@openclaw/fs-safe 0.12.0 → 0.13.1
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 +73 -0
- package/README.md +12 -7
- package/dist/absolute-path.d.ts.map +1 -1
- package/dist/absolute-path.js +32 -11
- package/dist/advanced.d.ts +2 -0
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +2 -0
- package/dist/archive-input.d.ts.map +1 -1
- package/dist/archive-input.js +6 -2
- package/dist/archive-merge.d.ts.map +1 -1
- package/dist/archive-merge.js +15 -2
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +7 -19
- package/dist/archive-plan.js +1 -1
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +18 -13
- package/dist/archive-staging.d.ts.map +1 -1
- package/dist/archive-staging.js +43 -10
- package/dist/archive-tar-inspect.d.ts.map +1 -1
- package/dist/archive-tar-inspect.js +4 -1
- 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 +2 -2
- package/dist/archive-zip-directory.d.ts +3 -0
- package/dist/archive-zip-directory.d.ts.map +1 -1
- package/dist/archive-zip-directory.js +13 -2
- package/dist/archive-zip-loader.d.ts +3 -2
- package/dist/archive-zip-loader.d.ts.map +1 -1
- package/dist/archive-zip-loader.js +30 -4
- package/dist/archive-zip-manifest.d.ts +5 -0
- package/dist/archive-zip-manifest.d.ts.map +1 -0
- package/dist/archive-zip-manifest.js +22 -0
- package/dist/archive-zip-names.d.ts +6 -1
- package/dist/archive-zip-names.d.ts.map +1 -1
- package/dist/archive-zip-names.js +35 -14
- package/dist/archive-zip-preflight.d.ts.map +1 -1
- package/dist/archive-zip-preflight.js +3 -2
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +9 -4
- package/dist/copy-file-input.d.ts +1 -1
- package/dist/copy-file-input.d.ts.map +1 -1
- package/dist/copy-file-input.js +2 -0
- package/dist/darwin-acl.d.ts +4 -0
- package/dist/darwin-acl.d.ts.map +1 -0
- package/dist/darwin-acl.js +24 -0
- package/dist/deny-mutations.d.ts.map +1 -1
- package/dist/deny-mutations.js +8 -2
- package/dist/directory-durability.d.ts.map +1 -1
- package/dist/directory-durability.js +67 -23
- package/dist/directory-entry-path.d.ts +3 -0
- package/dist/directory-entry-path.d.ts.map +1 -0
- package/dist/directory-entry-path.js +21 -0
- package/dist/directory-guard.d.ts +17 -1
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-guard.js +134 -48
- package/dist/directory-mode-node.d.ts +12 -0
- package/dist/directory-mode-node.d.ts.map +1 -1
- package/dist/directory-mode-node.js +102 -4
- package/dist/effective-uid.d.ts +2 -0
- package/dist/effective-uid.d.ts.map +1 -0
- package/dist/effective-uid.js +25 -0
- package/dist/file-handle-transfer.d.ts.map +1 -1
- package/dist/file-handle-transfer.js +98 -27
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +3 -0
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +36 -6
- package/dist/file-lock.d.ts.map +1 -1
- package/dist/file-lock.js +29 -9
- package/dist/file-observation.d.ts +1 -1
- package/dist/file-observation.d.ts.map +1 -1
- package/dist/file-store-boundary.d.ts +6 -2
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +20 -65
- package/dist/file-store-copy-source.d.ts +5 -0
- package/dist/file-store-copy-source.d.ts.map +1 -0
- package/dist/file-store-copy-source.js +31 -0
- package/dist/file-store-path.d.ts.map +1 -1
- package/dist/file-store-path.js +4 -1
- package/dist/file-store-sync-directory.d.ts +16 -0
- package/dist/file-store-sync-directory.d.ts.map +1 -0
- package/dist/file-store-sync-directory.js +349 -0
- package/dist/file-store.d.ts.map +1 -1
- package/dist/file-store.js +11 -28
- package/dist/filename.d.ts.map +1 -1
- package/dist/filename.js +65 -20
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +3 -2
- package/dist/guarded-mkdir.d.ts +8 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +176 -27
- package/dist/guest.d.ts.map +1 -1
- package/dist/guest.js +4 -1
- package/dist/home-dir.d.ts.map +1 -1
- package/dist/home-dir.js +73 -10
- package/dist/install-path.d.ts.map +1 -1
- package/dist/install-path.js +54 -19
- package/dist/json-durable-queue-ownership.d.ts +6 -0
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +89 -42
- package/dist/json-durable-queue-paths.d.ts +11 -0
- package/dist/json-durable-queue-paths.d.ts.map +1 -0
- package/dist/json-durable-queue-paths.js +42 -0
- package/dist/json-durable-queue-read.d.ts.map +1 -1
- package/dist/json-durable-queue-read.js +2 -0
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +50 -58
- package/dist/json-store.d.ts.map +1 -1
- package/dist/json-store.js +5 -1
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +54 -22
- package/dist/local-file-access.d.ts.map +1 -1
- package/dist/local-file-access.js +4 -0
- package/dist/local-file-descriptor.d.ts +17 -0
- package/dist/local-file-descriptor.d.ts.map +1 -0
- package/dist/local-file-descriptor.js +84 -0
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +35 -7
- package/dist/move-path-cleanup.d.ts +2 -0
- package/dist/move-path-cleanup.d.ts.map +1 -1
- package/dist/move-path-cleanup.js +44 -18
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +31 -6
- package/dist/native-binding.d.ts +17 -0
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-binding.js +8 -1
- package/dist/native-directory-observation.d.ts +17 -0
- package/dist/native-directory-observation.d.ts.map +1 -0
- package/dist/native-directory-observation.js +37 -0
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +6 -4
- package/dist/native-parent-admission.d.ts +32 -0
- package/dist/native-parent-admission.d.ts.map +1 -0
- package/dist/native-parent-admission.js +127 -0
- package/dist/native-pinned-write-windows.d.ts +0 -1
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +8 -9
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +314 -42
- package/dist/native-staged-file.d.ts +4 -4
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +20 -10
- package/dist/native.d.ts +1 -1
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +7 -2
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +15 -5
- package/dist/overwrite-file-handle.d.ts.map +1 -1
- package/dist/overwrite-file-handle.js +5 -1
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +2 -0
- package/dist/path-policy.d.ts.map +1 -1
- package/dist/path-policy.js +7 -2
- package/dist/path-prefix.d.ts +7 -0
- package/dist/path-prefix.d.ts.map +1 -0
- package/dist/path-prefix.js +82 -0
- package/dist/path-scope-lexical.d.ts.map +1 -1
- package/dist/path-scope-lexical.js +18 -8
- package/dist/path-segment-route.d.ts +7 -0
- package/dist/path-segment-route.d.ts.map +1 -0
- package/dist/path-segment-route.js +24 -0
- package/dist/path-suffix-aliases.d.ts +10 -0
- package/dist/path-suffix-aliases.d.ts.map +1 -0
- package/dist/path-suffix-aliases.js +386 -0
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +16 -5
- package/dist/permissions-windows.d.ts.map +1 -1
- package/dist/permissions-windows.js +14 -3
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +37 -8
- package/dist/pinned-mutation-admission.d.ts +25 -0
- package/dist/pinned-mutation-admission.d.ts.map +1 -0
- package/dist/pinned-mutation-admission.js +425 -0
- package/dist/pinned-mutation-observation.d.ts +34 -0
- package/dist/pinned-mutation-observation.d.ts.map +1 -0
- package/dist/pinned-mutation-observation.js +142 -0
- package/dist/pinned-mutation-shared-route.d.ts +24 -0
- package/dist/pinned-mutation-shared-route.d.ts.map +1 -0
- package/dist/pinned-mutation-shared-route.js +70 -0
- package/dist/pinned-open.d.ts +6 -0
- package/dist/pinned-open.d.ts.map +1 -1
- package/dist/pinned-open.js +28 -10
- package/dist/pinned-write-types.d.ts +75 -0
- package/dist/pinned-write-types.d.ts.map +1 -0
- package/dist/pinned-write-types.js +1 -0
- package/dist/pinned-write.d.ts +7 -33
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +151 -17
- package/dist/private-directory.d.ts.map +1 -1
- package/dist/private-directory.js +2 -0
- package/dist/private-producer-handoff.d.ts +16 -0
- package/dist/private-producer-handoff.d.ts.map +1 -0
- package/dist/private-producer-handoff.js +272 -0
- package/dist/private-temp-workspace.d.ts +2 -39
- package/dist/private-temp-workspace.d.ts.map +1 -1
- package/dist/private-temp-workspace.js +183 -77
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +38 -32
- package/dist/regular-file.d.ts.map +1 -1
- package/dist/regular-file.js +56 -45
- package/dist/replace-directory.d.ts.map +1 -1
- package/dist/replace-directory.js +12 -5
- package/dist/replace-file-temp-owner.d.ts +1 -0
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +12 -1
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +24 -24
- package/dist/root-boundary.d.ts +4 -0
- package/dist/root-boundary.d.ts.map +1 -1
- package/dist/root-boundary.js +6 -1
- package/dist/root-context.d.ts +12 -1
- package/dist/root-context.d.ts.map +1 -1
- package/dist/root-context.js +57 -11
- package/dist/root-directory-creation.d.ts +13 -0
- package/dist/root-directory-creation.d.ts.map +1 -0
- package/dist/root-directory-creation.js +212 -0
- package/dist/root-directory-list.d.ts +16 -4
- package/dist/root-directory-list.d.ts.map +1 -1
- package/dist/root-directory-list.js +180 -39
- package/dist/root-directory.d.ts +23 -0
- package/dist/root-directory.d.ts.map +1 -0
- package/dist/root-directory.js +141 -0
- package/dist/root-errors.d.ts.map +1 -1
- package/dist/root-errors.js +12 -1
- package/dist/root-file-final-admission.d.ts +21 -0
- package/dist/root-file-final-admission.d.ts.map +1 -0
- package/dist/root-file-final-admission.js +83 -0
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +103 -24
- package/dist/root-impl.d.ts +1 -0
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +289 -317
- package/dist/root-move-noreplace.d.ts +14 -0
- package/dist/root-move-noreplace.d.ts.map +1 -0
- package/dist/root-move-noreplace.js +202 -0
- package/dist/root-observed-path.d.ts +9 -0
- package/dist/root-observed-path.d.ts.map +1 -0
- package/dist/root-observed-path.js +95 -0
- package/dist/root-path-errors.d.ts +12 -0
- package/dist/root-path-errors.d.ts.map +1 -0
- package/dist/root-path-errors.js +13 -0
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +53 -20
- package/dist/root-path-observation.d.ts +63 -0
- package/dist/root-path-observation.d.ts.map +1 -0
- package/dist/root-path-observation.js +180 -0
- package/dist/root-path-stat.d.ts +5 -0
- package/dist/root-path-stat.d.ts.map +1 -0
- package/dist/root-path-stat.js +101 -0
- package/dist/root-path-symlink.d.ts.map +1 -1
- package/dist/root-path-symlink.js +23 -4
- package/dist/root-path.d.ts +11 -0
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +215 -53
- package/dist/root-paths-lexical.d.ts +9 -0
- package/dist/root-paths-lexical.d.ts.map +1 -0
- package/dist/root-paths-lexical.js +22 -0
- package/dist/root-paths.d.ts +3 -25
- package/dist/root-paths.d.ts.map +1 -1
- package/dist/root-paths.js +77 -154
- package/dist/root-read-admission.d.ts +26 -0
- package/dist/root-read-admission.d.ts.map +1 -0
- package/dist/root-read-admission.js +94 -0
- package/dist/root-remove-identity.d.ts +15 -0
- package/dist/root-remove-identity.d.ts.map +1 -0
- package/dist/root-remove-identity.js +89 -0
- package/dist/root-remove-receipt.d.ts +17 -0
- package/dist/root-remove-receipt.d.ts.map +1 -0
- package/dist/root-remove-receipt.js +37 -0
- package/dist/root-remove.d.ts +2 -1
- package/dist/root-remove.d.ts.map +1 -1
- package/dist/root-remove.js +172 -10
- package/dist/root-write-admission.d.ts +68 -0
- package/dist/root-write-admission.d.ts.map +1 -0
- package/dist/root-write-admission.js +322 -0
- package/dist/root-write-compatibility.d.ts +13 -0
- package/dist/root-write-compatibility.d.ts.map +1 -0
- package/dist/root-write-compatibility.js +74 -0
- package/dist/root-write-complete-parent.d.ts +42 -0
- package/dist/root-write-complete-parent.d.ts.map +1 -0
- package/dist/root-write-complete-parent.js +195 -0
- package/dist/root-write-publication.d.ts +24 -0
- package/dist/root-write-publication.d.ts.map +1 -0
- package/dist/root-write-publication.js +85 -0
- package/dist/root-write-verification.d.ts.map +1 -1
- package/dist/root-write-verification.js +6 -4
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +62 -24
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +18 -13
- package/dist/secret-read-policy.d.ts.map +1 -1
- package/dist/secret-read-policy.js +5 -1
- package/dist/secure-file.d.ts.map +1 -1
- package/dist/secure-file.js +92 -7
- package/dist/secure-temp-dir.d.ts +6 -3
- package/dist/secure-temp-dir.d.ts.map +1 -1
- package/dist/secure-temp-dir.js +121 -101
- package/dist/secure-temp-repair.d.ts +35 -0
- package/dist/secure-temp-repair.d.ts.map +1 -0
- package/dist/secure-temp-repair.js +106 -0
- package/dist/sibling-staged-file.d.ts +3 -2
- package/dist/sibling-staged-file.d.ts.map +1 -1
- package/dist/sibling-staged-file.js +179 -55
- package/dist/sibling-temp.d.ts.map +1 -1
- package/dist/sibling-temp.js +27 -13
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +44 -14
- package/dist/sidecar-lock-root.d.ts.map +1 -1
- package/dist/sidecar-lock-root.js +4 -2
- package/dist/staged-directory.d.ts +14 -5
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +54 -3
- package/dist/standalone-publication-path.d.ts +2 -0
- package/dist/standalone-publication-path.d.ts.map +1 -0
- package/dist/standalone-publication-path.js +6 -0
- package/dist/stat-observation.d.ts +11 -0
- package/dist/stat-observation.d.ts.map +1 -0
- package/dist/stat-observation.js +64 -0
- package/dist/strict-file-identity.d.ts.map +1 -1
- package/dist/strict-file-identity.js +39 -2
- package/dist/symlink-parents.d.ts.map +1 -1
- package/dist/symlink-parents.js +7 -2
- package/dist/temp-target.d.ts +2 -0
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +130 -3
- package/dist/temp-workspace-admission.d.ts +22 -0
- package/dist/temp-workspace-admission.d.ts.map +1 -0
- package/dist/temp-workspace-admission.js +374 -0
- package/dist/temp-workspace-child-admission.d.ts +13 -0
- package/dist/temp-workspace-child-admission.d.ts.map +1 -0
- package/dist/temp-workspace-child-admission.js +95 -0
- package/dist/temp-workspace-descriptor.d.ts +48 -0
- package/dist/temp-workspace-descriptor.d.ts.map +1 -0
- package/dist/temp-workspace-descriptor.js +363 -0
- package/dist/temp-workspace-identity.d.ts +15 -0
- package/dist/temp-workspace-identity.d.ts.map +1 -0
- package/dist/temp-workspace-identity.js +41 -0
- package/dist/temp-workspace-owner.d.ts +7 -6
- package/dist/temp-workspace-owner.d.ts.map +1 -1
- package/dist/temp-workspace-owner.js +121 -61
- package/dist/temp-workspace-permissions.d.ts +4 -0
- package/dist/temp-workspace-permissions.d.ts.map +1 -0
- package/dist/temp-workspace-permissions.js +32 -0
- package/dist/temp-workspace-types.d.ts +40 -0
- package/dist/temp-workspace-types.d.ts.map +1 -0
- package/dist/temp-workspace-types.js +1 -0
- package/dist/temp.d.ts +1 -1
- package/dist/temp.d.ts.map +1 -1
- package/dist/temp.js +1 -1
- package/dist/test-hooks.d.ts +7 -0
- package/dist/test-hooks.d.ts.map +1 -1
- package/dist/text-atomic.d.ts.map +1 -1
- package/dist/text-atomic.js +3 -1
- package/dist/trash.d.ts.map +1 -1
- package/dist/trash.js +54 -8
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +9 -6
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +5 -0
- package/dist/windows-path-alias.d.ts +39 -0
- package/dist/windows-path-alias.d.ts.map +1 -0
- package/dist/windows-path-alias.js +153 -0
- package/docs/advanced.md +25 -0
- package/docs/archive.md +23 -2
- package/docs/atomic.md +27 -3
- package/docs/copy.md +3 -0
- package/docs/durability.md +14 -0
- package/docs/errors.md +14 -6
- package/docs/file-store.md +24 -3
- package/docs/filename.md +14 -7
- package/docs/install-path.md +2 -2
- package/docs/install.md +8 -7
- package/docs/json-store.md +5 -1
- package/docs/json.md +11 -0
- package/docs/mutation-policy-proof.md +65 -0
- package/docs/native-helper.md +41 -11
- package/docs/native.md +32 -8
- package/docs/output.md +33 -11
- package/docs/path-prefix.md +64 -0
- package/docs/path-suffix-aliases.md +159 -0
- package/docs/path.md +11 -0
- package/docs/private-file-store.md +14 -0
- package/docs/public-api.md +9 -0
- package/docs/quickstart.md +1 -1
- package/docs/reading.md +8 -1
- package/docs/root.md +18 -3
- package/docs/secret-file.md +3 -0
- package/docs/secure-file.md +6 -2
- package/docs/security-model.md +75 -8
- package/docs/sidecar-lock.md +28 -1
- package/docs/store.md +5 -1
- package/docs/temp.md +260 -36
- package/docs/test-hooks.md +14 -0
- package/docs/writing.md +38 -8
- package/package.json +10 -10
package/dist/root-path.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
1
|
+
import fs, {} from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { shortPath } from "./error-detail.js";
|
|
4
|
+
import { pathEscapeError, sanitizeRootPathError, symlinkEscapeError } from "./root-path-errors.js";
|
|
4
5
|
import { FsSafeError } from "./errors.js";
|
|
6
|
+
import { isNativeDirectoryObservationGuard } from "./native-directory-observation.js";
|
|
5
7
|
import { assertNoNulPathInput, isNotFoundPathError, isPathRelativeEscape, } from "./path.js";
|
|
6
8
|
import { absolutePathWithRawSegments, rawPathRelativeToCanonicalRoot, resolvePathViaExistingAncestor, resolvePathViaExistingAncestorSync, } from "./root-path-existing.js";
|
|
7
9
|
import { admitPathInsideRoot, } from "./root-boundary.js";
|
|
10
|
+
import { RootPathObservationError, captureRootPathObservedDirectory, createRootPathTraversalObservation, inspectRootPathTraversalEntry, } from "./root-path-observation.js";
|
|
8
11
|
import { resolveSymlinkHopPath, resolveSymlinkHopPathSync } from "./root-path-symlink.js";
|
|
9
12
|
import { assertNoDriveRelativePathSegments } from "./safe-path-segment.js";
|
|
13
|
+
import { assertNoWindowsPathAlias, pathForWindowsFilesystem, resolvePathFromBasePreservingWindowsRoot, resolvePathPreservingWindowsRoot, } from "./windows-path-alias.js";
|
|
10
14
|
export { resolvePathViaExistingAncestorSync } from "./root-path-existing.js";
|
|
15
|
+
export { RootPathObservationError, } from "./root-path-observation.js";
|
|
11
16
|
export const ROOT_PATH_ALIAS_POLICIES = {
|
|
12
17
|
strict: Object.freeze({
|
|
13
18
|
allowFinalSymlinkForUnlink: false,
|
|
@@ -26,14 +31,47 @@ export async function resolveRootPath(params) {
|
|
|
26
31
|
throw sanitizeRootPathError(error);
|
|
27
32
|
}
|
|
28
33
|
}
|
|
29
|
-
async function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
export async function resolveRootPathWithCanonicalRootObservation(params, observeRoot) {
|
|
35
|
+
try {
|
|
36
|
+
return await resolveRootPathInternal(params, undefined, undefined, observeRoot);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw sanitizeRootPathError(error);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function resolveRootPathInternal(params, observationRequest, observationOutput, observeRoot, removalReceipts) {
|
|
43
|
+
const input = captureValidRootPathInputs(params);
|
|
44
|
+
const rawAbsolutePath = absolutePathWithRawSegments(input.absolutePath);
|
|
45
|
+
const rootPath = resolvePathPreservingWindowsRoot(input.rootPath);
|
|
46
|
+
const absolutePath = resolvePathPreservingWindowsRoot(rawAbsolutePath);
|
|
47
|
+
const rootCanonicalPath = input.rootCanonicalPath
|
|
48
|
+
? resolvePathPreservingWindowsRoot(input.rootCanonicalPath)
|
|
35
49
|
: await resolvePathViaExistingAncestor(rootPath);
|
|
36
|
-
|
|
50
|
+
assertNoWindowsPathAlias(rootPath);
|
|
51
|
+
assertNoWindowsPathAlias(absolutePath);
|
|
52
|
+
assertNoWindowsPathAlias(rootCanonicalPath);
|
|
53
|
+
observeRoot?.(rootCanonicalPath);
|
|
54
|
+
return resolveRootPathLexicalAsync(prepareRootTraversal(input, rootPath, rootCanonicalPath, absolutePath, rawAbsolutePath), observationRequest, observationOutput, removalReceipts);
|
|
55
|
+
}
|
|
56
|
+
export async function resolveRootPathWithObservation(params, request) {
|
|
57
|
+
const output = {};
|
|
58
|
+
try {
|
|
59
|
+
const resolved = await resolveRootPathInternal(params, request, output);
|
|
60
|
+
return output.receipt ? { resolved, receipt: output.receipt } : { resolved };
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
throw sanitizeRootPathError(error);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Removal receipts are separate from metadata observations and canonical-root
|
|
67
|
+
// callbacks; the public resolver's options and result remain unchanged.
|
|
68
|
+
export async function resolveRootPathForRemoval(params, receipts) {
|
|
69
|
+
try {
|
|
70
|
+
return await resolveRootPathInternal(params, undefined, undefined, undefined, receipts);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
throw sanitizeRootPathError(error);
|
|
74
|
+
}
|
|
37
75
|
}
|
|
38
76
|
export function resolveRootPathSync(params) {
|
|
39
77
|
try {
|
|
@@ -43,18 +81,30 @@ export function resolveRootPathSync(params) {
|
|
|
43
81
|
throw sanitizeRootPathError(error);
|
|
44
82
|
}
|
|
45
83
|
}
|
|
46
|
-
function
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
84
|
+
export function resolveRootPathSyncWithCanonicalRootObservation(params, observeRoot) {
|
|
85
|
+
try {
|
|
86
|
+
return resolveRootPathSyncInternal(params, observeRoot);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
throw sanitizeRootPathError(error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function resolveRootPathSyncInternal(params, observeRoot) {
|
|
93
|
+
const input = captureValidRootPathInputs(params);
|
|
94
|
+
const rawAbsolutePath = absolutePathWithRawSegments(input.absolutePath);
|
|
95
|
+
const rootPath = resolvePathPreservingWindowsRoot(input.rootPath);
|
|
96
|
+
const absolutePath = resolvePathPreservingWindowsRoot(rawAbsolutePath);
|
|
97
|
+
const rootCanonicalPath = input.rootCanonicalPath
|
|
98
|
+
? resolvePathPreservingWindowsRoot(input.rootCanonicalPath)
|
|
52
99
|
: resolvePathViaExistingAncestorSync(rootPath);
|
|
53
|
-
|
|
100
|
+
assertNoWindowsPathAlias(rootPath);
|
|
101
|
+
assertNoWindowsPathAlias(absolutePath);
|
|
102
|
+
assertNoWindowsPathAlias(rootCanonicalPath);
|
|
103
|
+
observeRoot?.(rootCanonicalPath);
|
|
104
|
+
return resolveRootPathLexicalSync(prepareRootTraversal(input, rootPath, rootCanonicalPath, absolutePath, rawAbsolutePath));
|
|
54
105
|
}
|
|
55
|
-
function prepareRootTraversal(params, rootPath, rootCanonicalPath) {
|
|
56
|
-
|
|
57
|
-
let raw = params.absolutePath;
|
|
106
|
+
function prepareRootTraversal(params, rootPath, rootCanonicalPath, absolutePath, rawAbsolutePath) {
|
|
107
|
+
let raw = rawAbsolutePath;
|
|
58
108
|
let trustedAbsolutePath = false;
|
|
59
109
|
const direct = admitRawPathInsideRoot(rootPath, raw, params.rootIdentity);
|
|
60
110
|
if (direct) {
|
|
@@ -72,30 +122,49 @@ function prepareRootTraversal(params, rootPath, rootCanonicalPath) {
|
|
|
72
122
|
raw = relative === "" ? rootPath : `${rootPath}${path.sep}${relative}`;
|
|
73
123
|
}
|
|
74
124
|
return {
|
|
75
|
-
params
|
|
125
|
+
params,
|
|
126
|
+
rawAbsolutePath: raw,
|
|
76
127
|
rootPath,
|
|
77
128
|
rootCanonicalPath,
|
|
78
129
|
// Preserve the caller-spelling receipt for ordinary aliases. Only a
|
|
79
130
|
// Windows case-fold admission must return the identity-gated Root spelling,
|
|
80
131
|
// because downstream I/O must not reuse the ambiguous caller prefix.
|
|
81
|
-
absolutePath: trustedAbsolutePath ?
|
|
132
|
+
absolutePath: trustedAbsolutePath ? resolvePathPreservingWindowsRoot(raw) : absolutePath,
|
|
133
|
+
observationEligible: raw === rawAbsolutePath && !trustedAbsolutePath,
|
|
82
134
|
};
|
|
83
135
|
}
|
|
84
|
-
function
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
assertNoEmbeddedDriveRelativeSegment(
|
|
136
|
+
function captureValidRootPathInputs(params) {
|
|
137
|
+
const rootPath = params.rootPath;
|
|
138
|
+
assertNoNulPathInput(rootPath, "root path contains a NUL byte");
|
|
139
|
+
const absolutePath = params.absolutePath;
|
|
140
|
+
assertNoNulPathInput(absolutePath, "absolute path contains a NUL byte");
|
|
141
|
+
assertNoWindowsPathAlias(rootPath, "filesystem", "root path uses a Windows filesystem namespace alias");
|
|
142
|
+
assertNoWindowsPathAlias(absolutePath, "filesystem", "absolute path uses a Windows filesystem namespace alias");
|
|
143
|
+
assertNoEmbeddedDriveRelativeSegment(rootPath, "root path");
|
|
144
|
+
assertNoEmbeddedDriveRelativeSegment(absolutePath, "absolute path");
|
|
145
|
+
const rootCanonicalPath = params.rootCanonicalPath;
|
|
146
|
+
if (rootCanonicalPath !== undefined) {
|
|
147
|
+
assertNoNulPathInput(rootCanonicalPath, "canonical root path contains a NUL byte");
|
|
148
|
+
assertNoWindowsPathAlias(rootCanonicalPath, "filesystem", "canonical root path uses a Windows filesystem namespace alias");
|
|
149
|
+
assertNoEmbeddedDriveRelativeSegment(rootCanonicalPath, "canonical root path");
|
|
98
150
|
}
|
|
151
|
+
// Keep traversal policy with the admitted paths across ancestor and symlink
|
|
152
|
+
// resolution. Caller-owned flags and getters must not change a running walk.
|
|
153
|
+
const policy = params.policy;
|
|
154
|
+
const rootIdentity = params.rootIdentity;
|
|
155
|
+
return {
|
|
156
|
+
rootPath,
|
|
157
|
+
absolutePath,
|
|
158
|
+
rootCanonicalPath,
|
|
159
|
+
rootIdentity: rootIdentity == null ? undefined : { dev: rootIdentity.dev, ino: rootIdentity.ino },
|
|
160
|
+
boundaryLabel: params.boundaryLabel,
|
|
161
|
+
policy: policy == null ? undefined : {
|
|
162
|
+
allowFinalSymlinkForUnlink: policy.allowFinalSymlinkForUnlink,
|
|
163
|
+
},
|
|
164
|
+
rejectSymlinks: params.rejectSymlinks,
|
|
165
|
+
rejectFinalSymlink: params.rejectFinalSymlink,
|
|
166
|
+
rejectUnresolvedSymlinks: params.rejectUnresolvedSymlinks,
|
|
167
|
+
};
|
|
99
168
|
}
|
|
100
169
|
function assertNoEmbeddedDriveRelativeSegment(filePath, label) {
|
|
101
170
|
if (process.platform !== "win32") {
|
|
@@ -105,13 +174,15 @@ function assertNoEmbeddedDriveRelativeSegment(filePath, label) {
|
|
|
105
174
|
assertNoDriveRelativePathSegments(filePath.slice(root.length).replaceAll("\\", "/"), label);
|
|
106
175
|
}
|
|
107
176
|
function createLexicalTraversalState(params) {
|
|
108
|
-
const rawAbsolutePath = params.
|
|
177
|
+
const rawAbsolutePath = params.rawAbsolutePath;
|
|
109
178
|
const relative = admitRawPathInsideRoot(params.rootPath, rawAbsolutePath, params.params.rootIdentity)?.relativePath;
|
|
110
179
|
if (relative === undefined)
|
|
111
180
|
throw new Error("Path traversal must begin at the root");
|
|
112
181
|
const segments = splitTraversalSegments(relative);
|
|
113
182
|
return {
|
|
114
183
|
segments,
|
|
184
|
+
relativePath: relative,
|
|
185
|
+
reuseLexicalCanonical: false,
|
|
115
186
|
finalComponentIndex: segments.findLastIndex((segment) => segment !== "."),
|
|
116
187
|
allowFinalSymlink: params.params.policy?.allowFinalSymlinkForUnlink === true,
|
|
117
188
|
canonicalCursor: params.rootCanonicalPath,
|
|
@@ -127,8 +198,16 @@ function createLexicalTraversalContext(params) {
|
|
|
127
198
|
rootPath: params.rootPath,
|
|
128
199
|
rootCanonicalPath: params.rootCanonicalPath,
|
|
129
200
|
absolutePath: params.absolutePath,
|
|
201
|
+
observationEligible: params.observationEligible,
|
|
130
202
|
};
|
|
131
203
|
}
|
|
204
|
+
function createLexicalTraversalObservation(context, request) {
|
|
205
|
+
const observation = createRootPathTraversalObservation(context, request);
|
|
206
|
+
if (observation && observation.targetIndex >= 0) {
|
|
207
|
+
context.state.reuseLexicalCanonical = true;
|
|
208
|
+
}
|
|
209
|
+
return observation;
|
|
210
|
+
}
|
|
132
211
|
function splitTraversalSegments(value) {
|
|
133
212
|
const segments = value
|
|
134
213
|
.split(process.platform === "win32" ? /[\\/]+/ : /\/+/)
|
|
@@ -141,7 +220,9 @@ function admitRawPathInsideRoot(rootPath, candidatePath, rootIdentity) {
|
|
|
141
220
|
if (!path.isAbsolute(candidatePath)) {
|
|
142
221
|
return undefined;
|
|
143
222
|
}
|
|
144
|
-
|
|
223
|
+
// Every caller supplies the already-resolved root selected by
|
|
224
|
+
// resolveRootPathInternal; resolving it again is redundant on each traversal.
|
|
225
|
+
const root = rootPath;
|
|
145
226
|
const candidate = process.platform === "win32"
|
|
146
227
|
? candidatePath.replaceAll("/", path.sep)
|
|
147
228
|
: candidatePath;
|
|
@@ -171,7 +252,14 @@ function assertLexicalCursorInsideBoundary(context, candidatePath) {
|
|
|
171
252
|
});
|
|
172
253
|
}
|
|
173
254
|
function advanceCanonicalCursorForSegment(context, segment) {
|
|
174
|
-
|
|
255
|
+
const candidatePath = context.state.reuseLexicalCanonical
|
|
256
|
+
? context.state.lexicalCursor
|
|
257
|
+
: resolvePathFromBasePreservingWindowsRoot(context.state.canonicalCursor, segment);
|
|
258
|
+
context.state.canonicalCursor = assertLexicalCursorInsideBoundary(context, candidatePath);
|
|
259
|
+
}
|
|
260
|
+
function disableLexicalTraversalObservation(context, observation) {
|
|
261
|
+
observation.enabled = false;
|
|
262
|
+
context.state.reuseLexicalCanonical = false;
|
|
175
263
|
}
|
|
176
264
|
function finalizeLexicalResolution(context, kind) {
|
|
177
265
|
context.state.canonicalCursor = assertLexicalCursorInsideBoundary(context, context.state.canonicalCursor);
|
|
@@ -215,7 +303,7 @@ function applyResolvedSymlinkHop(context, linkCanonical) {
|
|
|
215
303
|
context.state.lexicalCursor = admitted;
|
|
216
304
|
}
|
|
217
305
|
function applyParentTraversalStep(context) {
|
|
218
|
-
context.state.lexicalCursor =
|
|
306
|
+
context.state.lexicalCursor = resolvePathFromBasePreservingWindowsRoot(context.state.lexicalCursor, "..");
|
|
219
307
|
advanceCanonicalCursorForSegment(context, "..");
|
|
220
308
|
if (context.state.missingDepth > 0)
|
|
221
309
|
context.state.missingDepth -= 1;
|
|
@@ -228,12 +316,13 @@ function assertDirectoryBeforeMoreSegments(stat, pathname, isLast) {
|
|
|
228
316
|
function assertResolvedLinkDirectory(pathname, isLast) {
|
|
229
317
|
if (isLast)
|
|
230
318
|
return;
|
|
231
|
-
const stat = fs.statSync(pathname);
|
|
319
|
+
const stat = fs.statSync(pathForWindowsFilesystem(pathname));
|
|
232
320
|
assertDirectoryBeforeMoreSegments(stat, pathname, isLast);
|
|
233
321
|
}
|
|
234
|
-
async function resolveRootPathLexicalAsync(params) {
|
|
322
|
+
async function resolveRootPathLexicalAsync(params, observationRequest, observationOutput, removalReceipts) {
|
|
235
323
|
const context = createLexicalTraversalContext(params);
|
|
236
324
|
const { state } = context;
|
|
325
|
+
const observation = createLexicalTraversalObservation(context, observationRequest);
|
|
237
326
|
for (let idx = 0; idx < state.segments.length; idx += 1) {
|
|
238
327
|
const segment = state.segments[idx] ?? "";
|
|
239
328
|
const isLast = idx === state.segments.length - 1;
|
|
@@ -250,14 +339,56 @@ async function resolveRootPathLexicalAsync(params) {
|
|
|
250
339
|
continue;
|
|
251
340
|
}
|
|
252
341
|
let stat;
|
|
342
|
+
let observed;
|
|
253
343
|
try {
|
|
254
|
-
|
|
344
|
+
if (removalReceipts && !isLast) {
|
|
345
|
+
const directoryStat = fs.lstatSync(pathForWindowsFilesystem(state.lexicalCursor), { bigint: true });
|
|
346
|
+
if (directoryStat.isDirectory() && !directoryStat.isSymbolicLink()) {
|
|
347
|
+
removalReceipts.observeDirectory(state.lexicalCursor, directoryStat);
|
|
348
|
+
}
|
|
349
|
+
stat = directoryStat;
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
const directorySlot = observation?.enabled === true && idx === observation.directoryIndex;
|
|
353
|
+
const targetSlot = observation?.enabled === true && idx === observation.targetIndex;
|
|
354
|
+
const observeExactly = directorySlot || targetSlot;
|
|
355
|
+
if (observeExactly) {
|
|
356
|
+
observed = inspectRootPathTraversalEntry(state.lexicalCursor, directorySlot, observation);
|
|
357
|
+
}
|
|
358
|
+
stat = isNativeDirectoryObservationGuard(observed)
|
|
359
|
+
? undefined
|
|
360
|
+
: observed?.stat ?? fs.lstatSync(state.lexicalCursor);
|
|
361
|
+
}
|
|
255
362
|
}
|
|
256
363
|
catch (error) {
|
|
364
|
+
if (observation?.enabled && observation.request.kind === "stat" &&
|
|
365
|
+
idx === observation.targetIndex && observation.directoryGuard) {
|
|
366
|
+
const parentReceipt = {
|
|
367
|
+
kind: "stat-parent",
|
|
368
|
+
rootGuard: observation.request.rootGuard,
|
|
369
|
+
directoryGuard: observation.directoryGuard,
|
|
370
|
+
directoryObserver: observation.directoryObserver,
|
|
371
|
+
targetPath: state.lexicalCursor,
|
|
372
|
+
};
|
|
373
|
+
// Stop here: the generic missing-path fallback would re-admit a parent.
|
|
374
|
+
// Preserve observation-only versus ordinary traversal error precedence.
|
|
375
|
+
throw new RootPathObservationError(error instanceof RootPathObservationError ? error.error : sanitizeRootPathError(error), parentReceipt, !(error instanceof RootPathObservationError));
|
|
376
|
+
}
|
|
257
377
|
if (handleLexicalLstatFailure(context, error, segment))
|
|
258
378
|
continue;
|
|
259
379
|
throw error;
|
|
260
380
|
}
|
|
381
|
+
if (isNativeDirectoryObservationGuard(observed)) {
|
|
382
|
+
advanceCanonicalCursorForSegment(context, segment);
|
|
383
|
+
captureRootPathObservedDirectory(observation, observed, state.lexicalCursor, state.canonicalCursor, context.rootCanonicalPath, context.resolveParams.rootIdentity);
|
|
384
|
+
if (idx === observation.targetIndex) {
|
|
385
|
+
observation.targetPath = state.canonicalCursor;
|
|
386
|
+
observation.target = observed;
|
|
387
|
+
}
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
if (!stat)
|
|
391
|
+
throw new Error("directory observation did not return metadata");
|
|
261
392
|
const isSymbolicLink = stat.isSymbolicLink();
|
|
262
393
|
if (!isSymbolicLink)
|
|
263
394
|
assertDirectoryBeforeMoreSegments(stat, state.lexicalCursor, isLast);
|
|
@@ -271,10 +402,24 @@ async function resolveRootPathLexicalAsync(params) {
|
|
|
271
402
|
if (disposition !== "resolve-link") {
|
|
272
403
|
state.preserveFinalSymlink = disposition === "break";
|
|
273
404
|
advanceCanonicalCursorForSegment(context, segment);
|
|
405
|
+
if (observation?.enabled && isSymbolicLink) {
|
|
406
|
+
disableLexicalTraversalObservation(context, observation);
|
|
407
|
+
}
|
|
408
|
+
if (observation?.enabled && idx === observation.directoryIndex) {
|
|
409
|
+
const captured = observed?.identity && captureRootPathObservedDirectory(observation, observed, state.canonicalCursor, state.canonicalCursor, context.rootCanonicalPath, context.resolveParams.rootIdentity);
|
|
410
|
+
if (!captured)
|
|
411
|
+
disableLexicalTraversalObservation(context, observation);
|
|
412
|
+
}
|
|
413
|
+
if (observation?.enabled && idx === observation.targetIndex) {
|
|
414
|
+
observation.targetPath = state.canonicalCursor;
|
|
415
|
+
observation.target = observed?.identity ? observed : undefined;
|
|
416
|
+
}
|
|
274
417
|
if (state.preserveFinalSymlink)
|
|
275
418
|
break;
|
|
276
419
|
continue;
|
|
277
420
|
}
|
|
421
|
+
if (observation?.enabled)
|
|
422
|
+
disableLexicalTraversalObservation(context, observation);
|
|
278
423
|
const linkCanonical = await resolveSymlinkHopPath(state.lexicalCursor, {
|
|
279
424
|
rejectUnresolved: context.resolveParams.rejectUnresolvedSymlinks,
|
|
280
425
|
});
|
|
@@ -284,7 +429,26 @@ async function resolveRootPathLexicalAsync(params) {
|
|
|
284
429
|
}
|
|
285
430
|
assertResolvedLinkDirectory(linkCanonical, isLast);
|
|
286
431
|
}
|
|
287
|
-
const
|
|
432
|
+
const completeObservation = observation?.enabled === true && observation.directoryGuard !== undefined &&
|
|
433
|
+
observation.targetPath === state.canonicalCursor && observation.target !== undefined;
|
|
434
|
+
const kind = completeObservation
|
|
435
|
+
? {
|
|
436
|
+
exists: true,
|
|
437
|
+
kind: isNativeDirectoryObservationGuard(observation.target)
|
|
438
|
+
? "directory"
|
|
439
|
+
: toResolvedKind(observation.target.stat),
|
|
440
|
+
}
|
|
441
|
+
: await getPathKind(state.canonicalCursor, state.preserveFinalSymlink);
|
|
442
|
+
if (completeObservation && observationOutput) {
|
|
443
|
+
observationOutput.receipt = {
|
|
444
|
+
kind: observation.request.kind,
|
|
445
|
+
rootGuard: observation.request.rootGuard,
|
|
446
|
+
directoryGuard: observation.directoryGuard,
|
|
447
|
+
directoryObserver: observation.directoryObserver,
|
|
448
|
+
targetPath: observation.targetPath,
|
|
449
|
+
target: observation.target,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
288
452
|
return finalizeLexicalResolution(context, kind);
|
|
289
453
|
}
|
|
290
454
|
function resolveRootPathLexicalSync(params) {
|
|
@@ -356,9 +520,10 @@ function buildResolvedRootPath(params) {
|
|
|
356
520
|
}
|
|
357
521
|
async function getPathKind(absolutePath, preserveFinalSymlink) {
|
|
358
522
|
try {
|
|
523
|
+
const operationPath = pathForWindowsFilesystem(absolutePath);
|
|
359
524
|
const stat = preserveFinalSymlink
|
|
360
|
-
? fs.lstatSync(
|
|
361
|
-
: fs.statSync(
|
|
525
|
+
? fs.lstatSync(operationPath)
|
|
526
|
+
: fs.statSync(operationPath);
|
|
362
527
|
return { exists: true, kind: toResolvedKind(stat) };
|
|
363
528
|
}
|
|
364
529
|
catch (error) {
|
|
@@ -370,7 +535,10 @@ async function getPathKind(absolutePath, preserveFinalSymlink) {
|
|
|
370
535
|
}
|
|
371
536
|
function getPathKindSync(absolutePath, preserveFinalSymlink) {
|
|
372
537
|
try {
|
|
373
|
-
const
|
|
538
|
+
const operationPath = pathForWindowsFilesystem(absolutePath);
|
|
539
|
+
const stat = preserveFinalSymlink
|
|
540
|
+
? fs.lstatSync(operationPath)
|
|
541
|
+
: fs.statSync(operationPath);
|
|
374
542
|
return { exists: true, kind: toResolvedKind(stat) };
|
|
375
543
|
}
|
|
376
544
|
catch (error) {
|
|
@@ -393,7 +561,7 @@ function toResolvedKind(stat) {
|
|
|
393
561
|
return "other";
|
|
394
562
|
}
|
|
395
563
|
function relativeInsideRoot(rootPath, targetPath) {
|
|
396
|
-
const relative = path.relative(
|
|
564
|
+
const relative = path.relative(resolvePathPreservingWindowsRoot(rootPath), resolvePathPreservingWindowsRoot(targetPath));
|
|
397
565
|
if (!relative || relative === ".") {
|
|
398
566
|
return "";
|
|
399
567
|
}
|
|
@@ -413,9 +581,3 @@ function assertInsideBoundary(params) {
|
|
|
413
581
|
}
|
|
414
582
|
throw new Error(`Path resolves outside ${params.boundaryLabel} (${shortPath(params.rootCanonicalPath)}): ${shortPath(params.absolutePath)}`);
|
|
415
583
|
}
|
|
416
|
-
function pathEscapeError(params) {
|
|
417
|
-
return new Error(`Path escapes ${params.boundaryLabel} (${shortPath(params.rootPath)}): ${shortPath(params.absolutePath)}`);
|
|
418
|
-
}
|
|
419
|
-
function symlinkEscapeError(params) {
|
|
420
|
-
return new Error(`Symlink escapes ${params.boundaryLabel} (${shortPath(params.rootCanonicalPath)}): ${shortPath(params.symlinkPath)}`);
|
|
421
|
-
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ResolvePathWithinRootParams } from "./path-scope-lexical.js";
|
|
2
|
+
export declare function resolvePathWithinRoot(params: ResolvePathWithinRootParams): {
|
|
3
|
+
ok: true;
|
|
4
|
+
path: string;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
error: string;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=root-paths-lexical.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-paths-lexical.d.ts","sourceRoot":"","sources":["../src/root-paths-lexical.ts"],"names":[],"mappings":"AACA,OAAO,EAAmC,KAAK,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAU5G,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,2BAA2B,GAClC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAgB3D"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { resolvePathWithinNormalizedRoot } from "./path-scope-lexical.js";
|
|
3
|
+
import { hasWindowsPathAlias, resolvePathPreservingWindowsRoot, } from "./windows-path-alias.js";
|
|
4
|
+
function invalidPath(scopeLabel) {
|
|
5
|
+
return { ok: false, error: `Invalid path: must stay within ${scopeLabel}` };
|
|
6
|
+
}
|
|
7
|
+
export function resolvePathWithinRoot(params) {
|
|
8
|
+
const rootDir = params.rootDir;
|
|
9
|
+
if (typeof rootDir !== "string")
|
|
10
|
+
path.resolve(rootDir);
|
|
11
|
+
const requestedPath = params.requestedPath;
|
|
12
|
+
const scopeLabel = params.scopeLabel;
|
|
13
|
+
const defaultFileName = params.defaultFileName;
|
|
14
|
+
if (hasWindowsPathAlias(rootDir, "filesystem") ||
|
|
15
|
+
hasWindowsPathAlias(requestedPath, "filesystem") ||
|
|
16
|
+
(defaultFileName !== undefined &&
|
|
17
|
+
hasWindowsPathAlias(defaultFileName, "filesystem"))) {
|
|
18
|
+
return invalidPath(scopeLabel);
|
|
19
|
+
}
|
|
20
|
+
const root = resolvePathPreservingWindowsRoot(rootDir);
|
|
21
|
+
return resolvePathWithinNormalizedRoot({ rootDir, requestedPath, scopeLabel, defaultFileName }, root);
|
|
22
|
+
}
|
package/dist/root-paths.d.ts
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { type DirectoryResult } from "./root-directory.js";
|
|
2
|
+
export { resolvePathWithinRoot } from "./root-paths-lexical.js";
|
|
3
|
+
export { ensureDirectoryWithinRoot } from "./root-directory.js";
|
|
3
4
|
type InvalidPathResult = {
|
|
4
5
|
ok: false;
|
|
5
6
|
error: string;
|
|
6
7
|
};
|
|
7
|
-
type DirectoryResult = {
|
|
8
|
-
ok: true;
|
|
9
|
-
path: string;
|
|
10
|
-
} | {
|
|
11
|
-
ok: false;
|
|
12
|
-
error: string;
|
|
13
|
-
diagnostic?: FsSafeError;
|
|
14
|
-
};
|
|
15
8
|
type ResolvePathsWithinRootParams = {
|
|
16
9
|
rootDir: string;
|
|
17
10
|
requestedPaths: string[];
|
|
@@ -51,13 +44,6 @@ export type PathScope = {
|
|
|
51
44
|
mode?: number;
|
|
52
45
|
}): Promise<DirectoryResult>;
|
|
53
46
|
};
|
|
54
|
-
export declare function resolvePathWithinRoot(params: ResolvePathWithinRootParams): {
|
|
55
|
-
ok: true;
|
|
56
|
-
path: string;
|
|
57
|
-
} | {
|
|
58
|
-
ok: false;
|
|
59
|
-
error: string;
|
|
60
|
-
};
|
|
61
47
|
export declare function resolveWritablePathWithinRoot(params: {
|
|
62
48
|
rootDir: string;
|
|
63
49
|
requestedPath: string;
|
|
@@ -70,16 +56,8 @@ export declare function resolveWritablePathWithinRoot(params: {
|
|
|
70
56
|
ok: false;
|
|
71
57
|
error: string;
|
|
72
58
|
}>;
|
|
73
|
-
export declare function ensureDirectoryWithinRoot(params: {
|
|
74
|
-
rootDir: string;
|
|
75
|
-
requestedPath: string;
|
|
76
|
-
scopeLabel: string;
|
|
77
|
-
defaultDirName?: string;
|
|
78
|
-
mode?: number;
|
|
79
|
-
}): Promise<DirectoryResult>;
|
|
80
59
|
export declare function resolvePathsWithinRoot(params: ResolvePathsWithinRootParams): ResolvePathsWithinRootResult;
|
|
81
60
|
export declare function resolveExistingPathsWithinRoot(params: ResolvePathsWithinRootParams): Promise<ResolvePathsWithinRootResult>;
|
|
82
61
|
export declare function resolveStrictExistingPathsWithinRoot(params: ResolvePathsWithinRootParams): Promise<ResolvePathsWithinRootResult>;
|
|
83
62
|
export declare function pathScope(rootDir: string, options: PathScopeOptions): PathScope;
|
|
84
|
-
export {};
|
|
85
63
|
//# sourceMappingURL=root-paths.d.ts.map
|
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":"
|
|
1
|
+
{"version":3,"file":"root-paths.d.ts","sourceRoot":"","sources":["../src/root-paths.ts"],"names":[],"mappings":"AAgBA,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,KAAK,iBAAiB,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AACtD,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;AAoEF,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA0CrE;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,4BAA4B,GACnC,4BAA4B,CA2B9B;AAED,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,4BAA4B,CAAC,CAEvC;AAED,wBAAsB,oCAAoC,CACxD,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,4BAA4B,CAAC,CAEvC;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAyC/E"}
|