@openclaw/fs-safe 0.18.0 → 0.18.2
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 +18 -0
- package/dist/advanced.d.ts +4 -2
- package/dist/advanced.js +1 -1
- package/dist/archive-durability.d.ts +1 -1
- package/dist/archive-merge.js +0 -1
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-plan.d.ts +64 -3
- package/dist/archive-plan.js +55 -1
- package/dist/archive-staging.d.ts +1 -2
- package/dist/archive-staging.js +0 -2
- package/dist/archive-tar-wasm.d.ts +1 -1
- package/dist/archive-zip-directory.d.ts +1 -1
- package/dist/archive-zip-entry.d.ts +1 -1
- package/dist/archive-zip-entry.js +1 -1
- package/dist/archive-zip-preflight.d.ts +0 -2
- package/dist/archive-zip-preflight.js +0 -1
- package/dist/archive.d.ts +14 -8
- package/dist/archive.js +127 -12
- package/dist/atomic.d.ts +3 -1
- package/dist/copy-publication.d.ts +1 -1
- package/dist/create.d.ts +16 -2
- package/dist/create.js +388 -2
- package/dist/creation-boundary.d.ts +60 -0
- package/dist/creation-boundary.js +371 -0
- package/dist/directory-guard.d.ts +0 -1
- package/dist/directory-guard.js +0 -3
- package/dist/directory-mode-node.d.ts +20 -2
- package/dist/directory-mode-node.js +89 -3
- package/dist/durability.d.ts +2 -1
- package/dist/file-lock-sync-acquisition.js +3 -3
- package/dist/file-lock-sync-root-acquire.js +2 -6
- package/dist/file-lock-sync-root-options.d.ts +2 -10
- package/dist/file-lock-sync-root.d.ts +2 -1
- package/dist/file-lock-sync-stale-admission.js +3 -10
- package/dist/file-lock-sync.d.ts +4 -21
- package/dist/file-store-boundary.d.ts +7 -0
- package/dist/file-store-boundary.js +58 -1
- package/dist/file-store-sync-write.js +2 -3
- package/dist/file-store.js +1 -6
- package/dist/guarded-mkdir.d.ts +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/json-durable-queue-ownership.d.ts +1 -5
- package/dist/json-durable-queue-read.js +7 -3
- package/dist/json-durable-queue.d.ts +0 -1
- package/dist/json-durable-queue.js +1 -3
- package/dist/json-store.js +1 -2
- package/dist/json.js +1 -2
- package/dist/move-path.js +1 -2
- package/dist/native-operations.js +0 -1
- package/dist/native-pinned-write-windows.d.ts +1 -1
- package/dist/native-pinned-write-windows.js +1 -1
- package/dist/native-pinned-write.d.ts +1 -1
- package/dist/native-pinned-write.js +3 -6
- package/dist/native-policy-parent-windows.d.ts +1 -1
- package/dist/native-staged-file.d.ts +2 -2
- package/dist/native-staged-file.js +1 -2
- package/dist/permission-exec.d.ts +6 -0
- package/dist/permissions-public.d.ts +2 -1
- package/dist/permissions-windows.d.ts +3 -6
- package/dist/permissions.d.ts +3 -10
- package/dist/permissions.js +0 -1
- package/dist/pinned-mutation-admission.d.ts +1 -1
- package/dist/pinned-open.d.ts +1 -0
- package/dist/pinned-open.js +7 -2
- package/dist/pinned-operation.d.ts +1 -1
- package/dist/pinned-operation.js +3 -16
- package/dist/pinned-write-mode.js +1 -1
- package/dist/pinned-write-staged.js +1 -2
- package/dist/pinned-write.d.ts +0 -1
- package/dist/pinned-write.js +3 -5
- package/dist/private-producer-handoff-sync.d.ts +2 -12
- package/dist/private-producer-handoff-sync.js +1 -1
- package/dist/private-producer-handoff.d.ts +3 -3
- package/dist/private-temp-workspace.js +1 -2
- package/dist/publish-copy-stage.d.ts +1 -1
- package/dist/publish-file.d.ts +0 -1
- package/dist/publish-file.js +1 -2
- package/dist/replace-directory.js +6 -19
- package/dist/replace-file-copy-fallback.d.ts +1 -8
- package/dist/replace-file-descriptor.d.ts +3 -11
- package/dist/replace-file-descriptor.js +1 -1
- package/dist/replace-file-rename-policy.d.ts +1 -2
- package/dist/replace-file.d.ts +3 -3
- package/dist/replace-file.js +1 -1
- package/dist/retained-directory-replacement.d.ts +1 -0
- package/dist/retained-directory-replacement.js +1 -1
- package/dist/root-context.js +3 -7
- package/dist/root-create-input.d.ts +1 -1
- package/dist/root-directory-creation.d.ts +1 -1
- package/dist/root-directory-creation.js +1 -1
- package/dist/root-directory-list.js +3 -7
- package/dist/root-entries.js +2 -2
- package/dist/root-errors.d.ts +4 -0
- package/dist/root-errors.js +5 -3
- package/dist/root-file-final-admission.d.ts +1 -1
- package/dist/root-file-final-admission.js +1 -6
- package/dist/root-file.js +2 -5
- package/dist/root-impl.d.ts +0 -5
- package/dist/root-impl.js +22 -21
- package/dist/root-move-noreplace.js +4 -10
- package/dist/root-observed-path.js +2 -4
- package/dist/root-options.d.ts +1 -1
- package/dist/root-path-existing.js +2 -3
- package/dist/root-path-stat.js +2 -4
- package/dist/root-public-types.d.ts +11 -0
- package/dist/root-remove-identity.js +2 -4
- package/dist/root-remove.js +2 -4
- package/dist/root-write-admission.d.ts +1 -1
- package/dist/root-write-admission.js +3 -7
- package/dist/root-write-complete-parent.js +2 -3
- package/dist/root-write-verification.d.ts +1 -1
- package/dist/root.d.ts +2 -6
- package/dist/secret-file.js +11 -17
- package/dist/secret-read-policy.js +1 -1
- package/dist/secure-file-windows.js +4 -9
- package/dist/secure-temp-dir.js +2 -7
- package/dist/secure-temp-repair.js +5 -1
- package/dist/sidecar-lock-acquire.js +8 -11
- package/dist/sidecar-lock-policy.d.ts +1 -0
- package/dist/sidecar-lock-policy.js +7 -0
- package/dist/sidecar-lock-reclaim.js +5 -6
- package/dist/sidecar-lock-stale-admission.js +2 -6
- package/dist/sidecar-lock-types.d.ts +22 -16
- package/dist/stat-observation.js +3 -10
- package/dist/strict-file-identity.d.ts +2 -0
- package/dist/strict-file-identity.js +6 -6
- package/dist/temp-target.js +3 -8
- package/dist/temp-workspace-admission.js +7 -15
- package/dist/temp-workspace-child-admission.d.ts +16 -2
- package/dist/temp-workspace-child-admission.js +65 -3
- package/dist/temp-workspace-descriptor.d.ts +1 -1
- package/dist/temp-workspace-descriptor.js +2 -4
- package/dist/text-atomic.js +1 -1
- package/dist/windows-owner.d.ts +3 -6
- package/dist/windows-owner.js +1 -1
- package/dist/windows-path-alias.d.ts +1 -0
- package/dist/windows-path-alias.js +5 -0
- package/dist/windows-security-bridge.cs +0 -2
- package/docs/advanced.md +3 -1
- package/docs/secret-file.md +13 -0
- package/docs/sidecar-lock.md +6 -0
- package/docs/store.md +6 -0
- package/docs/temp.md +8 -1
- package/docs/writing.md +5 -0
- package/package.json +8 -8
- package/dist/archive-native.d.ts +0 -10
- package/dist/archive-native.js +0 -73
- package/dist/archive-options.d.ts +0 -30
- package/dist/archive-policy.d.ts +0 -21
- package/dist/archive-policy.js +0 -38
- package/dist/archive-tar-inspect.d.ts +0 -6
- package/dist/archive-tar-inspect.js +0 -62
- package/dist/archive-tar.d.ts +0 -18
- package/dist/archive-tar.js +0 -21
- package/dist/create-directory.d.ts +0 -18
- package/dist/create-directory.js +0 -111
- package/dist/create-file-async.d.ts +0 -6
- package/dist/create-file-async.js +0 -121
- package/dist/create-file.d.ts +0 -7
- package/dist/create-file.js +0 -179
- package/dist/creation-darwin.d.ts +0 -5
- package/dist/creation-darwin.js +0 -70
- package/dist/creation-file-state.d.ts +0 -18
- package/dist/creation-file-state.js +0 -118
- package/dist/creation-path.d.ts +0 -22
- package/dist/creation-path.js +0 -83
- package/dist/creation-permissions.d.ts +0 -18
- package/dist/creation-permissions.js +0 -115
- package/dist/directory-mode-owner.d.ts +0 -20
- package/dist/directory-mode-owner.js +0 -78
- package/dist/file-store-copy-source.d.ts +0 -4
- package/dist/file-store-copy-source.js +0 -31
- package/dist/file-store-limit.d.ts +0 -1
- package/dist/file-store-limit.js +0 -7
- package/dist/file-store-path.d.ts +0 -2
- package/dist/file-store-path.js +0 -30
- package/dist/standalone-publication-path.d.ts +0 -1
- package/dist/standalone-publication-path.js +0 -6
- package/dist/temp-workspace-identity.d.ts +0 -14
- package/dist/temp-workspace-identity.js +0 -41
- package/dist/temp-workspace-permissions.d.ts +0 -3
- package/dist/temp-workspace-permissions.js +0 -32
- /package/dist/{archive-options.js → root-public-types.js} +0 -0
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
import { type BigIntStats } from "node:fs";
|
|
2
1
|
import { type OwnedFileDescriptorSync } from "./create-owned-file.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
sourcePath: string;
|
|
6
|
-
targetPath: string;
|
|
7
|
-
identity: BigIntStats;
|
|
8
|
-
assertSourceParent: () => void;
|
|
9
|
-
assertTargetParent: () => void;
|
|
10
|
-
assertBeforeMutation?: () => void;
|
|
11
|
-
verifyDescriptor?: (fd: number, path: string, links: number) => void;
|
|
12
|
-
onPublished?: () => void;
|
|
13
|
-
}): OwnedFileDescriptorSync;
|
|
2
|
+
import { type CreatedHandoffParams } from "./private-producer-handoff.js";
|
|
3
|
+
export declare function handoffCreatedFileSync(params: CreatedHandoffParams<OwnedFileDescriptorSync, void>): OwnedFileDescriptorSync;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fs
|
|
1
|
+
import fs from "node:fs";
|
|
2
2
|
import { ownFileDescriptorSync } from "./create-owned-file.js";
|
|
3
3
|
import { assertSynchronousCallbackResult } from "./mutation-authority.js";
|
|
4
4
|
import { assertInitialSource, FileHandoff, inspectLinkedFile, } from "./private-producer-handoff.js";
|
|
@@ -18,11 +18,11 @@ type HandoffPaths = HandoffParents & {
|
|
|
18
18
|
type ProducerHandoffParams = HandoffPaths & {
|
|
19
19
|
readWrite: boolean;
|
|
20
20
|
};
|
|
21
|
-
type CreatedHandoffParams = HandoffPaths & {
|
|
22
|
-
source:
|
|
21
|
+
export type CreatedHandoffParams<TSource = FileHandle, TVerification = Promise<void>> = HandoffPaths & {
|
|
22
|
+
source: TSource;
|
|
23
23
|
identity: BigIntStats;
|
|
24
24
|
assertBeforeMutation?: () => void;
|
|
25
|
-
verifyDescriptor?: (fd: number, path: string, links: number) =>
|
|
25
|
+
verifyDescriptor?: (fd: number, path: string, links: number) => TVerification;
|
|
26
26
|
onPublished?: () => void;
|
|
27
27
|
};
|
|
28
28
|
export declare function assertInitialSource(stat: BigIntStats): void;
|
|
@@ -12,9 +12,8 @@ import { registerTempPathForExit, } from "./temp-cleanup.js";
|
|
|
12
12
|
import { TempWorkspaceCleanupCapability, TempWorkspaceCleanupOwner, throwTempWorkspaceCreationFailure, } from "./temp-workspace-owner.js";
|
|
13
13
|
import { assertNoWindowsPathAlias, hasWindowsPathAlias, } from "./windows-path-alias.js";
|
|
14
14
|
import { TempWorkspaceRetainedChild } from "./temp-workspace-descriptor.js";
|
|
15
|
-
import { validateInitialTempWorkspaceChild } from "./temp-workspace-child-admission.js";
|
|
15
|
+
import { validateInitialTempWorkspaceChild, validateTempWorkspaceDirMode } from "./temp-workspace-child-admission.js";
|
|
16
16
|
import { admitTempWorkspaceRoot, admitTempWorkspaceRootSync, } from "./temp-workspace-admission.js";
|
|
17
|
-
import { validateTempWorkspaceDirMode } from "./temp-workspace-permissions.js";
|
|
18
17
|
function resolveTempWorkspaceCleanupSafety(value) {
|
|
19
18
|
if (value === undefined || value === "compatible")
|
|
20
19
|
return "compatible";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type BigIntStats } from "node:fs";
|
|
2
2
|
import { type AnyAsyncDirectoryGuard } from "./directory-guard.js";
|
|
3
|
-
import type { PublishedWriteIdentity } from "./pinned-write.js";
|
|
3
|
+
import type { PublishedWriteIdentity } from "./pinned-write-types.js";
|
|
4
4
|
export declare function publishCopyStage(params: {
|
|
5
5
|
temporaryPath: string;
|
|
6
6
|
targetPath: string;
|
package/dist/publish-file.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { type BigIntStats, type Stats } from "node:fs";
|
|
|
2
2
|
import { type DirectoryReceipt, type DirectorySyncOutcome } from "./directory-durability.js";
|
|
3
3
|
import { type FileIdentityStat } from "./file-identity.js";
|
|
4
4
|
import { type PublishFileExclusiveSyncFailurePolicy } from "./publish-file-failure.js";
|
|
5
|
-
export type { PublishFileExclusiveCleanup, PublishFileExclusiveDirectorySyncFailure, PublishFileExclusiveFailureDetails, PublishFileExclusiveFailurePhase, PublishFileExclusiveSyncFailurePolicy, } from "./publish-file-failure.js";
|
|
6
5
|
export type PublishFileExclusiveStrategy = "link-or-copy" | "link-required" | "rename-noreplace";
|
|
7
6
|
export type PublishFileExclusiveResult = {
|
|
8
7
|
method: "hardlink" | "exclusive-copy" | "rename-noreplace";
|
package/dist/publish-file.js
CHANGED
|
@@ -12,9 +12,8 @@ import { getNativeBinding, requireNativeBinding } from "./native.js";
|
|
|
12
12
|
import { captureNativeFdClose } from "./native-binding.js";
|
|
13
13
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
14
14
|
import { directorySyncFailure, publicationFailure, rememberCreatedTarget, } from "./publish-file-failure.js";
|
|
15
|
-
import { admitStandalonePublicationPath } from "./
|
|
15
|
+
import { admitStandalonePublicationPath, assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
16
16
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
17
|
-
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
18
17
|
import { hasErrorCode } from "./file-cleanup.js";
|
|
19
18
|
import { writeAllToFile } from "./write-file-handle.js";
|
|
20
19
|
const HARDLINK_FALLBACK_CODES = new Set(["EPERM", "EXDEV", "ENOTSUP", "EOPNOTSUPP", "ENOSYS"]);
|
|
@@ -6,11 +6,10 @@ import { assertSyncDirectoryGuard, createAsyncDirectoryGuard, inspectDirectoryId
|
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
7
7
|
import { classifyNativeRenameFailure, NATIVE_RENAME_SOURCE_IDENTITY_MISMATCH, } from "./native-rename-outcome.js";
|
|
8
8
|
import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
|
|
9
|
-
import { RetainedDirectoryReplacement } from "./retained-directory-replacement.js";
|
|
9
|
+
import { copyOperationalCode, RetainedDirectoryReplacement } from "./retained-directory-replacement.js";
|
|
10
10
|
import { assertSafePathPrefix } from "./safe-path-segment.js";
|
|
11
|
-
import { admitStandalonePublicationPath } from "./
|
|
11
|
+
import { admitStandalonePublicationPath, assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
12
12
|
import { serializePathWrite } from "./write-queue.js";
|
|
13
|
-
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
14
13
|
function distinctGuards(source, target) {
|
|
15
14
|
return source === target ? [source] : [source, target];
|
|
16
15
|
}
|
|
@@ -18,30 +17,18 @@ function assertGuardsCurrent(guards) {
|
|
|
18
17
|
for (const guard of guards)
|
|
19
18
|
assertSyncDirectoryGuard(guard);
|
|
20
19
|
}
|
|
21
|
-
function
|
|
22
|
-
const code = source?.code;
|
|
23
|
-
if (typeof code === "string") {
|
|
24
|
-
Object.defineProperty(target, "code", { configurable: true, value: code });
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function replacementFailure(error, message, details) {
|
|
20
|
+
function replacementFailure(error, message, details, cause = error) {
|
|
28
21
|
if (error instanceof FsSafeError) {
|
|
29
|
-
return new FsSafeError(error.code, message, { cause
|
|
22
|
+
return new FsSafeError(error.code, message, { cause, details });
|
|
30
23
|
}
|
|
31
|
-
const failure = new Error(message, { cause
|
|
24
|
+
const failure = new Error(message, { cause });
|
|
32
25
|
copyOperationalCode(failure, error);
|
|
33
26
|
Object.defineProperty(failure, "details", { configurable: true, value: details });
|
|
34
27
|
return failure;
|
|
35
28
|
}
|
|
36
29
|
function replacementAggregate(error, recoveryError, message, details) {
|
|
37
30
|
const combined = new AggregateError([error, recoveryError], "directory replacement operation and recovery both failed");
|
|
38
|
-
|
|
39
|
-
return new FsSafeError(error.code, message, { cause: combined, details });
|
|
40
|
-
}
|
|
41
|
-
const failure = new Error(message, { cause: combined });
|
|
42
|
-
copyOperationalCode(failure, error);
|
|
43
|
-
Object.defineProperty(failure, "details", { configurable: true, value: details });
|
|
44
|
-
return failure;
|
|
31
|
+
return replacementFailure(error, message, details, combined);
|
|
45
32
|
}
|
|
46
33
|
function isMissingDirectoryEntry(error) {
|
|
47
34
|
return error?.code === "ENOENT";
|
|
@@ -24,15 +24,8 @@ export declare function copyFallbackReplace(params: {
|
|
|
24
24
|
expectedSourceIdentity?: BigIntStats;
|
|
25
25
|
sync: boolean;
|
|
26
26
|
}): Promise<void>;
|
|
27
|
-
export declare function copyFallbackReplaceSync(params: {
|
|
27
|
+
export declare function copyFallbackReplaceSync(params: Omit<Parameters<typeof copyFallbackReplace>[0], "fsModule"> & {
|
|
28
28
|
fsModule: SyncFallbackFs;
|
|
29
|
-
src: string;
|
|
30
|
-
dest: string;
|
|
31
|
-
destinationHardlinks?: ReplaceFileDestinationHardlinkPolicy;
|
|
32
|
-
restore: ReplaceFileCopyFallbackRestorePolicy;
|
|
33
|
-
maxRestoreBytes?: number;
|
|
34
|
-
expectedSourceIdentity?: BigIntStats;
|
|
35
29
|
fchmodSync?: (fd: number, mode: number) => void;
|
|
36
|
-
sync: boolean;
|
|
37
30
|
}): void;
|
|
38
31
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import syncFs, { type BigIntStats } from "node:fs";
|
|
2
2
|
import fs, { type FileHandle } from "node:fs/promises";
|
|
3
|
-
import { type DirectoryModeOwner } from "./directory-mode-
|
|
3
|
+
import { type DirectoryModeOwner } from "./directory-mode-node.js";
|
|
4
4
|
type AsyncTempFileSystem = Pick<typeof fs, "lstat" | "open" | "writeFile">;
|
|
5
5
|
type SyncTempFileSystem = Pick<typeof syncFs, "closeSync" | "fstatSync" | "fsyncSync" | "lstatSync" | "openSync" | "writeFileSync">;
|
|
6
6
|
export type SyncFchmod = (fd: number, mode: number) => void;
|
|
@@ -12,11 +12,8 @@ export declare function pinDirectoryForMode(params: {
|
|
|
12
12
|
/** Compatibility for best-effort directory modes; admission and close still fail closed. */
|
|
13
13
|
ignoreChmodError?: boolean;
|
|
14
14
|
}): Promise<DirectoryModeOwner | undefined>;
|
|
15
|
-
export declare function applyDirectoryMode(params: {
|
|
16
|
-
fsModule: AsyncTempFileSystem;
|
|
17
|
-
dirPath: string;
|
|
15
|
+
export declare function applyDirectoryMode(params: Parameters<typeof pinDirectoryForMode>[0] & {
|
|
18
16
|
mode: number;
|
|
19
|
-
ignoreChmodError?: boolean;
|
|
20
17
|
}): Promise<void>;
|
|
21
18
|
export declare function applyDirectoryModeSync(params: {
|
|
22
19
|
fsModule: SyncTempFileSystem;
|
|
@@ -35,14 +32,9 @@ export declare function writeTempFile(params: {
|
|
|
35
32
|
handle: FileHandle;
|
|
36
33
|
identity: BigIntStats;
|
|
37
34
|
}>;
|
|
38
|
-
export declare function writeTempFileSync(params: {
|
|
35
|
+
export declare function writeTempFileSync(params: Omit<Parameters<typeof writeTempFile>[0], "fsModule"> & {
|
|
39
36
|
fsModule: SyncTempFileSystem;
|
|
40
|
-
tempPath: string;
|
|
41
|
-
content: string | Uint8Array;
|
|
42
|
-
mode: number;
|
|
43
37
|
fchmodSync?: SyncFchmod;
|
|
44
|
-
sync: boolean;
|
|
45
|
-
onIdentity?: (identity: BigIntStats) => void;
|
|
46
38
|
}): {
|
|
47
39
|
fd: number;
|
|
48
40
|
identity: BigIntStats;
|
|
@@ -3,7 +3,7 @@ import syncFs, {} from "node:fs";
|
|
|
3
3
|
import fs, {} from "node:fs/promises";
|
|
4
4
|
import { FsSafeError } from "./errors.js";
|
|
5
5
|
import { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
6
|
-
import { ownDirectoryMode } from "./directory-mode-
|
|
6
|
+
import { ownDirectoryMode } from "./directory-mode-node.js";
|
|
7
7
|
export async function syncDirectoryBestEffort(fsModule, dirPath) {
|
|
8
8
|
let handle;
|
|
9
9
|
try {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { RenameIdentityPolicy } from "./pinned-write.js";
|
|
2
|
-
export type { RenameIdentityPolicy };
|
|
1
|
+
import type { RenameIdentityPolicy } from "./pinned-write-types.js";
|
|
3
2
|
export declare function validateRenameIdentity(policy: RenameIdentityPolicy | undefined): void;
|
|
4
3
|
export declare function atomicExpectedContentHash(policy: RenameIdentityPolicy | undefined, content: string | Uint8Array): string | undefined;
|
|
5
4
|
export declare function withAtomicRenameIdentityLock<T>(filePath: string, fn: () => Promise<T>): Promise<T>;
|
package/dist/replace-file.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import syncFs from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
|
-
import
|
|
4
|
-
import { type
|
|
3
|
+
import type { RenameIdentityPolicy } from "./pinned-write-types.js";
|
|
4
|
+
import { type ReplaceFileCopyFallbackRestorePolicy, type ReplaceFileDestinationHardlinkPolicy } from "./replace-file-copy-fallback.js";
|
|
5
5
|
export type ReplaceFileAtomicFileSystem = {
|
|
6
6
|
promises: Pick<typeof fs, "mkdir" | "writeFile" | "rename" | "copyFile" | "unlink" | "rm" | "open" | "stat" | "lstat"> & {
|
|
7
7
|
/** @deprecated Accepted for adapter compatibility but never called. */
|
|
@@ -13,7 +13,6 @@ export type ReplaceFileAtomicSyncFileSystem = Pick<typeof syncFs, "mkdirSync" |
|
|
|
13
13
|
chmodSync?: typeof syncFs.chmodSync;
|
|
14
14
|
fchmodSync?: typeof syncFs.fchmodSync;
|
|
15
15
|
};
|
|
16
|
-
export type { RenameIdentityPolicy, ReplaceFileAtomicRestoreCleanup, ReplaceFileAtomicRestoreFailureDetails, ReplaceFileCopyFallbackRestorePolicy, ReplaceFileDestinationHardlinkPolicy, };
|
|
17
16
|
type ReplaceFileAtomicBaseOptions = {
|
|
18
17
|
filePath: string;
|
|
19
18
|
content: string | Uint8Array;
|
|
@@ -56,3 +55,4 @@ export type ReplaceFileAtomicResult = {
|
|
|
56
55
|
export declare function replaceFileAtomic(options: ReplaceFileAtomicOptions): Promise<ReplaceFileAtomicResult>;
|
|
57
56
|
export declare function replaceFileAtomicWithDirectorySync(options: ReplaceFileAtomicOptions, syncParent?: (directoryPath: string) => Promise<unknown>): Promise<ReplaceFileAtomicResult>;
|
|
58
57
|
export declare function replaceFileAtomicSync(options: ReplaceFileAtomicSyncOptions): ReplaceFileAtomicResult;
|
|
58
|
+
export {};
|
package/dist/replace-file.js
CHANGED
|
@@ -9,7 +9,7 @@ import { inheritedRegularFileMode } from "./replace-file-mode.js";
|
|
|
9
9
|
import { atomicExpectedContentHash, validateRenameIdentity, withAtomicRenameIdentityLock, withAtomicRenameIdentityLockSync, } from "./replace-file-rename-policy.js";
|
|
10
10
|
import { AsyncAtomicTempOwner, SyncAtomicTempOwner } from "./replace-file-temp-owner.js";
|
|
11
11
|
import { assertSafePathPrefix } from "./safe-path-segment.js";
|
|
12
|
-
import { admitStandalonePublicationPath } from "./
|
|
12
|
+
import { admitStandalonePublicationPath } from "./windows-path-alias.js";
|
|
13
13
|
import { sleep, sleepSync } from "./timing.js";
|
|
14
14
|
import { serializePathWrite } from "./write-queue.js";
|
|
15
15
|
import { hasErrorCode, readErrorCode } from "./file-cleanup.js";
|
|
@@ -6,6 +6,7 @@ export type RetainedReplacementParent = Readonly<{
|
|
|
6
6
|
realPath: string;
|
|
7
7
|
identity: Pick<BigIntStats, "dev" | "ino">;
|
|
8
8
|
}>;
|
|
9
|
+
export declare function copyOperationalCode(target: Error, source: unknown): void;
|
|
9
10
|
export declare class RetainedDirectoryReplacement {
|
|
10
11
|
#private;
|
|
11
12
|
private constructor();
|
|
@@ -7,7 +7,7 @@ function helperUnavailable(message, cause) {
|
|
|
7
7
|
...(cause instanceof Error ? { cause } : {}),
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
|
-
function copyOperationalCode(target, source) {
|
|
10
|
+
export function copyOperationalCode(target, source) {
|
|
11
11
|
const code = source?.code;
|
|
12
12
|
if (typeof code === "string") {
|
|
13
13
|
Object.defineProperty(target, "code", { configurable: true, value: code });
|
package/dist/root-context.js
CHANGED
|
@@ -7,7 +7,7 @@ import { sameFileIdentity } from "./file-identity.js";
|
|
|
7
7
|
import { assertNoNulPathInput, assertNoUnsafeDeviceReadPath, hasNodeErrorCode, isNotFoundPathError, isPathInside, } from "./path.js";
|
|
8
8
|
import { ROOT_PATH_ALIAS_POLICIES, resolveRootPath } from "./root-path.js";
|
|
9
9
|
import { admitPathInsideRoot } from "./root-boundary.js";
|
|
10
|
-
import { outsideWorkspaceError, rootPathChangedError } from "./root-errors.js";
|
|
10
|
+
import { errorCauseOptions, outsideWorkspaceError, rootPathChangedError } from "./root-errors.js";
|
|
11
11
|
import { isDriveRelativePath } from "./safe-path-segment.js";
|
|
12
12
|
import { realpathSync } from "./realpath.js";
|
|
13
13
|
import { inspectFileIdentity } from "./strict-file-identity.js";
|
|
@@ -223,14 +223,10 @@ export async function resolvePathInRoot(root, relativePath, options) {
|
|
|
223
223
|
throw error;
|
|
224
224
|
}
|
|
225
225
|
if (hasNodeErrorCode(error, "ENAMETOOLONG")) {
|
|
226
|
-
throw new FsSafeError("invalid-path", "relative path is too long",
|
|
227
|
-
cause: error instanceof Error ? error : undefined,
|
|
228
|
-
});
|
|
226
|
+
throw new FsSafeError("invalid-path", "relative path is too long", errorCauseOptions(error));
|
|
229
227
|
}
|
|
230
228
|
const code = options?.aliasErrorCode ?? "outside-workspace";
|
|
231
|
-
throw new FsSafeError(code, code === "path-alias" ? "path alias escape blocked" : "file is outside workspace root",
|
|
232
|
-
cause: error instanceof Error ? error : undefined,
|
|
233
|
-
});
|
|
229
|
+
throw new FsSafeError(code, code === "path-alias" ? "path alias escape blocked" : "file is outside workspace root", errorCauseOptions(error));
|
|
234
230
|
}
|
|
235
231
|
return { rootReal: root.rootReal, rootWithSep: root.rootWithSep, resolved };
|
|
236
232
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PinnedWriteInput } from "./pinned-write.js";
|
|
1
|
+
import type { PinnedWriteInput } from "./pinned-write-types.js";
|
|
2
2
|
import type { RootCreateOptions, RootCreateStreamOptions, RootWriteOptions } from "./root-options.js";
|
|
3
3
|
declare const exclusiveSidecarCreate: unique symbol;
|
|
4
4
|
export declare const sidecarExclusiveCreate: Readonly<{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PinnedWriteMutationAdmission } from "./pinned-write.js";
|
|
1
|
+
import type { PinnedWriteMutationAdmission } from "./pinned-write-types.js";
|
|
2
2
|
import { type RootContext } from "./root-context.js";
|
|
3
3
|
/**
|
|
4
4
|
* Complete the common Root.mkdir case with one exact existing parent. This is
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fsSync, {} from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { assertPrivateDirectory } from "./creation-
|
|
4
|
+
import { assertPrivateDirectory } from "./creation-boundary.js";
|
|
5
5
|
import { assertAsyncDirectoryGuard, assertDirectoryIdentitySync, assertSyncDirectoryGuard, createAsyncDirectoryGuard, inspectDirectoryIdentitySync, } from "./directory-guard.js";
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
7
7
|
import { mkdirPathComponentsWithGuards } from "./guarded-mkdir.js";
|
|
@@ -7,7 +7,7 @@ import { FsSafeError } from "./errors.js";
|
|
|
7
7
|
import { inspectNativeDirectoryObservation, isNativeDirectoryObservationGuard, } from "./native-directory-observation.js";
|
|
8
8
|
import { isNotFoundPathError } from "./path.js";
|
|
9
9
|
import { assertRootIdentityCurrent } from "./root-context.js";
|
|
10
|
-
import { rootPathChangedError } from "./root-errors.js";
|
|
10
|
+
import { errorCauseOptions, rootPathChangedError } from "./root-errors.js";
|
|
11
11
|
import { admitPathInsideRoot } from "./root-boundary.js";
|
|
12
12
|
import { createSuppressedError } from "./suppressed-error.js";
|
|
13
13
|
import { realpathSync } from "./realpath.js";
|
|
@@ -50,9 +50,7 @@ export async function createRootDirectoryObservationGuard(root, directory) {
|
|
|
50
50
|
function directoryChangedError(error) {
|
|
51
51
|
if (error instanceof FsSafeError && error.code === "path-mismatch")
|
|
52
52
|
return error;
|
|
53
|
-
return new FsSafeError("path-mismatch", "directory changed during operation",
|
|
54
|
-
cause: error instanceof Error ? error : undefined,
|
|
55
|
-
});
|
|
53
|
+
return new FsSafeError("path-mismatch", "directory changed during operation", errorCauseOptions(error));
|
|
56
54
|
}
|
|
57
55
|
export async function assertRootDirectoryObservationGuard(root, guard) {
|
|
58
56
|
if (isNativeDirectoryObservationGuard(guard)) {
|
|
@@ -162,9 +160,7 @@ export function assertRootPathObservationReceiptCurrent(root, receipt, finalTarg
|
|
|
162
160
|
}
|
|
163
161
|
function normalizeDirectoryError(error) {
|
|
164
162
|
if (isNotFoundPathError(error)) {
|
|
165
|
-
return new FsSafeError("not-found", "directory not found",
|
|
166
|
-
cause: error instanceof Error ? error : undefined,
|
|
167
|
-
});
|
|
163
|
+
return new FsSafeError("not-found", "directory not found", errorCauseOptions(error));
|
|
168
164
|
}
|
|
169
165
|
return error;
|
|
170
166
|
}
|
package/dist/root-entries.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FsSafeError } from "./errors.js";
|
|
2
|
-
import {
|
|
2
|
+
import { validatePinnedRelativePath } from "./pinned-operation.js";
|
|
3
3
|
import { resolvePathInRoot } from "./root-context.js";
|
|
4
4
|
import { openRootDirectoryListing } from "./root-directory-list.js";
|
|
5
5
|
import { readSymlinkResolution } from "./root-symlink-policy.js";
|
|
@@ -13,7 +13,7 @@ export async function* entriesInRoot(root, relativePath, options) {
|
|
|
13
13
|
throw new TypeError(`invalid root entries order: ${String(options.order)}`);
|
|
14
14
|
}
|
|
15
15
|
options.signal?.throwIfAborted();
|
|
16
|
-
|
|
16
|
+
validatePinnedRelativePath(relativePath);
|
|
17
17
|
const resolved = await resolvePathInRoot(root, relativePath, {
|
|
18
18
|
...readSymlinkResolution(options.symlinks),
|
|
19
19
|
resolveCanonical: true,
|
package/dist/root-errors.d.ts
CHANGED
|
@@ -10,3 +10,7 @@ export declare function normalizePinnedPathError(error: unknown, details?: FsSaf
|
|
|
10
10
|
export declare function normalizeRemoveGuardError(error: unknown, details?: FsSafeErrorDetails): Error;
|
|
11
11
|
export declare function normalizeRemovePathError(error: unknown, details?: FsSafeErrorDetails): Error;
|
|
12
12
|
export declare function throwFsSafeReadError(error: unknown, label: string): never;
|
|
13
|
+
/** Existing boundaries retain only Error instances as their cause. */
|
|
14
|
+
export declare function errorCauseOptions(error: unknown): {
|
|
15
|
+
cause: Error | undefined;
|
|
16
|
+
};
|
package/dist/root-errors.js
CHANGED
|
@@ -41,9 +41,7 @@ export function normalizePinnedWriteError(error) {
|
|
|
41
41
|
const message = code
|
|
42
42
|
? `${PINNED_WRITE_ERRNO_MESSAGES.get(code) ?? "filesystem write failed"} (${code})`
|
|
43
43
|
: "path is not a regular file under root";
|
|
44
|
-
return new FsSafeError("invalid-path", message,
|
|
45
|
-
cause: error instanceof Error ? error : undefined,
|
|
46
|
-
});
|
|
44
|
+
return new FsSafeError("invalid-path", message, errorCauseOptions(error));
|
|
47
45
|
}
|
|
48
46
|
export function normalizePinnedPathError(error, details) {
|
|
49
47
|
if (error instanceof FsSafeError) {
|
|
@@ -88,3 +86,7 @@ export function throwFsSafeReadError(error, label) {
|
|
|
88
86
|
}
|
|
89
87
|
throw error;
|
|
90
88
|
}
|
|
89
|
+
/** Existing boundaries retain only Error instances as their cause. */
|
|
90
|
+
export function errorCauseOptions(error) {
|
|
91
|
+
return { cause: error instanceof Error ? error : undefined };
|
|
92
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import type
|
|
2
|
+
import { type PinnedOpenSyncFinalAdmission } from "./pinned-open.js";
|
|
3
3
|
export type RootFileAdmissionFs = Pick<typeof fs, "lstatSync" | "realpathSync">;
|
|
4
4
|
type ExactIdentity = Readonly<{
|
|
5
5
|
dev: bigint;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import { FsSafeError } from "./errors.js";
|
|
3
|
+
import { isExpectedPathError } from "./pinned-open.js";
|
|
3
4
|
import { realpathSync } from "./realpath.js";
|
|
4
5
|
import { admitPathInsideRoot } from "./root-boundary.js";
|
|
5
6
|
import { hardlinkedPathNotAllowedError } from "./root-errors.js";
|
|
@@ -8,12 +9,6 @@ import { assertNoWindowsPathAlias, pathForWindowsFilesystem } from "./windows-pa
|
|
|
8
9
|
function rootIdentityMismatch(cause) {
|
|
9
10
|
return new FsSafeError("path-mismatch", "canonical root directory identity changed or could not be verified", cause === undefined ? {} : { cause });
|
|
10
11
|
}
|
|
11
|
-
function isExpectedPathError(error) {
|
|
12
|
-
const code = typeof error === "object" && error !== null && "code" in error
|
|
13
|
-
? String(error.code)
|
|
14
|
-
: "";
|
|
15
|
-
return code === "ENOENT" || code === "ENOTDIR" || code === "ELOOP";
|
|
16
|
-
}
|
|
17
12
|
function inspectCanonicalRoot(ioFs, rootPath, expected) {
|
|
18
13
|
try {
|
|
19
14
|
assertNoWindowsPathAlias(rootPath);
|
package/dist/root-file.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { resolveRootPathSyncWithCanonicalRootObservation, resolveRootPathWithCanonicalRootObservation, } from "./root-path.js";
|
|
4
4
|
import { readSymlinkResolution } from "./root-symlink-policy.js";
|
|
5
|
-
import { openPinnedFileSync, } from "./pinned-open.js";
|
|
5
|
+
import { isExpectedPathError, openPinnedFileSync, } from "./pinned-open.js";
|
|
6
6
|
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
7
7
|
import { FsSafeError } from "./errors.js";
|
|
8
8
|
import { createRootFileFinalAdmission, observeCanonicalRoot, } from "./root-file-final-admission.js";
|
|
@@ -198,10 +198,7 @@ function snapshotAsyncResolution(params, absolutePath) {
|
|
|
198
198
|
function toRootObservationError(error) {
|
|
199
199
|
if (error instanceof FsSafeError)
|
|
200
200
|
return toBoundaryValidationError(error);
|
|
201
|
-
|
|
202
|
-
? String(error.code)
|
|
203
|
-
: "";
|
|
204
|
-
if (code === "ENOENT" || code === "ENOTDIR" || code === "ELOOP") {
|
|
201
|
+
if (isExpectedPathError(error)) {
|
|
205
202
|
return { ok: false, reason: "path", error };
|
|
206
203
|
}
|
|
207
204
|
return { ok: false, reason: "io", error };
|
package/dist/root-impl.d.ts
CHANGED
|
@@ -7,13 +7,8 @@ import { type RootContext } from "./root-context.js";
|
|
|
7
7
|
import type { DirEntry, PathStat } from "./types.js";
|
|
8
8
|
import { type RootWalkEntry, type RootWalkOptions } from "./root-walk.js";
|
|
9
9
|
import { type RootAppendOptions, type RootCopyOptions, type RootCopySource, type RootCreateJsonOptions, type RootCreateOptions, type RootCreateStreamOptions, type RootDefaults, type RootMkdirOptions, type RootMoveOptions, type RootOpenOptions, type RootOpenWritableOptions, type RootReadOptions, type RootRemoveOptions, type RootWriteJsonOptions, type RootWriteOptions } from "./root-options.js";
|
|
10
|
-
export type { HardlinkPolicy, RootAppendOptions, RootCopyOptions, RootCopySource, RootCreateJsonOptions, RootCreateOptions, RootCreateStreamOptions, RootDefaults, RootMkdirOptions, RootMoveOptions, RootOpenOptions, RootOpenWritableOptions, RootOptions, RootReadOptions, RootRemoveOptions, RootWriteJsonOptions, RootWriteOptions, WritableOpenMode, } from "./root-options.js";
|
|
11
10
|
export { DEFAULT_ROOT_MAX_BYTES } from "./root-options.js";
|
|
12
|
-
export type { DenyMutationPolicy } from "./deny-mutations.js";
|
|
13
|
-
export type { RenameIdentityPolicy } from "./pinned-write.js";
|
|
14
|
-
export type { MutationSymlinkPolicy, SymlinkPolicy } from "./root-symlink-policy.js";
|
|
15
11
|
export { resolveOpenedFileRealPathForHandle } from "./opened-realpath.js";
|
|
16
|
-
export type { ReadResult } from "./read-opened-file.js";
|
|
17
12
|
export type OpenResult = {
|
|
18
13
|
handle: FileHandle;
|
|
19
14
|
containment: ContainmentGuarantee;
|
package/dist/root-impl.js
CHANGED
|
@@ -56,7 +56,7 @@ import fs from "node:fs/promises";
|
|
|
56
56
|
import path from "node:path";
|
|
57
57
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
58
58
|
import { assertCopySourceCurrent, resolveFileCopyCloneMode } from "./copy-file-input.js";
|
|
59
|
-
import { assertPrivateFileCreationAvailable, resolveCreationPermissions } from "./creation-
|
|
59
|
+
import { assertPrivateFileCreationAvailable, resolveCreationPermissions } from "./creation-boundary.js";
|
|
60
60
|
import { assertAsyncDirectoryGuard, assertSyncDirectoryGuard, createAsyncDirectoryGuard, createNearestExistingDirectoryGuard } from "./directory-guard.js";
|
|
61
61
|
import { FsSafeError } from "./errors.js";
|
|
62
62
|
import { syncDirectoryBestEffort } from "./directory-durability.js";
|
|
@@ -68,7 +68,7 @@ import { openedPathResolutionError, recordExclusiveCreateFailure, recordOpenedFi
|
|
|
68
68
|
import { runPinnedWriteHelper, runPinnedWriteWithRenamePolicy } from "./pinned-write.js";
|
|
69
69
|
import { preparePinnedWriteMutationAdmission, snapshotPinnedMutationPolicy } from "./pinned-mutation-admission.js";
|
|
70
70
|
import { getNativeBinding } from "./native.js";
|
|
71
|
-
import {
|
|
71
|
+
import { validatePinnedRelativePath } from "./pinned-operation.js";
|
|
72
72
|
import { PATH_ALIAS_POLICIES } from "./path-policy.js";
|
|
73
73
|
import { assertNoNulPathInput, hasNodeErrorCode, isNotFoundPathError, isSymlinkOpenError, } from "./path.js";
|
|
74
74
|
import { readOpenedFileSafely } from "./read-opened-file.js";
|
|
@@ -86,7 +86,7 @@ import { statResolvedPathInRoot } from "./root-path-stat.js";
|
|
|
86
86
|
import { entriesInRoot } from "./root-entries.js";
|
|
87
87
|
import { assertMoveMutationAllowed } from "./root-move-preflight.js";
|
|
88
88
|
import { assertRootIdentityCurrent, assertRootIdentityCurrentSync, assertValidRootDestinationPath, assertValidRootRelativePath, ensureTrailingSep, expandRelativePathWithHome, resolvePathInRoot, resolveRootContext, rootRelativeReadPath, } from "./root-context.js";
|
|
89
|
-
import { fileNotFoundError, hardlinkedPathNotAllowedError, isAlreadyExistsError, normalizePinnedPathError, normalizePinnedWriteError, outsideWorkspaceError, } from "./root-errors.js";
|
|
89
|
+
import { errorCauseOptions, fileNotFoundError, hardlinkedPathNotAllowedError, isAlreadyExistsError, normalizePinnedPathError, normalizePinnedWriteError, outsideWorkspaceError, } from "./root-errors.js";
|
|
90
90
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
91
91
|
import { stringifyJsonDocument } from "./json-stringify.js";
|
|
92
92
|
import { walkRoot } from "./root-walk.js";
|
|
@@ -304,6 +304,9 @@ export class RootHandle {
|
|
|
304
304
|
mode: this.defaults.mode,
|
|
305
305
|
renameIdentity: this.defaults.renameIdentity,
|
|
306
306
|
...this.mutationOptions(options),
|
|
307
|
+
atomic: undefined,
|
|
308
|
+
private: undefined,
|
|
309
|
+
strictFileSync: undefined,
|
|
307
310
|
relativePath,
|
|
308
311
|
data,
|
|
309
312
|
durable: options.durable ?? this.defaults.durable ?? true,
|
|
@@ -364,18 +367,19 @@ export class RootHandle {
|
|
|
364
367
|
}
|
|
365
368
|
async stat(relativePath) {
|
|
366
369
|
assertValidRootRelativePath(relativePath);
|
|
367
|
-
|
|
370
|
+
validatePinnedRelativePath(relativePath);
|
|
368
371
|
return await statPathFallback(this.context, relativePath);
|
|
369
372
|
}
|
|
370
373
|
async list(relativePath, options = {}) {
|
|
371
374
|
assertValidRootRelativePath(relativePath);
|
|
372
|
-
|
|
375
|
+
validatePinnedRelativePath(relativePath);
|
|
373
376
|
return await listPathFallback(this.context, relativePath, options.withFileTypes === true);
|
|
374
377
|
}
|
|
375
378
|
async move(fromRelative, toRelative, options = {}) {
|
|
376
379
|
assertValidRootRelativePath(fromRelative);
|
|
377
380
|
assertValidRootDestinationPath(toRelative);
|
|
378
|
-
|
|
381
|
+
validatePinnedRelativePath(fromRelative);
|
|
382
|
+
validatePinnedRelativePath(toRelative);
|
|
379
383
|
const mutationOptions = this.mutationOptions(options);
|
|
380
384
|
const { assertBeforeMutation } = mutationOptions;
|
|
381
385
|
const { denyMutations, mutationSymlinks } = snapshotPinnedMutationPolicy(mutationOptions.denyMutations, mutationOptions.mutationSymlinks) ?? {};
|
|
@@ -407,7 +411,7 @@ export class RootHandle {
|
|
|
407
411
|
rootReal: this.context.rootReal,
|
|
408
412
|
stat: relative => this.stat(relative),
|
|
409
413
|
list: async (relative, listingOptions) => {
|
|
410
|
-
|
|
414
|
+
validatePinnedRelativePath(relative);
|
|
411
415
|
const resolved = await resolvePinnedPathInRoot(this.context, { relativePath: relative, allowRoot: true });
|
|
412
416
|
return await openRootDirectoryListing(this.context, resolved.resolved, listingOptions);
|
|
413
417
|
},
|
|
@@ -503,7 +507,6 @@ async function openWritableFileInRoot(root, params, options) {
|
|
|
503
507
|
relativePath: params.relativePath, guardedTarget, mkdir: params.mkdir,
|
|
504
508
|
assertBeforeMutation: params.assertBeforeMutation,
|
|
505
509
|
}) : undefined;
|
|
506
|
-
const mutationAdmission = prepared?.mutationAdmission;
|
|
507
510
|
const preparedParent = prepared?.preparedParent;
|
|
508
511
|
let ioPath = prepared?.targetPath ?? (params.mkdir === false ? resolved :
|
|
509
512
|
await prepareRootWriteTarget(root, resolved, params.assertBeforeMutation));
|
|
@@ -763,7 +766,7 @@ async function appendFileInRoot(root, params) {
|
|
|
763
766
|
}
|
|
764
767
|
}
|
|
765
768
|
async function removePathInRoot(root, params) {
|
|
766
|
-
|
|
769
|
+
validatePinnedRelativePath(params.relativePath);
|
|
767
770
|
const removalReceipts = params.recursive ? undefined : new RemovalPathReceipts();
|
|
768
771
|
const resolved = await resolvePinnedPathInRoot(root, {
|
|
769
772
|
relativePath: params.relativePath,
|
|
@@ -783,7 +786,7 @@ async function removePathInRoot(root, params) {
|
|
|
783
786
|
}
|
|
784
787
|
async function mkdirPathInRoot(root, params) {
|
|
785
788
|
const privateMode = resolveCreationPermissions(params, true).private;
|
|
786
|
-
|
|
789
|
+
validatePinnedRelativePath(params.relativePath);
|
|
787
790
|
const policy = params.denyMutations === undefined && params.mutationSymlinks === undefined
|
|
788
791
|
? undefined
|
|
789
792
|
: snapshotPinnedMutationPolicy(params.denyMutations, params.mutationSymlinks);
|
|
@@ -862,7 +865,7 @@ async function commitPinnedWriteInRoot(root, pinned, params, input) {
|
|
|
862
865
|
overwrite: params.overwrite,
|
|
863
866
|
rejectFinalSymlink: params.mutationSymlinks !== undefined,
|
|
864
867
|
input,
|
|
865
|
-
maxBytes: params.maxBytes,
|
|
868
|
+
maxBytes: input.kind === "buffer" ? undefined : params.maxBytes,
|
|
866
869
|
rootIdentity: root.rootIdentity,
|
|
867
870
|
mutationAdmission: pinned.mutationAdmission,
|
|
868
871
|
assertBeforeMutation: params.assertBeforeMutation,
|
|
@@ -892,9 +895,7 @@ async function commitPinnedWriteInRoot(root, pinned, params, input) {
|
|
|
892
895
|
throw error;
|
|
893
896
|
}
|
|
894
897
|
if (params.overwrite === false && isAlreadyExistsError(error)) {
|
|
895
|
-
throw new FsSafeError("already-exists", "file already exists",
|
|
896
|
-
cause: error instanceof Error ? error : undefined,
|
|
897
|
-
});
|
|
898
|
+
throw new FsSafeError("already-exists", "file already exists", errorCauseOptions(error));
|
|
898
899
|
}
|
|
899
900
|
throw normalizePinnedWriteError(error);
|
|
900
901
|
}
|
|
@@ -1173,9 +1174,7 @@ async function movePathFallback(root, params) {
|
|
|
1173
1174
|
throw fileNotFoundError(error instanceof Error ? error : undefined);
|
|
1174
1175
|
}
|
|
1175
1176
|
if (hasNodeErrorCode(error, "EEXIST")) {
|
|
1176
|
-
throw new FsSafeError("already-exists", "destination exists",
|
|
1177
|
-
cause: error instanceof Error ? error : undefined,
|
|
1178
|
-
});
|
|
1177
|
+
throw new FsSafeError("already-exists", "destination exists", errorCauseOptions(error));
|
|
1179
1178
|
}
|
|
1180
1179
|
throw error;
|
|
1181
1180
|
}
|
|
@@ -1193,7 +1192,11 @@ async function writeFileFallback(root, params) {
|
|
|
1193
1192
|
const policy = snapshotPinnedMutationPolicy(params.denyMutations, params.mutationSymlinks);
|
|
1194
1193
|
if (policy)
|
|
1195
1194
|
params = { ...params, ...policy };
|
|
1196
|
-
const { rootReal, resolved } = await resolveGuardedWritePathInRoot(root,
|
|
1195
|
+
const { rootReal, resolved } = await resolveGuardedWritePathInRoot(root, {
|
|
1196
|
+
relativePath: params.relativePath,
|
|
1197
|
+
denyMutations: params.denyMutations,
|
|
1198
|
+
mutationSymlinks: params.mutationSymlinks,
|
|
1199
|
+
});
|
|
1197
1200
|
await withRootFallbackCompatibilityLock({
|
|
1198
1201
|
rootPath: rootReal, rootIdentity: root.rootIdentity, targetPath: resolved, assertBeforeMutation: params.assertBeforeMutation,
|
|
1199
1202
|
}, async ({ targetPath, ...binding }) => await writeFileFallbackUnlocked(root, { ...params, ...binding }, targetPath));
|
|
@@ -1422,9 +1425,7 @@ async function writeMissingFileFallback(root, params, expectedWritePath) {
|
|
|
1422
1425
|
if (verifyingPublication)
|
|
1423
1426
|
throw err;
|
|
1424
1427
|
if (hasNodeErrorCode(err, "EEXIST")) {
|
|
1425
|
-
throw new FsSafeError("already-exists", "file already exists",
|
|
1426
|
-
cause: err instanceof Error ? err : undefined,
|
|
1427
|
-
});
|
|
1428
|
+
throw new FsSafeError("already-exists", "file already exists", errorCauseOptions(err));
|
|
1428
1429
|
}
|
|
1429
1430
|
throw err;
|
|
1430
1431
|
}
|