@openclaw/fs-safe 0.8.2 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +1 -1
- package/dist/advanced.d.ts +2 -2
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +2 -2
- package/dist/archive-kind.d.ts +1 -0
- package/dist/archive-kind.d.ts.map +1 -1
- package/dist/archive-kind.js +6 -0
- package/dist/archive-limits.d.ts +0 -1
- package/dist/archive-limits.d.ts.map +1 -1
- package/dist/archive-limits.js +0 -3
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +5 -8
- package/dist/archive-parser-errors.d.ts +2 -0
- package/dist/archive-parser-errors.d.ts.map +1 -0
- package/dist/archive-parser-errors.js +12 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +7 -13
- package/dist/archive-tar-wasm.d.ts +1 -1
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +5 -8
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +43 -6
- package/dist/atomic.d.ts +1 -1
- package/dist/atomic.d.ts.map +1 -1
- package/dist/atomic.js +1 -1
- package/dist/bounded-read-stream.d.ts +1 -5
- package/dist/bounded-read-stream.d.ts.map +1 -1
- package/dist/bounded-read-stream.js +5 -13
- package/dist/byte-budget.d.ts +0 -1
- package/dist/byte-budget.d.ts.map +1 -1
- package/dist/byte-budget.js +1 -1
- package/dist/directory-mode-owner.d.ts.map +1 -1
- package/dist/directory-mode-owner.js +2 -0
- package/dist/error-detail.d.ts +1 -0
- package/dist/error-detail.d.ts.map +1 -1
- package/dist/error-detail.js +6 -0
- package/dist/file-store-boundary.d.ts +1 -1
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +2 -13
- package/dist/file-store.js +1 -1
- package/dist/file-sync.d.ts +5 -0
- package/dist/file-sync.d.ts.map +1 -0
- package/dist/file-sync.js +19 -0
- package/dist/guarded-mutation.d.ts +3 -0
- package/dist/guarded-mutation.d.ts.map +1 -1
- package/dist/guarded-mutation.js +5 -1
- package/dist/home-dir.d.ts +0 -10
- package/dist/home-dir.d.ts.map +1 -1
- package/dist/home-dir.js +0 -28
- package/dist/json-durable-queue-ownership.d.ts +1 -0
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +139 -18
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +5 -10
- package/dist/json-store.d.ts.map +1 -1
- package/dist/json-store.js +1 -1
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +2 -3
- package/dist/move-path-cleanup.d.ts +1 -1
- package/dist/move-path-cleanup.d.ts.map +1 -1
- package/dist/move-path-cleanup.js +4 -2
- package/dist/move-path.d.ts +9 -0
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +53 -16
- package/dist/native-operations.d.ts +0 -1
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +0 -10
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +5 -4
- package/dist/native-staged-file.d.ts +8 -1
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +30 -9
- package/dist/opened-realpath.d.ts +12 -1
- package/dist/opened-realpath.d.ts.map +1 -1
- package/dist/opened-realpath.js +8 -7
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +26 -2
- package/dist/path-policy.js +1 -1
- package/dist/permissions.d.ts +1 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +3 -0
- package/dist/pinned-write.d.ts +1 -2
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +2 -11
- package/dist/private-temp-workspace.js +1 -1
- package/dist/publish-file.js +2 -2
- package/dist/replace-file-copy-source.d.ts.map +1 -1
- package/dist/replace-file-copy-source.js +2 -7
- package/dist/replace-file-descriptor.d.ts.map +1 -1
- package/dist/replace-file-descriptor.js +3 -16
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +2 -7
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +21 -8
- package/dist/root-errors.d.ts +1 -0
- package/dist/root-errors.d.ts.map +1 -1
- package/dist/root-errors.js +9 -0
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +17 -28
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +12 -33
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +49 -94
- package/dist/root-write-mode.d.ts +6 -0
- package/dist/root-write-mode.d.ts.map +1 -0
- package/dist/root-write-mode.js +60 -0
- package/dist/root-write-verification.js +2 -2
- package/dist/safe-path-segment.d.ts +1 -0
- package/dist/safe-path-segment.d.ts.map +1 -1
- package/dist/safe-path-segment.js +1 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +2 -9
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +2 -10
- package/dist/secret-read-policy.d.ts +4 -0
- package/dist/secret-read-policy.d.ts.map +1 -1
- package/dist/secret-read-policy.js +12 -0
- package/dist/sibling-staged-file.d.ts.map +1 -1
- package/dist/sibling-staged-file.js +2 -7
- package/dist/sidecar-lock-policy.d.ts +0 -1
- package/dist/sidecar-lock-policy.d.ts.map +1 -1
- package/dist/sidecar-lock-policy.js +0 -4
- package/dist/string-coerce.d.ts +0 -9
- package/dist/string-coerce.d.ts.map +1 -1
- package/dist/string-coerce.js +0 -56
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +1 -12
- package/docs/atomic.md +53 -19
- package/docs/staged-file.md +6 -2
- package/docs/writing.md +5 -0
- package/package.json +8 -8
- package/dist/archive-tar-extract.d.ts +0 -11
- package/dist/archive-tar-extract.d.ts.map +0 -1
- package/dist/archive-tar-extract.js +0 -49
- package/dist/fsync.d.ts +0 -2
- package/dist/fsync.d.ts.map +0 -1
- package/dist/fsync.js +0 -1
- package/dist/json-durable-queue-retirement.d.ts +0 -9
- package/dist/json-durable-queue-retirement.d.ts.map +0 -1
- package/dist/json-durable-queue-retirement.js +0 -126
- package/dist/json-durable-queue-transfer-lock.d.ts +0 -2
- package/dist/json-durable-queue-transfer-lock.d.ts.map +0 -1
- package/dist/json-durable-queue-transfer-lock.js +0 -19
- package/dist/mode.d.ts +0 -2
- package/dist/mode.d.ts.map +0 -1
- package/dist/mode.js +0 -3
- package/dist/output-sibling.d.ts +0 -8
- package/dist/output-sibling.d.ts.map +0 -1
- package/dist/output-sibling.js +0 -30
- package/dist/read-error.d.ts +0 -2
- package/dist/read-error.d.ts.map +0 -1
- package/dist/read-error.js +0 -11
- package/dist/short-path.d.ts +0 -2
- package/dist/short-path.d.ts.map +0 -1
- package/dist/short-path.js +0 -7
- package/dist/staged-file.d.ts +0 -10
- package/dist/staged-file.d.ts.map +0 -1
- package/dist/staged-file.js +0 -15
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type BigIntStats } from "node:fs";
|
|
1
2
|
import { type AnyAsyncDirectoryGuard, type SyncDirectoryGuard } from "./directory-guard.js";
|
|
2
3
|
export declare function withAsyncDirectoryGuards<T>(guards: readonly AnyAsyncDirectoryGuard[], mutate: () => Promise<T>, options?: {
|
|
3
4
|
verifyAfter?: boolean;
|
|
@@ -8,6 +9,8 @@ export declare function withSyncDirectoryGuards<T>(guards: readonly SyncDirector
|
|
|
8
9
|
}): T;
|
|
9
10
|
export declare function guardedRename(params: {
|
|
10
11
|
assertBeforeRename?: () => void;
|
|
12
|
+
onSourceInspected?: (identity: Pick<BigIntStats, "dev" | "ino">) => void;
|
|
13
|
+
onRenamed?: () => void;
|
|
11
14
|
from: string;
|
|
12
15
|
to: string;
|
|
13
16
|
targetRoot?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guarded-mutation.d.ts","sourceRoot":"","sources":["../src/guarded-mutation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"guarded-mutation.d.ts","sourceRoot":"","sources":["../src/guarded-mutation.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAGnD,OAAO,EAOL,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAC;AAE9B,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,MAAM,EAAE,SAAS,sBAAsB,EAAE,EACzC,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACxB,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACrE,GACL,OAAO,CAAC,CAAC,CAAC,CAyBZ;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EACvC,MAAM,EAAE,SAAS,kBAAkB,EAAE,EACrC,MAAM,EAAE,MAAM,CAAC,EACf,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,CAAC,CAWH;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC1C,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC;IACzE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,IAAI,CAUP;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,IAAI,CAWP"}
|
package/dist/guarded-mutation.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fsSync from "node:fs";
|
|
1
|
+
import fsSync, {} from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { assertAsyncDirectoryGuard, assertSyncDirectoryGuard, createAsyncDirectoryGuard, createNearestExistingDirectoryGuard, createNearestExistingSyncDirectoryGuard, createSyncDirectoryGuard, } from "./directory-guard.js";
|
|
@@ -48,9 +48,13 @@ export async function guardedRename(params) {
|
|
|
48
48
|
? await createNearestExistingDirectoryGuard(params.targetRoot, path.dirname(params.to))
|
|
49
49
|
: await createAsyncDirectoryGuard(path.dirname(params.to));
|
|
50
50
|
await withAsyncDirectoryGuards([sourceGuard, targetGuard], async () => {
|
|
51
|
+
if (params.onSourceInspected) {
|
|
52
|
+
params.onSourceInspected(await fs.lstat(params.from, { bigint: true }));
|
|
53
|
+
}
|
|
51
54
|
// Authority must survive all awaited guards; do not yield before rename dispatch.
|
|
52
55
|
params.assertBeforeRename?.();
|
|
53
56
|
await fs.rename(params.from, params.to);
|
|
57
|
+
params.onRenamed?.();
|
|
54
58
|
}, { verifyAfter: params.verifyAfter });
|
|
55
59
|
}
|
|
56
60
|
export function guardedRenameSync(params) {
|
package/dist/home-dir.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export declare function resolveEffectiveHomeDir(env?: NodeJS.ProcessEnv, homedir?: () => string): string | undefined;
|
|
2
|
-
export declare function resolveOsHomeDir(env?: NodeJS.ProcessEnv, homedir?: () => string): string | undefined;
|
|
3
2
|
export declare function resolveRequiredHomeDir(env?: NodeJS.ProcessEnv, homedir?: () => string): string;
|
|
4
|
-
export declare function resolveRequiredOsHomeDir(env?: NodeJS.ProcessEnv, homedir?: () => string): string;
|
|
5
3
|
export declare function expandHomePrefix(input: string, opts?: {
|
|
6
4
|
home?: string;
|
|
7
5
|
env?: NodeJS.ProcessEnv;
|
|
@@ -11,12 +9,4 @@ export declare function resolveHomeRelativePath(input: string, opts?: {
|
|
|
11
9
|
env?: NodeJS.ProcessEnv;
|
|
12
10
|
homedir?: () => string;
|
|
13
11
|
}): string;
|
|
14
|
-
export declare function resolveUserPath(input: string, optsOrEnv?: {
|
|
15
|
-
env?: NodeJS.ProcessEnv;
|
|
16
|
-
homedir?: () => string;
|
|
17
|
-
} | NodeJS.ProcessEnv, homedir?: () => string): string;
|
|
18
|
-
export declare function resolveOsHomeRelativePath(input: string, opts?: {
|
|
19
|
-
env?: NodeJS.ProcessEnv;
|
|
20
|
-
homedir?: () => string;
|
|
21
|
-
}): string;
|
|
22
12
|
//# sourceMappingURL=home-dir.d.ts.map
|
package/dist/home-dir.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"home-dir.d.ts","sourceRoot":"","sources":["../src/home-dir.ts"],"names":[],"mappings":"AAeA,wBAAgB,uBAAuB,CACrC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,MAAM,MAAmB,GACjC,MAAM,GAAG,SAAS,CAGpB;
|
|
1
|
+
{"version":3,"file":"home-dir.d.ts","sourceRoot":"","sources":["../src/home-dir.ts"],"names":[],"mappings":"AAeA,wBAAgB,uBAAuB,CACrC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,MAAM,MAAmB,GACjC,MAAM,GAAG,SAAS,CAGpB;AAyCD,wBAAgB,sBAAsB,CACpC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,MAAM,MAAmB,GACjC,MAAM,CAER;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;IACL,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;CACxB,GACA,MAAM,CAYR;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;IACL,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;CACxB,GACA,MAAM,CAcR"}
|
package/dist/home-dir.js
CHANGED
|
@@ -15,10 +15,6 @@ export function resolveEffectiveHomeDir(env = process.env, homedir = os.homedir)
|
|
|
15
15
|
const raw = resolveRawHomeDir(env, homedir);
|
|
16
16
|
return raw ? path.resolve(raw) : undefined;
|
|
17
17
|
}
|
|
18
|
-
export function resolveOsHomeDir(env = process.env, homedir = os.homedir) {
|
|
19
|
-
const raw = resolveRawOsHomeDir(env, homedir);
|
|
20
|
-
return raw ? path.resolve(raw) : undefined;
|
|
21
|
-
}
|
|
22
18
|
function resolveRawHomeDir(env, homedir) {
|
|
23
19
|
const explicitHome = normalize(env.OPENCLAW_HOME);
|
|
24
20
|
if (!explicitHome) {
|
|
@@ -59,9 +55,6 @@ function normalizeSafe(homedir) {
|
|
|
59
55
|
export function resolveRequiredHomeDir(env = process.env, homedir = os.homedir) {
|
|
60
56
|
return resolveEffectiveHomeDir(env, homedir) ?? path.resolve(process.cwd());
|
|
61
57
|
}
|
|
62
|
-
export function resolveRequiredOsHomeDir(env = process.env, homedir = os.homedir) {
|
|
63
|
-
return resolveOsHomeDir(env, homedir) ?? path.resolve(process.cwd());
|
|
64
|
-
}
|
|
65
58
|
export function expandHomePrefix(input, opts) {
|
|
66
59
|
const segments = path.normalize(input).split(path.sep);
|
|
67
60
|
if (segments[0] !== "~") {
|
|
@@ -89,24 +82,3 @@ export function resolveHomeRelativePath(input, opts) {
|
|
|
89
82
|
});
|
|
90
83
|
return path.resolve(expanded);
|
|
91
84
|
}
|
|
92
|
-
export function resolveUserPath(input, optsOrEnv, homedir) {
|
|
93
|
-
const opts = optsOrEnv && ("env" in optsOrEnv || "homedir" in optsOrEnv)
|
|
94
|
-
? optsOrEnv
|
|
95
|
-
: { env: optsOrEnv, homedir };
|
|
96
|
-
return resolveHomeRelativePath(input, opts);
|
|
97
|
-
}
|
|
98
|
-
export function resolveOsHomeRelativePath(input, opts) {
|
|
99
|
-
if (!input) {
|
|
100
|
-
return input;
|
|
101
|
-
}
|
|
102
|
-
const segments = path.normalize(input).split(path.sep);
|
|
103
|
-
if (segments[0] !== "~") {
|
|
104
|
-
return path.resolve(input);
|
|
105
|
-
}
|
|
106
|
-
const expanded = expandHomePrefix(input, {
|
|
107
|
-
home: resolveRequiredOsHomeDir(opts?.env ?? process.env, opts?.homedir ?? os.homedir),
|
|
108
|
-
env: opts?.env,
|
|
109
|
-
homedir: opts?.homedir,
|
|
110
|
-
});
|
|
111
|
-
return path.resolve(expanded);
|
|
112
|
-
}
|
|
@@ -13,4 +13,5 @@ export declare function moveDurableQueueEntryToFailed(params: {
|
|
|
13
13
|
paths: DurableQueueEntryPathsLike;
|
|
14
14
|
failedPath: string;
|
|
15
15
|
}): Promise<void>;
|
|
16
|
+
export declare function getErrorCode(error: unknown): string | null;
|
|
16
17
|
//# sourceMappingURL=json-durable-queue-ownership.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-durable-queue-ownership.d.ts","sourceRoot":"","sources":["../src/json-durable-queue-ownership.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"json-durable-queue-ownership.d.ts","sourceRoot":"","sources":["../src/json-durable-queue-ownership.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,0BAA0B,GAAG,MAAM,CAKpF;AA+DD,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,0BAA0B,EACjC,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,OAAO,CAAC,CAalB;AAED,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,KAAK,EAAE,0BAA0B,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDhB;AAKD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAI1D"}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { withSidecarLock } from "./sidecar-lock.js";
|
|
1
3
|
import fs from "node:fs/promises";
|
|
2
4
|
import path from "node:path";
|
|
3
5
|
import { syncDirectory } from "./directory-durability.js";
|
|
4
6
|
import { FsSafeError } from "./errors.js";
|
|
5
|
-
import { sameFileIdentityForCleanup } from "./file-identity.js";
|
|
6
|
-
import { recoverDurableQueueRetirement, retireDurableQueueSource, } from "./json-durable-queue-retirement.js";
|
|
7
|
-
import { withQueueTransferLock } from "./json-durable-queue-transfer-lock.js";
|
|
7
|
+
import { sameFileIdentityForCleanup, sha256Hex } from "./file-identity.js";
|
|
8
8
|
import { serializePathWrite } from "./write-queue.js";
|
|
9
|
-
function getErrorCode(error) {
|
|
10
|
-
return error && typeof error === "object" && "code" in error
|
|
11
|
-
? String(error.code)
|
|
12
|
-
: null;
|
|
13
|
-
}
|
|
14
9
|
export function durableQueueProcessingPath(paths) {
|
|
15
10
|
if (paths.processingPath)
|
|
16
11
|
return paths.processingPath;
|
|
@@ -18,16 +13,6 @@ export function durableQueueProcessingPath(paths) {
|
|
|
18
13
|
? `${paths.jsonPath.slice(0, -".json".length)}.processing`
|
|
19
14
|
: `${paths.jsonPath}.processing`;
|
|
20
15
|
}
|
|
21
|
-
async function lstatOrNull(filePath) {
|
|
22
|
-
try {
|
|
23
|
-
return await fs.lstat(filePath, { bigint: true });
|
|
24
|
-
}
|
|
25
|
-
catch (error) {
|
|
26
|
-
if (getErrorCode(error) === "ENOENT")
|
|
27
|
-
return null;
|
|
28
|
-
throw error;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
16
|
async function regularQueueFileIdentity(filePath) {
|
|
32
17
|
const identity = await lstatOrNull(filePath);
|
|
33
18
|
if (!identity)
|
|
@@ -169,3 +154,139 @@ export async function moveDurableQueueEntryToFailed(params) {
|
|
|
169
154
|
await syncDirectory(path.dirname(sourcePath));
|
|
170
155
|
});
|
|
171
156
|
}
|
|
157
|
+
const RETIREMENT_ROOT_NAME = ".fs-safe-retirements";
|
|
158
|
+
const RETIREMENT_ENTRY_NAME = "entry";
|
|
159
|
+
export function getErrorCode(error) {
|
|
160
|
+
return error && typeof error === "object" && "code" in error
|
|
161
|
+
? String(error.code)
|
|
162
|
+
: null;
|
|
163
|
+
}
|
|
164
|
+
async function lstatOrNull(filePath) {
|
|
165
|
+
try {
|
|
166
|
+
return await fs.lstat(filePath, { bigint: true });
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
if (getErrorCode(error) === "ENOENT")
|
|
170
|
+
return null;
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function assertDirectory(identity, label) {
|
|
175
|
+
if (identity.isSymbolicLink() || !identity.isDirectory()) {
|
|
176
|
+
throw new FsSafeError("path-mismatch", `${label} is not an owned directory`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async function regularFileIdentity(filePath) {
|
|
180
|
+
const identity = await lstatOrNull(filePath);
|
|
181
|
+
if (!identity)
|
|
182
|
+
return null;
|
|
183
|
+
if (identity.isSymbolicLink() || !identity.isFile()) {
|
|
184
|
+
throw new FsSafeError("path-mismatch", "queue retirement path is not a regular file");
|
|
185
|
+
}
|
|
186
|
+
return identity;
|
|
187
|
+
}
|
|
188
|
+
function retirementPaths(jsonPath) {
|
|
189
|
+
const rootPath = path.join(path.dirname(jsonPath), RETIREMENT_ROOT_NAME);
|
|
190
|
+
const dirPath = path.join(rootPath, path.basename(jsonPath));
|
|
191
|
+
return { dirPath, entryPath: path.join(dirPath, RETIREMENT_ENTRY_NAME), rootPath };
|
|
192
|
+
}
|
|
193
|
+
async function inspectRetirementRoot(jsonPath) {
|
|
194
|
+
const rootPath = retirementPaths(jsonPath).rootPath;
|
|
195
|
+
const root = await lstatOrNull(rootPath);
|
|
196
|
+
if (!root)
|
|
197
|
+
return null;
|
|
198
|
+
assertDirectory(root, "queue retirement root");
|
|
199
|
+
return rootPath;
|
|
200
|
+
}
|
|
201
|
+
async function ensureRetirementRoot(jsonPath) {
|
|
202
|
+
const parentPath = path.dirname(jsonPath);
|
|
203
|
+
const rootPath = retirementPaths(jsonPath).rootPath;
|
|
204
|
+
await fs.mkdir(rootPath, { mode: 0o700 }).catch((error) => {
|
|
205
|
+
if (getErrorCode(error) !== "EEXIST")
|
|
206
|
+
throw error;
|
|
207
|
+
});
|
|
208
|
+
const root = await fs.lstat(rootPath, { bigint: true });
|
|
209
|
+
assertDirectory(root, "queue retirement root");
|
|
210
|
+
await syncDirectory(parentPath);
|
|
211
|
+
return rootPath;
|
|
212
|
+
}
|
|
213
|
+
async function removeRetirementRecord(params) {
|
|
214
|
+
await fs.rmdir(params.dirPath).catch((error) => {
|
|
215
|
+
if (getErrorCode(error) !== "ENOENT")
|
|
216
|
+
throw error;
|
|
217
|
+
});
|
|
218
|
+
await syncDirectory(params.rootPath);
|
|
219
|
+
}
|
|
220
|
+
async function recoverDurableQueueRetirement(params) {
|
|
221
|
+
const rootPath = await inspectRetirementRoot(params.jsonPath);
|
|
222
|
+
if (!rootPath)
|
|
223
|
+
return;
|
|
224
|
+
const { dirPath, entryPath } = retirementPaths(params.jsonPath);
|
|
225
|
+
const dir = await lstatOrNull(dirPath);
|
|
226
|
+
if (!dir)
|
|
227
|
+
return;
|
|
228
|
+
assertDirectory(dir, "queue retirement record");
|
|
229
|
+
const names = await fs.readdir(dirPath);
|
|
230
|
+
if (names.length === 0) {
|
|
231
|
+
await removeRetirementRecord({ dirPath, rootPath });
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (names.length !== 1 || names[0] !== RETIREMENT_ENTRY_NAME) {
|
|
235
|
+
throw new FsSafeError("path-mismatch", "queue retirement record is ambiguous");
|
|
236
|
+
}
|
|
237
|
+
const entry = await regularFileIdentity(entryPath);
|
|
238
|
+
const processing = await regularFileIdentity(params.processingPath);
|
|
239
|
+
if (!entry || !processing) {
|
|
240
|
+
throw new FsSafeError("path-mismatch", "queue retirement ownership is incomplete");
|
|
241
|
+
}
|
|
242
|
+
if (!sameFileIdentityForCleanup(entry, processing)) {
|
|
243
|
+
const pending = await regularFileIdentity(params.jsonPath);
|
|
244
|
+
if (!pending) {
|
|
245
|
+
await fs.link(entryPath, params.jsonPath);
|
|
246
|
+
await syncDirectory(path.dirname(params.jsonPath));
|
|
247
|
+
}
|
|
248
|
+
else if (sameFileIdentityForCleanup(pending, entry)) {
|
|
249
|
+
await syncDirectory(path.dirname(params.jsonPath));
|
|
250
|
+
}
|
|
251
|
+
else if (pending.nlink > 1n) {
|
|
252
|
+
throw new FsSafeError("path-mismatch", "queue replacement identity is ambiguous");
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
await fs.unlink(entryPath);
|
|
256
|
+
await syncDirectory(dirPath);
|
|
257
|
+
await removeRetirementRecord({ dirPath, rootPath });
|
|
258
|
+
}
|
|
259
|
+
async function retireDurableQueueSource(params) {
|
|
260
|
+
await recoverDurableQueueRetirement(params);
|
|
261
|
+
const rootPath = await ensureRetirementRoot(params.jsonPath);
|
|
262
|
+
const { dirPath, entryPath } = retirementPaths(params.jsonPath);
|
|
263
|
+
await fs.mkdir(dirPath, { mode: 0o700 });
|
|
264
|
+
await syncDirectory(rootPath);
|
|
265
|
+
try {
|
|
266
|
+
await fs.rename(params.jsonPath, entryPath);
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
if (getErrorCode(error) !== "ENOENT")
|
|
270
|
+
throw error;
|
|
271
|
+
await removeRetirementRecord({ dirPath, rootPath });
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
await syncDirectory(dirPath);
|
|
275
|
+
await syncDirectory(path.dirname(params.jsonPath));
|
|
276
|
+
await recoverDurableQueueRetirement(params);
|
|
277
|
+
}
|
|
278
|
+
async function withQueueTransferLock(filePath, run) {
|
|
279
|
+
const lockPath = path.join(path.dirname(filePath), `.fs-safe-transfer-${sha256Hex(path.basename(filePath)).slice(0, 32)}.lock`);
|
|
280
|
+
return await withSidecarLock(filePath, {
|
|
281
|
+
managerKey: "fs-safe.queue-transfer",
|
|
282
|
+
lockPath,
|
|
283
|
+
staleMs: 30_000,
|
|
284
|
+
staleRecovery: "fail-closed",
|
|
285
|
+
timeoutMs: 45_000,
|
|
286
|
+
payload: () => ({
|
|
287
|
+
ownerToken: randomUUID(),
|
|
288
|
+
createdAt: new Date().toISOString(),
|
|
289
|
+
}),
|
|
290
|
+
retry: { retries: 180, minTimeout: 25, maxTimeout: 250, factor: 1.1 },
|
|
291
|
+
}, run);
|
|
292
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-durable-queue.d.ts","sourceRoot":"","sources":["../src/json-durable-queue.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"json-durable-queue.d.ts","sourceRoot":"","sources":["../src/json-durable-queue.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI;IAC1C,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAOF,eAAO,MAAM,0CAA0C,QAAmB,CAAC;AAM3E,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED,wBAAsB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUpF;AAmBD,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,GACT,0BAA0B,CAO5B;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhB;AAgLD,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQhB;AA6DD,wBAAsB,yBAAyB,CAAC,CAAC,EAC/C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,OAAO,CAAC,CAAC,CAAC,CASZ;AAED,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/F;AAED,wBAAsB,yBAAyB,CAAC,CAAC,EAAE,MAAM,EAAE;IACzD,KAAK,EAAE,0BAA0B,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAsBpB;AAED,wBAAsB,kCAAkC,CAAC,CAAC,EACxD,OAAO,EAAE,2BAA2B,CAAC,CAAC,CAAC,GACtC,OAAO,CAAC,CAAC,EAAE,CAAC,CA8Dd;AAED,wBAAsB,iCAAiC,CAAC,MAAM,EAAE;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB"}
|
|
@@ -3,18 +3,13 @@ import path from "node:path";
|
|
|
3
3
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
4
4
|
import { syncDirectory } from "./directory-durability.js";
|
|
5
5
|
import { syncQueueDirectoryCreation } from "./json-durable-queue-directory.js";
|
|
6
|
-
import { acknowledgeDurableQueueEntry, claimDurableQueueEntry, completeDeliveredQueueEntry, moveDurableQueueEntryToFailed, } from "./json-durable-queue-ownership.js";
|
|
6
|
+
import { getErrorCode, acknowledgeDurableQueueEntry, claimDurableQueueEntry, completeDeliveredQueueEntry, moveDurableQueueEntryToFailed, } from "./json-durable-queue-ownership.js";
|
|
7
7
|
import { stringifyJsonDocument } from "./json-stringify.js";
|
|
8
8
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
9
9
|
import { replaceFileAtomicWithDirectorySync } from "./replace-file.js";
|
|
10
10
|
import { assertSafePathSegment } from "./safe-path-segment.js";
|
|
11
11
|
import { inspectFileIdentity } from "./strict-file-identity.js";
|
|
12
12
|
export const DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES = 16 * 1024 * 1024;
|
|
13
|
-
function getErrnoCode(error) {
|
|
14
|
-
return error && typeof error === "object" && "code" in error
|
|
15
|
-
? String(error.code)
|
|
16
|
-
: null;
|
|
17
|
-
}
|
|
18
13
|
function assertSafeQueueEntryId(id) {
|
|
19
14
|
assertSafePathSegment(id, { label: "queue entry id" });
|
|
20
15
|
}
|
|
@@ -27,7 +22,7 @@ export async function jsonDurableQueueEntryExists(filePath) {
|
|
|
27
22
|
return stat.isFile();
|
|
28
23
|
}
|
|
29
24
|
catch (error) {
|
|
30
|
-
if (
|
|
25
|
+
if (getErrorCode(error) === "ENOENT") {
|
|
31
26
|
return false;
|
|
32
27
|
}
|
|
33
28
|
throw error;
|
|
@@ -41,7 +36,7 @@ async function unlinkStaleTmpBestEffort(filePath, now, maxAgeMs) {
|
|
|
41
36
|
}
|
|
42
37
|
}
|
|
43
38
|
catch (error) {
|
|
44
|
-
if (
|
|
39
|
+
if (getErrorCode(error) !== "ENOENT") {
|
|
45
40
|
throw error;
|
|
46
41
|
}
|
|
47
42
|
}
|
|
@@ -302,7 +297,7 @@ export async function loadJsonDurableQueueEntry(params) {
|
|
|
302
297
|
return result.entry;
|
|
303
298
|
}
|
|
304
299
|
catch (error) {
|
|
305
|
-
if (
|
|
300
|
+
if (getErrorCode(error) === "ENOENT") {
|
|
306
301
|
return null;
|
|
307
302
|
}
|
|
308
303
|
throw error;
|
|
@@ -314,7 +309,7 @@ export async function loadPendingJsonDurableQueueEntries(options) {
|
|
|
314
309
|
files = await fs.promises.readdir(options.queueDir);
|
|
315
310
|
}
|
|
316
311
|
catch (error) {
|
|
317
|
-
if (
|
|
312
|
+
if (getErrorCode(error) === "ENOENT") {
|
|
318
313
|
return [];
|
|
319
314
|
}
|
|
320
315
|
throw error;
|
package/dist/json-store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-store.d.ts","sourceRoot":"","sources":["../src/json-store.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"json-store.d.ts","sourceRoot":"","sources":["../src/json-store.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,SAAS,EACd,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,oBAAoB,GAAG;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,YAAY,EAAE,oBAAoB,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC;AAEtE,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAQvE"}
|
package/dist/json-store.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileStore } from "./file-store.js";
|
|
3
|
-
import {
|
|
3
|
+
import {} from "./json-document-store.js";
|
|
4
4
|
export function jsonStore(options) {
|
|
5
5
|
const filePath = path.resolve(options.filePath);
|
|
6
6
|
return fileStore({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-roots.d.ts","sourceRoot":"","sources":["../src/local-roots.ts"],"names":[],"mappings":"AAQA,OAAO,EAAQ,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAE3F,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oCAAoC,GAAG,sBAAsB,GAAG;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,sBAAsB,GAAG;IACnE,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B,CAAC;AAgDF,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,oCAAoC,GAC5C,oBAAoB,GAAG,IAAI,CAuC7B;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"local-roots.d.ts","sourceRoot":"","sources":["../src/local-roots.ts"],"names":[],"mappings":"AAQA,OAAO,EAAQ,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAE3F,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oCAAoC,GAAG,sBAAsB,GAAG;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,sBAAsB,GAAG;IACnE,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B,CAAC;AAgDF,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,oCAAoC,GAC5C,oBAAoB,GAAG,IAAI,CAuC7B;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA2CtC"}
|
package/dist/local-roots.js
CHANGED
|
@@ -2,7 +2,7 @@ import fsSync from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
4
4
|
import { FsSafeError } from "./errors.js";
|
|
5
|
-
import { expandHomePrefix,
|
|
5
|
+
import { expandHomePrefix, resolveHomeRelativePath } from "./home-dir.js";
|
|
6
6
|
import { isFileUrl, safeFileURLToPath } from "./local-file-access.js";
|
|
7
7
|
import { isPathInside } from "./path.js";
|
|
8
8
|
import { resolveRootPathSync } from "./root-path.js";
|
|
@@ -20,7 +20,7 @@ function resolveLocalPathInput(input, label) {
|
|
|
20
20
|
if (input.includes("\0")) {
|
|
21
21
|
throw new FsSafeError("invalid-path", `${label} must not contain NUL bytes`);
|
|
22
22
|
}
|
|
23
|
-
return
|
|
23
|
+
return resolveHomeRelativePath(input);
|
|
24
24
|
}
|
|
25
25
|
function resolveLocalRootInput(input, label) {
|
|
26
26
|
const trimmed = input.trim();
|
|
@@ -106,7 +106,6 @@ export async function readLocalFileFromRoots(options) {
|
|
|
106
106
|
}
|
|
107
107
|
const readOptions = {
|
|
108
108
|
hardlinks: options.hardlinks,
|
|
109
|
-
nonBlockingRead: options.nonBlockingRead,
|
|
110
109
|
symlinks: options.symlinks,
|
|
111
110
|
};
|
|
112
111
|
// Leave maxBytes absent when the caller omits it so Root's own default
|
|
@@ -38,6 +38,6 @@ export declare function sameIdentity(a: EntryIdentity, b: EntryIdentity): boolea
|
|
|
38
38
|
export declare function sourceChangedError(sourcePath: string): Error;
|
|
39
39
|
export declare function assertSourceStillMatches(sourcePath: string, identity: EntryIdentity): Promise<void>;
|
|
40
40
|
export declare function createCleanupCopiedEntryState(sourcePath: string, manifest: CopiedEntryManifest): CleanupCopiedEntryState;
|
|
41
|
-
export declare function cleanupCopiedEntry(sourcePath: string, manifest: CopiedEntryManifest, state: CleanupCopiedEntryState): Promise<CleanupCopiedEntryResult>;
|
|
41
|
+
export declare function cleanupCopiedEntry(sourcePath: string, manifest: CopiedEntryManifest, state: CleanupCopiedEntryState, assertBeforeMutation: () => void): Promise<CleanupCopiedEntryResult>;
|
|
42
42
|
export {};
|
|
43
43
|
//# sourceMappingURL=move-path-cleanup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"move-path-cleanup.d.ts","sourceRoot":"","sources":["../src/move-path-cleanup.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAC3B,CAAC,aAAa,GAAG;IACf,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,mBAAmB,CAAA;KAAE,CAAC,CAAC;IACjE,IAAI,EAAE,WAAW,CAAC;CACnB,CAAC,GACF,CAAC,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEvC,KAAK,wBAAwB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpD,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,aAAa,CAAC;IACxB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC7C,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,aAAa,CAUhB;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,GAAG,OAAO,CAUxE;AAMD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAI5D;AAED,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,IAAI,CAAC,CAIf;AA0BD,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,mBAAmB,GAC5B,uBAAuB,CAuBzB;AAsDD,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"move-path-cleanup.d.ts","sourceRoot":"","sources":["../src/move-path-cleanup.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAC3B,CAAC,aAAa,GAAG;IACf,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,mBAAmB,CAAA;KAAE,CAAC,CAAC;IACjE,IAAI,EAAE,WAAW,CAAC;CACnB,CAAC,GACF,CAAC,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEvC,KAAK,wBAAwB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpD,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,aAAa,CAAC;IACxB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC7C,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,aAAa,CAUhB;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,GAAG,OAAO,CAUxE;AAMD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAI5D;AAED,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,IAAI,CAAC,CAIf;AA0BD,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,mBAAmB,GAC5B,uBAAuB,CAuBzB;AAsDD,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,uBAAuB,EAC9B,oBAAoB,EAAE,MAAM,IAAI,GAC/B,OAAO,CAAC,wBAAwB,CAAC,CAyDnC"}
|
|
@@ -111,7 +111,7 @@ async function observeOwnedAliasUnlink(sourcePath, group) {
|
|
|
111
111
|
function mergeCleanupResults(a, b) {
|
|
112
112
|
return a === "stale" || b === "stale" ? "stale" : "removed";
|
|
113
113
|
}
|
|
114
|
-
export async function cleanupCopiedEntry(sourcePath, manifest, state) {
|
|
114
|
+
export async function cleanupCopiedEntry(sourcePath, manifest, state, assertBeforeMutation) {
|
|
115
115
|
const aliasGroup = manifest.kind === "leaf" ? state.aliasGroups.get(identityKey(manifest)) : undefined;
|
|
116
116
|
if (aliasGroup?.stale) {
|
|
117
117
|
return "stale";
|
|
@@ -134,8 +134,9 @@ export async function cleanupCopiedEntry(sourcePath, manifest, state) {
|
|
|
134
134
|
// clean manifest children so the fallback does not duplicate copied files.
|
|
135
135
|
let result = "removed";
|
|
136
136
|
for (const child of manifest.children) {
|
|
137
|
-
result = mergeCleanupResults(result, await cleanupCopiedEntry(path.join(sourcePath, child.name), child.manifest, state));
|
|
137
|
+
result = mergeCleanupResults(result, await cleanupCopiedEntry(path.join(sourcePath, child.name), child.manifest, state, assertBeforeMutation));
|
|
138
138
|
}
|
|
139
|
+
assertBeforeMutation();
|
|
139
140
|
try {
|
|
140
141
|
await fs.rmdir(sourcePath);
|
|
141
142
|
}
|
|
@@ -152,6 +153,7 @@ export async function cleanupCopiedEntry(sourcePath, manifest, state) {
|
|
|
152
153
|
if (!sameIdentity(expected, entryIdentity(currentStat))) {
|
|
153
154
|
return aliasGroup ? poisonAliasGroup(aliasGroup) : "stale";
|
|
154
155
|
}
|
|
156
|
+
assertBeforeMutation();
|
|
155
157
|
await fs.unlink(sourcePath);
|
|
156
158
|
return aliasGroup
|
|
157
159
|
? await observeOwnedAliasUnlink(sourcePath, aliasGroup)
|
package/dist/move-path.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
export type MovePathPublicationReceipt = Readonly<{
|
|
2
|
+
path: string;
|
|
3
|
+
dev: bigint;
|
|
4
|
+
ino: bigint;
|
|
5
|
+
}>;
|
|
1
6
|
export type MovePathWithCopyFallbackOptions = {
|
|
7
|
+
/** Rechecks authority before each rename and copied-source unlink/rmdir dispatch. */
|
|
8
|
+
assertBeforeMutation?: () => void;
|
|
2
9
|
/** Rechecks caller authority synchronously immediately before each rename dispatch. */
|
|
3
10
|
assertBeforeRename?: () => void;
|
|
11
|
+
/** Reports the committed destination before post-rename checks or source cleanup. */
|
|
12
|
+
onDestinationPublished?: (receipt: MovePathPublicationReceipt) => void;
|
|
4
13
|
from: string;
|
|
5
14
|
sourceHardlinks?: "allow" | "reject";
|
|
6
15
|
to: string;
|
package/dist/move-path.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"move-path.d.ts","sourceRoot":"","sources":["../src/move-path.ts"],"names":[],"mappings":"AAoBA,MAAM,MAAM,+BAA+B,GAAG;IAC5C,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACrC,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,KAAK,sBAAsB,GAAG,cAAc,GAAG,uBAAuB,CAAC;AAEvE,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,sBAAsB,GAAG,SAAS,CASpC;
|
|
1
|
+
{"version":3,"file":"move-path.d.ts","sourceRoot":"","sources":["../src/move-path.ts"],"names":[],"mappings":"AAoBA,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC,CAAC;AAEH,MAAM,MAAM,+BAA+B,GAAG;IAC5C,qFAAqF;IACrF,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,qFAAqF;IACrF,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,IAAI,CAAC;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACrC,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,KAAK,sBAAsB,GAAG,cAAc,GAAG,uBAAuB,CAAC;AAEvE,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,sBAAsB,GAAG,SAAS,CASpC;AAsPD,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,IAAI,CAAC,CAqHf"}
|
package/dist/move-path.js
CHANGED
|
@@ -211,24 +211,49 @@ async function copyEntryWithManifest(from, to, options, expectedIdentity) {
|
|
|
211
211
|
});
|
|
212
212
|
return { ...identity, kind: "leaf" };
|
|
213
213
|
}
|
|
214
|
+
function assertSynchronousResult(returned, name) {
|
|
215
|
+
if (returned !== undefined) {
|
|
216
|
+
// TypeScript permits async functions for () => void; consume their rejection.
|
|
217
|
+
void Promise.resolve(returned).catch(() => { });
|
|
218
|
+
throw new TypeError(`${name} must return undefined synchronously`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
214
221
|
export async function movePathWithCopyFallback(options) {
|
|
215
|
-
// Keep the initiating owner's
|
|
216
|
-
const
|
|
222
|
+
// Keep the initiating owner's callbacks across preparation and copy fallback.
|
|
223
|
+
const callerRenameAssert = options.assertBeforeRename;
|
|
224
|
+
const callerMutationAssert = options.assertBeforeMutation;
|
|
225
|
+
const callerPublished = options.onDestinationPublished;
|
|
217
226
|
let assertionRejected = false;
|
|
227
|
+
let destinationPublished = false;
|
|
228
|
+
const assertBeforeMutation = () => {
|
|
229
|
+
assertSynchronousResult(callerMutationAssert?.(), "assertBeforeMutation");
|
|
230
|
+
};
|
|
218
231
|
const assertBeforeRename = () => {
|
|
219
232
|
try {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
// TypeScript permits async functions for () => void; they cannot authorize a rename.
|
|
223
|
-
void Promise.resolve(returned).catch(() => { });
|
|
224
|
-
throw new TypeError("assertBeforeRename must return undefined synchronously");
|
|
225
|
-
}
|
|
233
|
+
assertSynchronousResult(callerRenameAssert?.(), "assertBeforeRename");
|
|
234
|
+
assertBeforeMutation();
|
|
226
235
|
}
|
|
227
236
|
catch (error) {
|
|
228
237
|
assertionRejected = true;
|
|
229
238
|
throw error;
|
|
230
239
|
}
|
|
231
240
|
};
|
|
241
|
+
let publicationReceipt;
|
|
242
|
+
const onSourceInspected = callerPublished
|
|
243
|
+
? (identity) => {
|
|
244
|
+
publicationReceipt = Object.freeze({
|
|
245
|
+
path: targetPath,
|
|
246
|
+
dev: identity.dev,
|
|
247
|
+
ino: identity.ino,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
: undefined;
|
|
251
|
+
const onRenamed = () => {
|
|
252
|
+
destinationPublished = true;
|
|
253
|
+
if (publicationReceipt) {
|
|
254
|
+
assertSynchronousResult(callerPublished?.(publicationReceipt), "onDestinationPublished");
|
|
255
|
+
}
|
|
256
|
+
};
|
|
232
257
|
const sourcePath = path.resolve(options.from);
|
|
233
258
|
const targetPath = path.resolve(options.to);
|
|
234
259
|
const rejectHardlinks = options.sourceHardlinks === "reject";
|
|
@@ -237,12 +262,18 @@ export async function movePathWithCopyFallback(options) {
|
|
|
237
262
|
}
|
|
238
263
|
if (!rejectHardlinks) {
|
|
239
264
|
try {
|
|
240
|
-
await guardedRename({
|
|
265
|
+
await guardedRename({
|
|
266
|
+
from: sourcePath,
|
|
267
|
+
to: targetPath,
|
|
268
|
+
assertBeforeRename,
|
|
269
|
+
onSourceInspected,
|
|
270
|
+
onRenamed,
|
|
271
|
+
});
|
|
241
272
|
return;
|
|
242
273
|
}
|
|
243
274
|
catch (error) {
|
|
244
275
|
// An owner's EXDEV/EPERM refusal is not permission to copy instead.
|
|
245
|
-
if (assertionRejected || !moveCopyFallbackReasonForRenameError(error)) {
|
|
276
|
+
if (assertionRejected || destinationPublished || !moveCopyFallbackReasonForRenameError(error)) {
|
|
246
277
|
throw error;
|
|
247
278
|
}
|
|
248
279
|
}
|
|
@@ -256,7 +287,6 @@ export async function movePathWithCopyFallback(options) {
|
|
|
256
287
|
const targetDir = path.dirname(targetPath);
|
|
257
288
|
const staged = path.join(targetDir, `.fs-safe-move-${process.pid}-${randomUUID()}.tmp`);
|
|
258
289
|
const unregisterStaged = registerTempPathForExit(staged, { recursive: true });
|
|
259
|
-
let stagedCommitted = false;
|
|
260
290
|
try {
|
|
261
291
|
const manifest = await copyEntryWithManifest(sourcePath, staged, {
|
|
262
292
|
sourceHardlinks: options.sourceHardlinks ?? "allow",
|
|
@@ -265,16 +295,23 @@ export async function movePathWithCopyFallback(options) {
|
|
|
265
295
|
const cleanupState = createCleanupCopiedEntryState(sourcePath, manifest);
|
|
266
296
|
unregisterStaged.setIdentity(await fs.lstat(staged, { bigint: true }));
|
|
267
297
|
await assertCopyDestinationOutsideSource(sourcePath, targetPath, manifest);
|
|
268
|
-
await guardedRename({
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
298
|
+
await guardedRename({
|
|
299
|
+
from: staged,
|
|
300
|
+
to: targetPath,
|
|
301
|
+
assertBeforeRename,
|
|
302
|
+
onSourceInspected,
|
|
303
|
+
onRenamed: () => {
|
|
304
|
+
unregisterStaged();
|
|
305
|
+
onRenamed();
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
const cleanupResult = await cleanupCopiedEntry(sourcePath, manifest, cleanupState, assertBeforeMutation);
|
|
272
309
|
if (cleanupResult === "stale") {
|
|
273
310
|
throw sourceChangedError(sourcePath);
|
|
274
311
|
}
|
|
275
312
|
}
|
|
276
313
|
finally {
|
|
277
|
-
if (!
|
|
314
|
+
if (!destinationPublished) {
|
|
278
315
|
try {
|
|
279
316
|
const stagedIdentity = await fs.lstat(staged, { bigint: true });
|
|
280
317
|
if (!stagedIdentity.isSymbolicLink())
|
|
@@ -18,5 +18,4 @@ export declare function removeNativeCreatedFileIfStillPinned(params: {
|
|
|
18
18
|
created?: BigIntStats;
|
|
19
19
|
}): void;
|
|
20
20
|
export declare function createNativeExclusiveFile(targetPath: string, mode: number): Promise<NativeFileHandle | undefined>;
|
|
21
|
-
export declare function syncNativeFileBestEffort(fd: number): void;
|
|
22
21
|
//# sourceMappingURL=native-operations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-operations.d.ts","sourceRoot":"","sources":["../src/native-operations.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAG/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAI7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5E,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAS5D;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,gBAAgB,EACvB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAgBf;AAsBD,wBAAgB,oCAAoC,CAAC,MAAM,EAAE;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB,GAAG,IAAI,CAqBP;AAED,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAwDvC
|
|
1
|
+
{"version":3,"file":"native-operations.d.ts","sourceRoot":"","sources":["../src/native-operations.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAG/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAI7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5E,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAS5D;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,gBAAgB,EACvB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAgBf;AAsBD,wBAAgB,oCAAoC,CAAC,MAAM,EAAE;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB,GAAG,IAAI,CAqBP;AAED,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAwDvC"}
|
|
@@ -130,13 +130,3 @@ export async function createNativeExclusiveFile(targetPath, mode) {
|
|
|
130
130
|
await parent.close().catch(() => undefined);
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
-
export function syncNativeFileBestEffort(fd) {
|
|
134
|
-
try {
|
|
135
|
-
fsSync.fsyncSync(fd);
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
if (error.code !== "EPERM") {
|
|
139
|
-
throw error;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|