@openclaw/fs-safe 0.8.2 → 0.8.4
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 +19 -0
- package/README.md +1 -1
- package/dist/absolute-path.d.ts.map +1 -1
- package/dist/absolute-path.js +8 -7
- package/dist/advanced.d.ts +2 -2
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +2 -2
- package/dist/archive-kind.d.ts +1 -0
- package/dist/archive-kind.d.ts.map +1 -1
- package/dist/archive-kind.js +6 -0
- package/dist/archive-limits.d.ts +0 -1
- package/dist/archive-limits.d.ts.map +1 -1
- package/dist/archive-limits.js +0 -3
- package/dist/archive-native.d.ts +1 -0
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +20 -76
- package/dist/archive-parser-errors.d.ts +2 -0
- package/dist/archive-parser-errors.d.ts.map +1 -0
- package/dist/archive-parser-errors.js +12 -0
- package/dist/archive-plan.d.ts +20 -0
- package/dist/archive-plan.d.ts.map +1 -0
- package/dist/archive-plan.js +55 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +7 -13
- package/dist/archive-tar-inspect.d.ts +7 -0
- package/dist/archive-tar-inspect.d.ts.map +1 -0
- package/dist/archive-tar-inspect.js +59 -0
- package/dist/archive-tar-wasm.d.ts +1 -1
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +5 -8
- package/dist/archive-tar.d.ts +3 -1
- package/dist/archive-tar.d.ts.map +1 -1
- package/dist/archive-tar.js +12 -49
- package/dist/archive.d.ts +1 -0
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +54 -33
- package/dist/atomic.d.ts +1 -1
- package/dist/atomic.d.ts.map +1 -1
- package/dist/atomic.js +1 -1
- package/dist/bounded-read-stream.d.ts +1 -5
- package/dist/bounded-read-stream.d.ts.map +1 -1
- package/dist/bounded-read-stream.js +5 -13
- package/dist/bounded-read.d.ts.map +1 -1
- package/dist/bounded-read.js +31 -4
- package/dist/byte-budget.d.ts +0 -1
- package/dist/byte-budget.d.ts.map +1 -1
- package/dist/byte-budget.js +1 -1
- package/dist/directory-durability.js +5 -5
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-guard.js +5 -6
- package/dist/directory-mode-owner.d.ts.map +1 -1
- package/dist/directory-mode-owner.js +2 -0
- package/dist/error-detail.d.ts +1 -0
- package/dist/error-detail.d.ts.map +1 -1
- package/dist/error-detail.js +6 -0
- package/dist/file-store-boundary.d.ts +1 -1
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +3 -14
- package/dist/file-store-prune.js +17 -8
- package/dist/file-store.js +3 -3
- package/dist/file-sync.d.ts +5 -0
- package/dist/file-sync.d.ts.map +1 -0
- package/dist/file-sync.js +19 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +5 -4
- package/dist/guarded-mutation.d.ts +3 -0
- package/dist/guarded-mutation.d.ts.map +1 -1
- package/dist/guarded-mutation.js +5 -1
- package/dist/home-dir.d.ts +0 -10
- package/dist/home-dir.d.ts.map +1 -1
- package/dist/home-dir.js +0 -28
- package/dist/json-durable-queue-ownership.d.ts +1 -0
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +139 -18
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +5 -10
- package/dist/json-store.d.ts.map +1 -1
- package/dist/json-store.js +1 -1
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +2 -3
- package/dist/move-path-cleanup.d.ts +1 -1
- package/dist/move-path-cleanup.d.ts.map +1 -1
- package/dist/move-path-cleanup.js +4 -2
- package/dist/move-path.d.ts +9 -0
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +53 -16
- package/dist/native-binding.d.ts +2 -1
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-operations.d.ts +0 -1
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +0 -10
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +8 -4
- package/dist/native-pinned-write.js +3 -3
- package/dist/native-staged-file.d.ts +10 -3
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +38 -13
- package/dist/opened-realpath.d.ts +12 -1
- package/dist/opened-realpath.d.ts.map +1 -1
- package/dist/opened-realpath.js +16 -14
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +26 -2
- package/dist/path-policy.js +3 -3
- package/dist/permissions.d.ts +1 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +3 -0
- package/dist/pinned-write.d.ts +2 -2
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +17 -22
- package/dist/private-temp-workspace.js +1 -1
- package/dist/publish-file.js +2 -2
- package/dist/regular-file.js +8 -8
- package/dist/replace-file-copy-source.d.ts.map +1 -1
- package/dist/replace-file-copy-source.js +2 -7
- package/dist/replace-file-descriptor.d.ts.map +1 -1
- package/dist/replace-file-descriptor.js +11 -20
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +15 -14
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +21 -8
- package/dist/root-context.js +5 -5
- package/dist/root-errors.d.ts +1 -0
- package/dist/root-errors.d.ts.map +1 -1
- package/dist/root-errors.js +9 -0
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +17 -28
- package/dist/root-impl.d.ts +2 -1
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +46 -58
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +2 -3
- package/dist/root-path-symlink.d.ts.map +1 -1
- package/dist/root-path-symlink.js +2 -3
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +51 -97
- package/dist/root-paths.d.ts.map +1 -1
- package/dist/root-paths.js +16 -15
- package/dist/root-write-mode.d.ts +6 -0
- package/dist/root-write-mode.d.ts.map +1 -0
- package/dist/root-write-mode.js +61 -0
- package/dist/root-write-verification.js +8 -8
- package/dist/safe-path-segment.d.ts +1 -0
- package/dist/safe-path-segment.d.ts.map +1 -1
- package/dist/safe-path-segment.js +1 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +4 -11
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +2 -10
- package/dist/secret-read-policy.d.ts +4 -0
- package/dist/secret-read-policy.d.ts.map +1 -1
- package/dist/secret-read-policy.js +12 -0
- package/dist/sibling-staged-file.d.ts.map +1 -1
- package/dist/sibling-staged-file.js +2 -7
- package/dist/sidecar-lock-policy.d.ts +0 -1
- package/dist/sidecar-lock-policy.d.ts.map +1 -1
- package/dist/sidecar-lock-policy.js +0 -4
- package/dist/strict-file-identity.d.ts +1 -1
- package/dist/strict-file-identity.d.ts.map +1 -1
- package/dist/string-coerce.d.ts +0 -9
- package/dist/string-coerce.d.ts.map +1 -1
- package/dist/string-coerce.js +0 -56
- package/dist/symlink-parents.d.ts.map +1 -1
- package/dist/symlink-parents.js +1 -2
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +1 -12
- package/docs/archive.md +57 -0
- package/docs/atomic.md +53 -19
- package/docs/reading.md +2 -0
- package/docs/root.md +10 -1
- package/docs/staged-file.md +6 -2
- package/docs/types.md +2 -1
- package/docs/writing.md +30 -2
- package/package.json +8 -8
- package/dist/archive-tar-extract.d.ts +0 -11
- package/dist/archive-tar-extract.d.ts.map +0 -1
- package/dist/archive-tar-extract.js +0 -49
- package/dist/fsync.d.ts +0 -2
- package/dist/fsync.d.ts.map +0 -1
- package/dist/fsync.js +0 -1
- package/dist/json-durable-queue-retirement.d.ts +0 -9
- package/dist/json-durable-queue-retirement.d.ts.map +0 -1
- package/dist/json-durable-queue-retirement.js +0 -126
- package/dist/json-durable-queue-transfer-lock.d.ts +0 -2
- package/dist/json-durable-queue-transfer-lock.d.ts.map +0 -1
- package/dist/json-durable-queue-transfer-lock.js +0 -19
- package/dist/mode.d.ts +0 -2
- package/dist/mode.d.ts.map +0 -1
- package/dist/mode.js +0 -3
- package/dist/output-sibling.d.ts +0 -8
- package/dist/output-sibling.d.ts.map +0 -1
- package/dist/output-sibling.js +0 -30
- package/dist/read-error.d.ts +0 -2
- package/dist/read-error.d.ts.map +0 -1
- package/dist/read-error.js +0 -11
- package/dist/short-path.d.ts +0 -2
- package/dist/short-path.d.ts.map +0 -1
- package/dist/short-path.js +0 -7
- package/dist/staged-file.d.ts +0 -10
- package/dist/staged-file.d.ts.map +0 -1
- package/dist/staged-file.js +0 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,yBAAyB,EACzB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,OAAO,GAAG,aAAa,GAAG,SAAS,CAAC;IAC5C,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,wBAAwB,CAAC;IACvC,sFAAsF;IACtF,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,wBAAsB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAsB1E;AAED,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,sBAAsB,GAC5B,OAAO,CAAC,eAAe,CAAC,CAuD1B;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM,CAKzF;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,eAAe,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB,GAAG,MAAM,CAYT;AASD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAEvD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAE5D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAE5D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAE5D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAE5D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD"}
|
package/dist/permissions.js
CHANGED
package/dist/pinned-write.d.ts
CHANGED
|
@@ -9,7 +9,6 @@ export type PinnedWriteInput = {
|
|
|
9
9
|
kind: "stream";
|
|
10
10
|
stream: Readable;
|
|
11
11
|
};
|
|
12
|
-
export type RenameIdentityMismatchPolicy = "throw" | "verify-content";
|
|
13
12
|
export type RenameIdentityPolicy = "strict" | "verify-content-with-lock";
|
|
14
13
|
export type PublishedWriteIdentity = Readonly<{
|
|
15
14
|
dev: bigint;
|
|
@@ -21,11 +20,12 @@ export type PinnedWriteParams = {
|
|
|
21
20
|
basename: string;
|
|
22
21
|
mkdir: boolean;
|
|
23
22
|
mode: number;
|
|
23
|
+
sync?: boolean;
|
|
24
24
|
overwrite?: boolean;
|
|
25
25
|
maxBytes?: number;
|
|
26
26
|
input: PinnedWriteInput;
|
|
27
27
|
rootIdentity?: FileIdentityStat;
|
|
28
|
-
onRenameIdentityMismatch?:
|
|
28
|
+
onRenameIdentityMismatch?: "verify-content";
|
|
29
29
|
verifyPublished?: (fd: number, identity: PublishedWriteIdentity, parentGuard: AnyAsyncDirectoryGuard) => Promise<void>;
|
|
30
30
|
};
|
|
31
31
|
export declare function runPinnedWriteHelper(params: PinnedWriteParams): Promise<FileIdentityStat>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pinned-write.d.ts","sourceRoot":"","sources":["../src/pinned-write.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pinned-write.d.ts","sourceRoot":"","sources":["../src/pinned-write.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAA4F,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAG7J,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAY3D,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAsDzC,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,0BAA0B,CAAC;AAEzE,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE5E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,CAAC;IACxB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,wBAAwB,CAAC,EAAE,gBAAgB,CAAC;IAE5C,eAAe,CAAC,EAAE,CAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,sBAAsB,EAChC,WAAW,EAAE,sBAAsB,KAChC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAgB/F;AAED,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,iBAAiB,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,oBAAoB,CAAC;CACvC,GACA,OAAO,CAAC,gBAAgB,CAAC,CA2B3B"}
|
package/dist/pinned-write.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { syncFileBestEffort } from "./file-sync.js";
|
|
1
2
|
import { randomUUID } from "node:crypto";
|
|
2
3
|
import fsSync, {} from "node:fs";
|
|
3
4
|
import fs from "node:fs/promises";
|
|
@@ -5,7 +6,7 @@ import path from "node:path";
|
|
|
5
6
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
6
7
|
import { createAsyncDirectoryGuard, createNearestExistingDirectoryGuard, inspectDirectoryIdentity } from "./directory-guard.js";
|
|
7
8
|
import { FsSafeError } from "./errors.js";
|
|
8
|
-
import { syncDirectoryBestEffort } from "./
|
|
9
|
+
import { syncDirectoryBestEffort } from "./directory-durability.js";
|
|
9
10
|
import { sameFileIdentity, sha256Hex } from "./file-identity.js";
|
|
10
11
|
import { withAsyncDirectoryGuards } from "./guarded-mutation.js";
|
|
11
12
|
import { mkdirPathComponentsWithGuards } from "./guarded-mkdir.js";
|
|
@@ -35,16 +36,6 @@ function assertWithinMaxBytes(bytes, maxBytes) {
|
|
|
35
36
|
throw new FsSafeError("too-large", `file exceeds limit of ${maxBytes} bytes (got at least ${bytes})`);
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
|
-
async function syncFileBestEffort(handle) {
|
|
39
|
-
try {
|
|
40
|
-
await handle.sync();
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
if (error?.code !== "EPERM") {
|
|
44
|
-
throw error;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
39
|
async function writeStreamToHandle(stream, handle, maxBytes) {
|
|
49
40
|
let bytes = 0;
|
|
50
41
|
for await (const chunk of stream) {
|
|
@@ -134,7 +125,7 @@ async function runPinnedWriteFallback(params) {
|
|
|
134
125
|
let created = true;
|
|
135
126
|
let createdIdentity;
|
|
136
127
|
try {
|
|
137
|
-
const verificationIdentity =
|
|
128
|
+
const verificationIdentity = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
138
129
|
createdIdentity = verificationIdentity;
|
|
139
130
|
if (params.input.kind === "buffer") {
|
|
140
131
|
assertWithinMaxBytes(byteLength(params.input.data, params.input.encoding), params.maxBytes);
|
|
@@ -150,9 +141,11 @@ async function runPinnedWriteFallback(params) {
|
|
|
150
141
|
}
|
|
151
142
|
// Content writes may clear set-ID bits; finalize them through the owned fd.
|
|
152
143
|
await handle.chmod(params.mode);
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
144
|
+
if (params.sync !== false)
|
|
145
|
+
await syncFileBestEffort(handle);
|
|
146
|
+
const stat = fsSync.fstatSync(handle.fd);
|
|
147
|
+
if (params.sync !== false)
|
|
148
|
+
await syncDirectoryBestEffort(parentPath);
|
|
156
149
|
// Publication is complete. A failed outer check must not remove its target.
|
|
157
150
|
created = false;
|
|
158
151
|
await params.verifyPublished?.(handle.fd, verificationIdentity, parentGuard);
|
|
@@ -184,7 +177,7 @@ async function runPinnedWriteFallback(params) {
|
|
|
184
177
|
let renamed = false;
|
|
185
178
|
try {
|
|
186
179
|
handle = await fs.open(tempPath, tempFlags, params.mode);
|
|
187
|
-
let verificationIdentity =
|
|
180
|
+
let verificationIdentity = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
188
181
|
tempIdentity = verificationIdentity;
|
|
189
182
|
if (params.input.kind === "buffer") {
|
|
190
183
|
assertWithinMaxBytes(byteLength(params.input.data, params.input.encoding), params.maxBytes);
|
|
@@ -198,21 +191,23 @@ async function runPinnedWriteFallback(params) {
|
|
|
198
191
|
else {
|
|
199
192
|
await writeStreamToHandle(params.input.stream, handle, params.maxBytes);
|
|
200
193
|
}
|
|
201
|
-
tempStat =
|
|
202
|
-
const tempPathStat =
|
|
194
|
+
tempStat = fsSync.fstatSync(handle.fd);
|
|
195
|
+
const tempPathStat = fsSync.lstatSync(tempPath);
|
|
203
196
|
if (tempPathStat.isSymbolicLink() || !sameFileIdentity(tempPathStat, tempStat)) {
|
|
204
197
|
throw new FsSafeError("path-mismatch", "fallback temp path changed during write");
|
|
205
198
|
}
|
|
206
199
|
const expectedTempStat = tempStat;
|
|
207
200
|
await handle.chmod(params.mode);
|
|
208
|
-
|
|
201
|
+
if (params.sync !== false)
|
|
202
|
+
await syncFileBestEffort(handle);
|
|
209
203
|
let verifiedIdentity = expectedTempStat;
|
|
210
204
|
await withAsyncDirectoryGuards([parentGuard], async () => {
|
|
211
205
|
await fs.rename(tempPath, targetPath);
|
|
212
206
|
renamed = true;
|
|
213
207
|
await getFsSafeTestHooks()?.afterPinnedWriteFallbackRename?.(targetPath);
|
|
214
|
-
|
|
215
|
-
|
|
208
|
+
if (params.sync !== false)
|
|
209
|
+
await syncDirectoryBestEffort(parentPath);
|
|
210
|
+
const targetStat = fsSync.lstatSync(targetPath);
|
|
216
211
|
if (targetStat.isSymbolicLink()) {
|
|
217
212
|
throw new FsSafeError("path-mismatch", "fallback target changed during write");
|
|
218
213
|
}
|
|
@@ -229,7 +224,7 @@ async function runPinnedWriteFallback(params) {
|
|
|
229
224
|
}
|
|
230
225
|
const expectedHash = sha256Hex(params.input.data, params.input.encoding);
|
|
231
226
|
readHandle = await fs.open(targetPath, resolveReadOpenFlags());
|
|
232
|
-
const readHandleStat =
|
|
227
|
+
const readHandleStat = fsSync.fstatSync(readHandle.fd, { bigint: true });
|
|
233
228
|
const actualHash = sha256Hex(await readHandle.readFile());
|
|
234
229
|
if (actualHash !== expectedHash) {
|
|
235
230
|
throw new FsSafeError("path-mismatch", "fallback target changed during write");
|
|
@@ -5,7 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import { fileStore, fileStoreSync, } from "./file-store.js";
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
7
7
|
import { isNotFoundPathError } from "./path.js";
|
|
8
|
-
import { throwFsSafeReadError } from "./
|
|
8
|
+
import { throwFsSafeReadError } from "./root-errors.js";
|
|
9
9
|
import { matchRootFileOpenFailure, openRootFileSync, } from "./root-file.js";
|
|
10
10
|
import { registerTempPathForExit, } from "./temp-cleanup.js";
|
|
11
11
|
import { TempWorkspaceCleanupCapability, TempWorkspaceCleanupOwner, } from "./temp-workspace-owner.js";
|
package/dist/publish-file.js
CHANGED
|
@@ -6,7 +6,7 @@ import { pinDirectory, } from "./directory-durability.js";
|
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
7
7
|
import { hashFileHandle } from "./file-hash.js";
|
|
8
8
|
import { sameFileIdentity, sameFileIdentityForCleanup, } from "./file-identity.js";
|
|
9
|
-
import {
|
|
9
|
+
import { syncFileBestEffortSync } from "./file-sync.js";
|
|
10
10
|
import { getNativeBinding, requireNativeBinding } from "./native.js";
|
|
11
11
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
12
12
|
import { directorySyncFailure, publicationFailure, rememberCreatedTarget, } from "./publish-file-failure.js";
|
|
@@ -256,7 +256,7 @@ export async function publishFileExclusive(params) {
|
|
|
256
256
|
throw error;
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
|
-
|
|
259
|
+
syncFileBestEffortSync(sourceNativeParent.handle.fd);
|
|
260
260
|
const targetIdentity = await fs.lstat(targetPath);
|
|
261
261
|
return {
|
|
262
262
|
method: "rename-noreplace",
|
package/dist/regular-file.js
CHANGED
|
@@ -31,7 +31,7 @@ function translateBoundedReadOverflow(error, filePath, maxBytes) {
|
|
|
31
31
|
export async function statRegularFile(filePath) {
|
|
32
32
|
let stat;
|
|
33
33
|
try {
|
|
34
|
-
stat =
|
|
34
|
+
stat = fsSync.lstatSync(filePath);
|
|
35
35
|
}
|
|
36
36
|
catch (err) {
|
|
37
37
|
if (isNotFoundPathError(err)) {
|
|
@@ -64,7 +64,7 @@ export async function readRegularFile(params) {
|
|
|
64
64
|
const maxBytes = normalizeMaxBytes(params.maxBytes);
|
|
65
65
|
assertNoUnsafeDeviceReadPath(params.filePath);
|
|
66
66
|
const before = await inspectFileIdentity(async () => {
|
|
67
|
-
const stat =
|
|
67
|
+
const stat = fsSync.lstatSync(params.filePath, { bigint: true });
|
|
68
68
|
assertRegularReadStat(stat, params.filePath, true);
|
|
69
69
|
return stat;
|
|
70
70
|
}).catch((error) => throwReadPreviewError(error, params.filePath));
|
|
@@ -82,15 +82,15 @@ export async function readRegularFile(params) {
|
|
|
82
82
|
throw err;
|
|
83
83
|
}
|
|
84
84
|
try {
|
|
85
|
-
const stat =
|
|
85
|
+
const stat = fsSync.fstatSync(handle.fd);
|
|
86
86
|
const identity = await inspectFileIdentity(async () => {
|
|
87
|
-
const exact =
|
|
87
|
+
const exact = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
88
88
|
assertRegularReadStat(exact, params.filePath);
|
|
89
89
|
return exact;
|
|
90
90
|
}, before);
|
|
91
91
|
try {
|
|
92
92
|
await inspectFileIdentity(async () => {
|
|
93
|
-
const current =
|
|
93
|
+
const current = fsSync.lstatSync(params.filePath, { bigint: true });
|
|
94
94
|
assertRegularReadStat(current, params.filePath);
|
|
95
95
|
return current;
|
|
96
96
|
}, identity);
|
|
@@ -245,7 +245,7 @@ export async function appendRegularFile(options) {
|
|
|
245
245
|
let preOpenStat;
|
|
246
246
|
try {
|
|
247
247
|
preOpenStat = await inspectFileIdentity(async () => {
|
|
248
|
-
const stat =
|
|
248
|
+
const stat = fsSync.lstatSync(options.filePath, { bigint: true });
|
|
249
249
|
if (stat.isSymbolicLink()) {
|
|
250
250
|
throw new Error(`Refusing to append through symlink: ${options.filePath}`);
|
|
251
251
|
}
|
|
@@ -282,12 +282,12 @@ export async function appendRegularFile(options) {
|
|
|
282
282
|
let identity;
|
|
283
283
|
try {
|
|
284
284
|
identity = await inspectFileIdentity(async () => {
|
|
285
|
-
const stat =
|
|
285
|
+
const stat = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
286
286
|
assertRegularAppendStat(stat, options.filePath);
|
|
287
287
|
return stat;
|
|
288
288
|
}, preOpenStat);
|
|
289
289
|
await inspectFileIdentity(async () => {
|
|
290
|
-
const current =
|
|
290
|
+
const current = fsSync.lstatSync(options.filePath, { bigint: true });
|
|
291
291
|
assertRegularAppendStat(current, options.filePath);
|
|
292
292
|
return current;
|
|
293
293
|
}, identity);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-file-copy-source.d.ts","sourceRoot":"","sources":["../src/replace-file-copy-source.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"replace-file-copy-source.d.ts","sourceRoot":"","sources":["../src/replace-file-copy-source.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAOnD,KAAK,qBAAqB,GAAG,IAAI,CAAC,cAAc,kBAAkB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;AACvF,KAAK,oBAAoB,GAAG,IAAI,CAC9B,OAAO,MAAM,EACb,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAClE,CAAC;AA0DF,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,QAAQ,EAAE,qBAAqB,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,WAAW,CAAC;CAChC,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA0BjD;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,WAAW,CAAC;CAChC,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA8BxC"}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import syncFs, {} from "node:fs";
|
|
2
|
+
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
2
3
|
import { FsSafeError } from "./errors.js";
|
|
3
4
|
import { sameFileIdentity } from "./file-identity.js";
|
|
4
5
|
import { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
5
|
-
const
|
|
6
|
-
? syncFs.constants.O_NOFOLLOW
|
|
7
|
-
: 0;
|
|
8
|
-
const NONBLOCK = process.platform !== "win32" && "O_NONBLOCK" in syncFs.constants
|
|
9
|
-
? syncFs.constants.O_NONBLOCK
|
|
10
|
-
: 0;
|
|
11
|
-
const OPEN_READ_FLAGS = syncFs.constants.O_RDONLY | NOFOLLOW | NONBLOCK;
|
|
6
|
+
const OPEN_READ_FLAGS = resolveReadOpenFlags();
|
|
12
7
|
const READ_CHUNK_BYTES = 64 * 1024;
|
|
13
8
|
function assertSourcePreview(source, src) {
|
|
14
9
|
if (source.isSymbolicLink()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-file-descriptor.d.ts","sourceRoot":"","sources":["../src/replace-file-descriptor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"replace-file-descriptor.d.ts","sourceRoot":"","sources":["../src/replace-file-descriptor.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAc,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAA0C,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE5G,KAAK,mBAAmB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC;AAC3E,KAAK,kBAAkB,GAAG,IAAI,CAC5B,OAAO,MAAM,EACb,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,eAAe,CACrF,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAE5D,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,EACjC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,IAAI,CAAC,OAAO,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC,EACrE,OAAO,EAAE,MAAM,GACd,IAAI,CAgBN;AA2BD,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,4FAA4F;IAC5F,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CA6B1C;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAC/C,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,OAAO,CAAC,IAAI,CAAC,CAOhB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,GAAG,IAAI,CAeP;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC1C,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;CAC9C,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,CAAC,CAuBzD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;CAC9C,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,CAoBxC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { syncFileBestEffort, syncFileBestEffortSync } from "./file-sync.js";
|
|
1
2
|
import syncFs, {} from "node:fs";
|
|
2
3
|
import fs, {} from "node:fs/promises";
|
|
3
4
|
import { FsSafeError } from "./errors.js";
|
|
@@ -61,13 +62,14 @@ export async function pinDirectoryForMode(params) {
|
|
|
61
62
|
if (process.platform === "win32") {
|
|
62
63
|
return;
|
|
63
64
|
}
|
|
64
|
-
const expected =
|
|
65
|
+
const expected = params.fsModule === fs
|
|
66
|
+
? syncFs.lstatSync(params.dirPath) : await params.fsModule.lstat(params.dirPath);
|
|
65
67
|
assertDirectory(expected, params.dirPath);
|
|
66
68
|
const handle = await params.fsModule.open(params.dirPath, directoryOpenFlags());
|
|
67
69
|
try {
|
|
68
70
|
const owner = ownDirectoryMode({
|
|
69
71
|
async inspect() {
|
|
70
|
-
const opened = await handle.stat();
|
|
72
|
+
const opened = params.fsModule === fs ? syncFs.fstatSync(handle.fd) : await handle.stat();
|
|
71
73
|
assertOwnedDirectory(expected, opened);
|
|
72
74
|
return opened.mode & 0o7777;
|
|
73
75
|
},
|
|
@@ -111,21 +113,17 @@ export function applyDirectoryModeSync(params) {
|
|
|
111
113
|
export async function writeTempFile(params) {
|
|
112
114
|
const handle = await params.fsModule.open(params.tempPath, "wx", params.mode);
|
|
113
115
|
try {
|
|
114
|
-
|
|
116
|
+
// Custom adapters retain their async-only metadata contract.
|
|
117
|
+
const inspect = () => params.fsModule === fs
|
|
118
|
+
? syncFs.fstatSync(handle.fd, { bigint: true }) : handle.stat({ bigint: true });
|
|
119
|
+
const identity = await inspectFileIdentity(inspect);
|
|
115
120
|
params.onIdentity?.(identity);
|
|
116
121
|
await params.fsModule.writeFile(handle, params.content);
|
|
117
122
|
await handle.chmod(params.mode);
|
|
118
123
|
if (params.sync) {
|
|
119
|
-
|
|
120
|
-
await handle.sync();
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
if (error.code !== "EPERM") {
|
|
124
|
-
throw error;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
124
|
+
await syncFileBestEffort(handle);
|
|
127
125
|
}
|
|
128
|
-
await inspectFileIdentity(
|
|
126
|
+
await inspectFileIdentity(inspect, identity);
|
|
129
127
|
return { handle, identity };
|
|
130
128
|
}
|
|
131
129
|
catch (error) {
|
|
@@ -146,14 +144,7 @@ export function writeTempFileSync(params) {
|
|
|
146
144
|
params.fsModule.writeFileSync(fd, params.content);
|
|
147
145
|
params.fchmodSync?.(fd, params.mode);
|
|
148
146
|
if (params.sync) {
|
|
149
|
-
|
|
150
|
-
params.fsModule.fsyncSync(fd);
|
|
151
|
-
}
|
|
152
|
-
catch (error) {
|
|
153
|
-
if (error.code !== "EPERM") {
|
|
154
|
-
throw error;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
147
|
+
syncFileBestEffortSync(fd, params.fsModule);
|
|
157
148
|
}
|
|
158
149
|
inspectFileIdentitySync(() => params.fsModule.fstatSync(fd, { bigint: true }), identity);
|
|
159
150
|
return { fd, identity };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-file-temp-owner.d.ts","sourceRoot":"","sources":["../src/replace-file-temp-owner.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAA6B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"replace-file-temp-owner.d.ts","sourceRoot":"","sources":["../src/replace-file-temp-owner.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAA6B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAO9F,KAAK,oBAAoB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC,CAAC;AACzE,KAAK,mBAAmB,GAAG,IAAI,CAC7B,OAAO,MAAM,EACb,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,GAAG,YAAY,CACrF,CAAC;AAgEF,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,WAAW,EAAE,sBAAsB,CAAC;CACrC,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBhB;AA+BD,qBAAa,oBAAoB;;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAM1B,YAAY,QAAQ,EAAE,MAAM,EAG3B;IAED,KAAK,IAAI,IAAI,CAEZ;IAED,QAAQ,CAAC,UAAU,aAAc,WAAW,KAAG,IAAI,CAGjD;IAEF,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI,CAG/D;IAED,IAAI,QAAQ,IAAI,WAAW,CAG1B;IAEK,aAAa,CAAC,QAAQ,EAAE,oBAAoB,EAAE,QAAQ,SAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3F;IAEK,eAAe,CACnB,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CA4Cf;IAED,WAAW,IAAI,IAAI,CAGlB;IAEK,MAAM,CAAC,MAAM,EAAE;QACnB,QAAQ,EAAE,oBAAoB,CAAC;QAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,mBAAmB,EAAE,OAAO,CAAC;KAC9B,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BhB;CACF;AAED,qBAAa,mBAAmB;;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAM1B,YAAY,QAAQ,EAAE,MAAM,EAG3B;IAED,KAAK,IAAI,IAAI,CAEZ;IAED,QAAQ,CAAC,UAAU,aAAc,WAAW,KAAG,IAAI,CAGjD;IAEF,KAAK,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI,CAGvD;IAED,IAAI,QAAQ,IAAI,WAAW,CAG1B;IAED,aAAa,CAAC,QAAQ,EAAE,mBAAmB,EAAE,QAAQ,SAAgB,GAAG,IAAI,CAkB3E;IAED,eAAe,CACb,QAAQ,EAAE,mBAAmB,EAC7B,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,IAAI,CAgDN;IAED,WAAW,IAAI,IAAI,CAGlB;IAED,MAAM,CAAC,MAAM,EAAE;QACb,QAAQ,EAAE,mBAAmB,CAAC;QAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,mBAAmB,EAAE,OAAO,CAAC;KAC9B,GAAG,IAAI,CAgCP;CACF"}
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import syncFs, {} from "node:fs";
|
|
2
2
|
import fs, {} from "node:fs/promises";
|
|
3
3
|
import { assertAsyncDirectoryGuard } from "./directory-guard.js";
|
|
4
|
+
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
4
5
|
import { FsSafeError } from "./errors.js";
|
|
5
6
|
import { sameFileIdentityForCleanup, sha256Hex } from "./file-identity.js";
|
|
6
7
|
import { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
7
8
|
import { registerTempPathForExit } from "./temp-cleanup.js";
|
|
8
|
-
const PUBLISHED_READ_FLAGS =
|
|
9
|
-
(process.platform !== "win32" && typeof syncFs.constants.O_NOFOLLOW === "number"
|
|
10
|
-
? syncFs.constants.O_NOFOLLOW
|
|
11
|
-
: 0) |
|
|
12
|
-
(process.platform !== "win32" && typeof syncFs.constants.O_NONBLOCK === "number"
|
|
13
|
-
? syncFs.constants.O_NONBLOCK
|
|
14
|
-
: 0);
|
|
9
|
+
const PUBLISHED_READ_FLAGS = resolveReadOpenFlags();
|
|
15
10
|
function assertOwnedFile(stat, pathname, pathnameEntry) {
|
|
16
11
|
if (stat.isSymbolicLink()) {
|
|
17
12
|
throw new FsSafeError("symlink", `Atomic replace owned file became a symlink: ${pathname}`);
|
|
@@ -38,7 +33,9 @@ async function cleanupOwnedPath(params) {
|
|
|
38
33
|
if (!params.identity)
|
|
39
34
|
return true;
|
|
40
35
|
try {
|
|
41
|
-
const current =
|
|
36
|
+
const current = params.fsModule === fs
|
|
37
|
+
? syncFs.lstatSync(params.pathname, { bigint: true })
|
|
38
|
+
: await params.fsModule.lstat(params.pathname, { bigint: true });
|
|
42
39
|
if (current.isSymbolicLink() ||
|
|
43
40
|
!current.isFile() ||
|
|
44
41
|
current.nlink !== 1n ||
|
|
@@ -66,11 +63,11 @@ export async function cleanupPinnedFilePath(params) {
|
|
|
66
63
|
if ([guard.stat.dev, guard.stat.ino].some((value) => typeof value === "number" && !Number.isSafeInteger(value)))
|
|
67
64
|
return;
|
|
68
65
|
await assertAsyncDirectoryGuard(guard);
|
|
69
|
-
const parent =
|
|
66
|
+
const parent = syncFs.lstatSync(guard.dir, { bigint: true });
|
|
70
67
|
if (parent.isSymbolicLink() || !parent.isDirectory() ||
|
|
71
68
|
!sameFileIdentityForCleanup(parent, guard.stat))
|
|
72
69
|
return;
|
|
73
|
-
const opened =
|
|
70
|
+
const opened = syncFs.fstatSync(params.handle.fd, { bigint: true });
|
|
74
71
|
if (!opened.isFile() || opened.nlink !== 1n ||
|
|
75
72
|
!sameFileIdentityForCleanup(opened, params.identity))
|
|
76
73
|
return;
|
|
@@ -136,13 +133,15 @@ export class AsyncAtomicTempOwner {
|
|
|
136
133
|
}
|
|
137
134
|
async assertCurrent(fsModule, pathname = this.pathname) {
|
|
138
135
|
const opened = await inspectFileIdentity(async () => {
|
|
139
|
-
const stat =
|
|
136
|
+
const stat = fsModule === fs ? syncFs.fstatSync(this.#handle.fd, { bigint: true })
|
|
137
|
+
: await this.#handle.stat({ bigint: true });
|
|
140
138
|
assertOwnedFile(stat, pathname, false);
|
|
141
139
|
return stat;
|
|
142
140
|
}, this.identity);
|
|
143
141
|
try {
|
|
144
142
|
await inspectFileIdentity(async () => {
|
|
145
|
-
const stat =
|
|
143
|
+
const stat = fsModule === fs ? syncFs.lstatSync(pathname, { bigint: true })
|
|
144
|
+
: await fsModule.lstat(pathname, { bigint: true });
|
|
146
145
|
assertOwnedFile(stat, pathname, true);
|
|
147
146
|
return stat;
|
|
148
147
|
}, opened);
|
|
@@ -178,12 +177,14 @@ export class AsyncAtomicTempOwner {
|
|
|
178
177
|
throw error;
|
|
179
178
|
}
|
|
180
179
|
const identity = await inspectFileIdentity(async () => {
|
|
181
|
-
const stat =
|
|
180
|
+
const stat = fsModule === fs ? syncFs.fstatSync(published.fd, { bigint: true })
|
|
181
|
+
: await published.stat({ bigint: true });
|
|
182
182
|
assertOwnedFile(stat, pathname, false);
|
|
183
183
|
return stat;
|
|
184
184
|
});
|
|
185
185
|
await inspectFileIdentity(async () => {
|
|
186
|
-
const stat =
|
|
186
|
+
const stat = fsModule === fs ? syncFs.lstatSync(pathname, { bigint: true })
|
|
187
|
+
: await fsModule.lstat(pathname, { bigint: true });
|
|
187
188
|
assertOwnedFile(stat, pathname, true);
|
|
188
189
|
return stat;
|
|
189
190
|
}, identity);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-file.d.ts","sourceRoot":"","sources":["../src/replace-file.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"replace-file.d.ts","sourceRoot":"","sources":["../src/replace-file.ts"],"names":[],"mappings":"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"}
|
package/dist/replace-file.js
CHANGED
|
@@ -18,7 +18,8 @@ function isPermissionRenameError(error) {
|
|
|
18
18
|
}
|
|
19
19
|
async function renameWithRetry(params) {
|
|
20
20
|
for (let attempt = 0; attempt <= params.maxRetries; attempt++) {
|
|
21
|
-
|
|
21
|
+
if (attempt > 0)
|
|
22
|
+
await params.assertSourceCurrent();
|
|
22
23
|
try {
|
|
23
24
|
await params.fsModule.rename(params.src, params.dest);
|
|
24
25
|
return { method: "rename" };
|
|
@@ -48,7 +49,8 @@ async function renameWithRetry(params) {
|
|
|
48
49
|
}
|
|
49
50
|
function renameWithRetrySync(params) {
|
|
50
51
|
for (let attempt = 0; attempt <= params.maxRetries; attempt++) {
|
|
51
|
-
|
|
52
|
+
if (attempt > 0)
|
|
53
|
+
params.assertSourceCurrent();
|
|
52
54
|
try {
|
|
53
55
|
params.fsModule.renameSync(params.src, params.dest);
|
|
54
56
|
return { method: "rename" };
|
|
@@ -175,9 +177,12 @@ async function replaceFileAtomicUnserialized(options, syncParent) {
|
|
|
175
177
|
await tempOwner.assertCurrent(fsModule);
|
|
176
178
|
if (options.beforeRename) {
|
|
177
179
|
await options.beforeRename({ filePath, tempPath });
|
|
180
|
+
await tempOwner.assertCurrent(fsModule);
|
|
181
|
+
}
|
|
182
|
+
if (options.destinationHardlinks === "reject") {
|
|
183
|
+
await assertDestinationHardlinkPolicy(fsModule, filePath, options.destinationHardlinks);
|
|
184
|
+
await tempOwner.assertCurrent(fsModule);
|
|
178
185
|
}
|
|
179
|
-
await tempOwner.assertCurrent(fsModule);
|
|
180
|
-
await assertDestinationHardlinkPolicy(fsModule, filePath, options.destinationHardlinks);
|
|
181
186
|
const result = await renameWithRetry({
|
|
182
187
|
fsModule,
|
|
183
188
|
src: tempPath,
|
|
@@ -199,13 +204,16 @@ async function replaceFileAtomicUnserialized(options, syncParent) {
|
|
|
199
204
|
else {
|
|
200
205
|
await tempOwner.assertCurrent(fsModule);
|
|
201
206
|
}
|
|
207
|
+
let didSyncParent = false;
|
|
202
208
|
if (syncParent) {
|
|
203
209
|
await syncParent(dir);
|
|
210
|
+
didSyncParent = true;
|
|
204
211
|
}
|
|
205
212
|
else if (options.syncParentDir) {
|
|
206
213
|
await syncDirectoryBestEffort(fsModule, dir);
|
|
214
|
+
didSyncParent = true;
|
|
207
215
|
}
|
|
208
|
-
if (result.method === "rename") {
|
|
216
|
+
if (result.method === "rename" && didSyncParent) {
|
|
209
217
|
await tempOwner.assertPublished(fsModule, filePath, expectedHash);
|
|
210
218
|
}
|
|
211
219
|
return result;
|
|
@@ -269,9 +277,12 @@ function replaceFileAtomicSyncUnserialized(options) {
|
|
|
269
277
|
tempOwner.assertCurrent(fsModule);
|
|
270
278
|
if (options.beforeRename) {
|
|
271
279
|
options.beforeRename({ filePath, tempPath });
|
|
280
|
+
tempOwner.assertCurrent(fsModule);
|
|
281
|
+
}
|
|
282
|
+
if (options.destinationHardlinks === "reject") {
|
|
283
|
+
assertDestinationHardlinkPolicySync(fsModule, filePath, options.destinationHardlinks);
|
|
284
|
+
tempOwner.assertCurrent(fsModule);
|
|
272
285
|
}
|
|
273
|
-
tempOwner.assertCurrent(fsModule);
|
|
274
|
-
assertDestinationHardlinkPolicySync(fsModule, filePath, options.destinationHardlinks);
|
|
275
286
|
const result = renameWithRetrySync({
|
|
276
287
|
fsModule,
|
|
277
288
|
src: tempPath,
|
|
@@ -294,10 +305,12 @@ function replaceFileAtomicSyncUnserialized(options) {
|
|
|
294
305
|
else {
|
|
295
306
|
tempOwner.assertCurrent(fsModule);
|
|
296
307
|
}
|
|
308
|
+
let didSyncParent = false;
|
|
297
309
|
if (options.syncParentDir) {
|
|
298
310
|
syncDirectoryBestEffortSync(fsModule, dir);
|
|
311
|
+
didSyncParent = true;
|
|
299
312
|
}
|
|
300
|
-
if (result.method === "rename") {
|
|
313
|
+
if (result.method === "rename" && didSyncParent) {
|
|
301
314
|
tempOwner.assertPublished(fsModule, filePath, expectedHash);
|
|
302
315
|
}
|
|
303
316
|
return result;
|
package/dist/root-context.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fs from "node:fs
|
|
1
|
+
import fs from "node:fs";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { inspectDirectoryIdentity } from "./directory-guard.js";
|
|
@@ -25,7 +25,7 @@ export async function expandRelativePathWithHome(relativePath) {
|
|
|
25
25
|
if (cachedHomePath?.raw !== rawHome) {
|
|
26
26
|
let realHome = rawHome;
|
|
27
27
|
try {
|
|
28
|
-
realHome =
|
|
28
|
+
realHome = fs.realpathSync.native(rawHome);
|
|
29
29
|
}
|
|
30
30
|
catch {
|
|
31
31
|
// If the home dir cannot be canonicalized, keep lexical expansion behavior.
|
|
@@ -39,8 +39,8 @@ export async function resolveRootContext(rootDir) {
|
|
|
39
39
|
let rootReal;
|
|
40
40
|
let rootIdentity;
|
|
41
41
|
try {
|
|
42
|
-
rootReal =
|
|
43
|
-
const rootStat =
|
|
42
|
+
rootReal = fs.realpathSync.native(rootDir);
|
|
43
|
+
const rootStat = fs.statSync(rootReal);
|
|
44
44
|
if (!rootStat.isDirectory()) {
|
|
45
45
|
throw new FsSafeError("invalid-path", "root dir is not a directory");
|
|
46
46
|
}
|
|
@@ -83,7 +83,7 @@ export async function assertRootIdentityCurrent(root) {
|
|
|
83
83
|
await inspectDirectoryIdentity(root.rootReal, { dev: root.rootIdentity.dev, ino: root.rootIdentity.ino });
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
|
-
current =
|
|
86
|
+
current = fs.lstatSync(root.rootReal);
|
|
87
87
|
}
|
|
88
88
|
catch (error) {
|
|
89
89
|
throw new FsSafeError("path-mismatch", "root path changed during operation", {
|
package/dist/root-errors.d.ts
CHANGED
|
@@ -8,4 +8,5 @@ export declare function normalizePinnedWriteError(error: unknown): Error;
|
|
|
8
8
|
export declare function normalizePinnedPathError(error: unknown): Error;
|
|
9
9
|
export declare function normalizeRemoveGuardError(error: unknown): Error;
|
|
10
10
|
export declare function normalizeRemovePathError(error: unknown): Error;
|
|
11
|
+
export declare function throwFsSafeReadError(error: unknown, label: string): never;
|
|
11
12
|
//# sourceMappingURL=root-errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-errors.d.ts","sourceRoot":"","sources":["../src/root-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK1C,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,CAI9D;AAED,wBAAgB,qBAAqB,IAAI,WAAW,CAEnD;AAED,wBAAgB,mCAAmC,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,CAIhF;AAED,wBAAgB,6BAA6B,IAAI,WAAW,CAE3D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAU/D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAO9D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAQ/D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAe9D"}
|
|
1
|
+
{"version":3,"file":"root-errors.d.ts","sourceRoot":"","sources":["../src/root-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK1C,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,CAI9D;AAED,wBAAgB,qBAAqB,IAAI,WAAW,CAEnD;AAED,wBAAgB,mCAAmC,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,CAIhF;AAED,wBAAgB,6BAA6B,IAAI,WAAW,CAE3D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAU/D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAO9D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAQ/D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAe9D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAQzE"}
|
package/dist/root-errors.js
CHANGED
|
@@ -64,3 +64,12 @@ export function normalizeRemovePathError(error) {
|
|
|
64
64
|
}
|
|
65
65
|
return new FsSafeError("not-removable", "path could not be removed", { cause });
|
|
66
66
|
}
|
|
67
|
+
export function throwFsSafeReadError(error, label) {
|
|
68
|
+
if (error instanceof FsSafeError) {
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
if (isNodeError(error)) {
|
|
72
|
+
throw new FsSafeError("read-failed", `${label} target could not be read`, { cause: error });
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
package/dist/root-file.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-file.d.ts","sourceRoot":"","sources":["../src/root-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAOzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EACjC,MAAM,kBAAkB,CAAC;AAE1B,KAAK,cAAc,GAAG,IAAI,CACxB,OAAO,EAAE,EACP,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,UAAU,GACV,cAAc,GACd,cAAc,CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,2BAA2B,GAAG,YAAY,CAAC;AAEnF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,yBAAyB,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtE,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAE7E,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,GAAG;IACxD,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B,CAAC;AAQF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAW3D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"root-file.d.ts","sourceRoot":"","sources":["../src/root-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAOzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EACjC,MAAM,kBAAkB,CAAC;AAE1B,KAAK,cAAc,GAAG,IAAI,CACxB,OAAO,EAAE,EACP,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,UAAU,GACV,cAAc,GACd,cAAc,CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,2BAA2B,GAAG,YAAY,CAAC;AAEnF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,yBAAyB,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtE,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAE7E,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,GAAG;IACxD,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B,CAAC;AAQF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAW3D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,kBAAkB,CAuBnF;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE;IACR,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,CAAC,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,CAAC,CAAC;IACjD,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,CAAC,CAAC;IACzC,QAAQ,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,CAAC,CAAC;CAC/C,GACA,CAAC,CAUH;AAoDD,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CAwB7B"}
|