@openclaw/feishu 2026.9.8 → 2026.10.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.setup/{channel-DV4hM2Uf.mjs → channel-CX62T71S.mjs} +146 -245
- package/dist/.setup/{channel.runtime-CXQcH5zZ.mjs → channel.runtime-COiaq-Rv.mjs} +6 -12
- package/dist/.setup/{chat-D8MlFAZi.mjs → chat-BdyvImsY.mjs} +6 -9
- package/dist/.setup/{client-BYG-_IZl.mjs → client-BsBVWJzN.mjs} +1 -1
- package/dist/.setup/{doctor-contract-3XC0vbIw.mjs → doctor-contract-B1B9ogdd.mjs} +212 -27
- package/dist/.setup/{monitor-D_rsHBZ6.mjs → monitor-7DvwUs4Y.mjs} +5 -6
- package/dist/.setup/{monitor.account-DvvY7i6k.mjs → monitor.account-7xVu7XWY.mjs} +190 -393
- package/dist/.setup/{probe-_ViqSi0j.mjs → probe-B9o7iey6.mjs} +13 -39
- package/dist/.setup/{reply-delivery-result-COAjaukc.mjs → reply-delivery-result-Bt-BWBEA.mjs} +151 -297
- package/dist/.setup/{setup-api-C4S5I3ac.mjs → setup-api-DmzX9S01.mjs} +1 -1
- package/dist/.setup/{subagent-hooks-BaFoMu8W.mjs → subagent-hooks-CUXg0pC-.mjs} +5 -11
- package/dist/.setup/{thread-bindings-EdLXPXzw.mjs → thread-bindings-jW2x5VuN.mjs} +23 -41
- package/dist/api.js +234 -297
- package/dist/channel-plugin-api.js +1 -1
- package/dist/doctor-contract-api.js +2 -2
- package/dist/session-binding-contract-api.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/setup-entry.js +1 -1
- package/dist/subagent-hooks-api.js +1 -1
- package/node_modules/@openclaw/fs-safe/CHANGELOG.md +95 -0
- package/node_modules/@openclaw/fs-safe/README.md +70 -379
- package/node_modules/@openclaw/fs-safe/dist/absolute-path.js +35 -51
- package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/advanced.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-input.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.js +9 -10
- package/node_modules/@openclaw/fs-safe/dist/archive.js +2 -5
- package/node_modules/@openclaw/fs-safe/dist/atomic-io.d.ts +51 -0
- package/node_modules/@openclaw/fs-safe/dist/atomic-io.js +242 -0
- package/node_modules/@openclaw/fs-safe/dist/config.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/config.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/copy-file-input.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/copy-file-input.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/copy-tree-portable.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/create.js +12 -5
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.d.ts +11 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.js +4 -7
- package/node_modules/@openclaw/fs-safe/dist/entry-publication-types.d.ts +55 -0
- package/node_modules/@openclaw/fs-safe/dist/entry-publication-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/entry-publication.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/entry-publication.js +262 -0
- package/node_modules/@openclaw/fs-safe/dist/exclusive-create.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/exclusive-create.js +22 -0
- package/node_modules/@openclaw/fs-safe/dist/file-cleanup.d.ts +1 -6
- package/node_modules/@openclaw/fs-safe/dist/file-cleanup.js +3 -6
- package/node_modules/@openclaw/fs-safe/dist/file-identity.js +3 -6
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-io.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-mutation.js +9 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root.js +4 -6
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-stale-admission.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.js +8 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.js +20 -18
- package/node_modules/@openclaw/fs-safe/dist/file-store.js +4 -10
- package/node_modules/@openclaw/fs-safe/dist/fs.d.ts +2 -10
- package/node_modules/@openclaw/fs-safe/dist/fs.js +2 -10
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts +3 -4
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js +6 -18
- package/node_modules/@openclaw/fs-safe/dist/guest-dispatch-python.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/guest-native-python.js +0 -2
- package/node_modules/@openclaw/fs-safe/dist/guest.js +3 -9
- package/node_modules/@openclaw/fs-safe/dist/index.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/index.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.js +1 -5
- package/node_modules/@openclaw/fs-safe/dist/json.js +19 -37
- package/node_modules/@openclaw/fs-safe/dist/move-path.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/mutation-authority.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/mutation-authority.js +9 -1
- package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +47 -2
- package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts +1 -9
- package/node_modules/@openclaw/fs-safe/dist/native-config.js +6 -40
- package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.js +5 -2
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.js +11 -316
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent-windows.d.ts +7 -7
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent-windows.js +28 -175
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.js +418 -0
- package/node_modules/@openclaw/fs-safe/dist/native-rename-outcome.js +9 -4
- package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +17 -13
- package/node_modules/@openclaw/fs-safe/dist/native-staged-symlink.js +6 -24
- package/node_modules/@openclaw/fs-safe/dist/native.js +5 -1
- package/node_modules/@openclaw/fs-safe/dist/path-case.js +10 -9
- package/node_modules/@openclaw/fs-safe/dist/path-scope-lexical.js +4 -1
- package/node_modules/@openclaw/fs-safe/dist/path-segment-route.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/path-segment-route.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/path.js +4 -1
- package/node_modules/@openclaw/fs-safe/dist/permissions-windows.d.ts +0 -1
- package/node_modules/@openclaw/fs-safe/dist/pinned-mutation-admission.js +1 -3
- package/node_modules/@openclaw/fs-safe/dist/pinned-write-staged.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-write.js +9 -10
- package/node_modules/@openclaw/fs-safe/dist/private-producer-handoff.js +3 -6
- package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/publish-file.js +4 -3
- package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.d.ts +3 -4
- package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.js +18 -32
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.d.ts +5 -17
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.js +92 -230
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.d.ts +4 -15
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.js +22 -63
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.d.ts +9 -34
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.js +78 -83
- package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.d.ts +18 -20
- package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.js +64 -98
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.d.ts +16 -33
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.js +61 -200
- package/node_modules/@openclaw/fs-safe/dist/replace-file-types.d.ts +1 -6
- package/node_modules/@openclaw/fs-safe/dist/replace-file.js +76 -216
- package/node_modules/@openclaw/fs-safe/dist/root-boundary.js +14 -24
- package/node_modules/@openclaw/fs-safe/dist/root-context.d.ts +1 -4
- package/node_modules/@openclaw/fs-safe/dist/root-context.js +4 -19
- package/node_modules/@openclaw/fs-safe/dist/root-create-native.d.ts +52 -0
- package/node_modules/@openclaw/fs-safe/dist/root-create-native.js +350 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.d.ts +35 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list.d.ts +2 -27
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list.js +31 -28
- package/node_modules/@openclaw/fs-safe/dist/root-directory.js +1 -4
- package/node_modules/@openclaw/fs-safe/dist/root-errors.js +34 -0
- package/node_modules/@openclaw/fs-safe/dist/root-file.js +9 -21
- package/node_modules/@openclaw/fs-safe/dist/root-impl.js +105 -37
- package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.d.ts +7 -2
- package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.js +67 -38
- package/node_modules/@openclaw/fs-safe/dist/root-observed-path.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/root-observed-path.js +0 -2
- package/node_modules/@openclaw/fs-safe/dist/root-options.d.ts +2 -3
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.js +3 -1
- package/node_modules/@openclaw/fs-safe/dist/root-path-stat.js +68 -85
- package/node_modules/@openclaw/fs-safe/dist/root-path.js +6 -1
- package/node_modules/@openclaw/fs-safe/dist/root-paths-lexical.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/root-paths-lexical.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/root-paths.js +4 -9
- package/node_modules/@openclaw/fs-safe/dist/root-remove-native.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/root-remove-native.js +311 -0
- package/node_modules/@openclaw/fs-safe/dist/root-remove.d.ts +11 -0
- package/node_modules/@openclaw/fs-safe/dist/root-remove.js +3 -1
- package/node_modules/@openclaw/fs-safe/dist/root-walk.d.ts +2 -2
- package/node_modules/@openclaw/fs-safe/dist/root-walk.js +1 -3
- package/node_modules/@openclaw/fs-safe/dist/root-write-admission.d.ts +3 -3
- package/node_modules/@openclaw/fs-safe/dist/root-write-admission.js +8 -10
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.d.ts +0 -1
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.js +0 -4
- package/node_modules/@openclaw/fs-safe/dist/secret-file.js +12 -9
- package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.d.ts +0 -2
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-temp.js +7 -4
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.js +13 -6
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.d.ts +0 -3
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js +5 -23
- package/node_modules/@openclaw/fs-safe/dist/staged-file-settlement.d.ts +2 -1
- package/node_modules/@openclaw/fs-safe/dist/staged-file-settlement.js +11 -6
- package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.js +1 -8
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.js +2 -9
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.d.ts +1 -6
- package/node_modules/@openclaw/fs-safe/dist/trash.js +6 -2
- package/node_modules/@openclaw/fs-safe/dist/walk.js +100 -46
- package/node_modules/@openclaw/fs-safe/dist/watch-hints.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-hints.js +235 -19
- package/node_modules/@openclaw/fs-safe/dist/watch-native.d.ts +21 -2
- package/node_modules/@openclaw/fs-safe/dist/watch-native.js +21 -3
- package/node_modules/@openclaw/fs-safe/dist/watch-rescan.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-rescan.js +111 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-scan.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-scan.js +27 -4
- package/node_modules/@openclaw/fs-safe/dist/watch-stream.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/watch.js +131 -40
- package/node_modules/@openclaw/fs-safe/dist/windows-path-alias.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-path-alias.js +24 -6
- package/node_modules/@openclaw/fs-safe/dist/windows-path-syntax.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-path-syntax.js +51 -0
- package/node_modules/@openclaw/fs-safe/docs/advanced.md +4 -0
- package/node_modules/@openclaw/fs-safe/docs/atomic.md +4 -1
- package/node_modules/@openclaw/fs-safe/docs/config.md +6 -14
- package/node_modules/@openclaw/fs-safe/docs/contributing.md +4 -14
- package/node_modules/@openclaw/fs-safe/docs/durability.md +6 -29
- package/node_modules/@openclaw/fs-safe/docs/entry-publication.md +146 -0
- package/node_modules/@openclaw/fs-safe/docs/errors.md +16 -0
- package/node_modules/@openclaw/fs-safe/docs/file-store.md +28 -5
- package/node_modules/@openclaw/fs-safe/docs/index.md +2 -31
- package/node_modules/@openclaw/fs-safe/docs/install.md +10 -31
- package/node_modules/@openclaw/fs-safe/docs/json.md +1 -1
- package/node_modules/@openclaw/fs-safe/docs/local-roots.md +0 -1
- package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +12 -12
- package/node_modules/@openclaw/fs-safe/docs/native-helper.md +35 -96
- package/node_modules/@openclaw/fs-safe/docs/native.md +22 -20
- package/node_modules/@openclaw/fs-safe/docs/path.md +1 -1
- package/node_modules/@openclaw/fs-safe/docs/permissions.md +1 -2
- package/node_modules/@openclaw/fs-safe/docs/public-api.md +1 -2
- package/node_modules/@openclaw/fs-safe/docs/reading.md +1 -2
- package/node_modules/@openclaw/fs-safe/docs/root.md +26 -184
- package/node_modules/@openclaw/fs-safe/docs/secret-file.md +1 -1
- package/node_modules/@openclaw/fs-safe/docs/security-model.md +115 -3
- package/node_modules/@openclaw/fs-safe/docs/store.md +2 -2
- package/node_modules/@openclaw/fs-safe/docs/temp.md +29 -65
- package/node_modules/@openclaw/fs-safe/docs/testing.md +90 -58
- package/node_modules/@openclaw/fs-safe/docs/types.md +3 -16
- package/node_modules/@openclaw/fs-safe/docs/walk.md +33 -5
- package/node_modules/@openclaw/fs-safe/docs/watch.md +96 -14
- package/node_modules/@openclaw/fs-safe/docs/writing.md +172 -16
- package/node_modules/@openclaw/fs-safe/package.json +10 -10
- package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +1 -1
- package/package.json +5 -5
- package/skills/feishu-wiki/SKILL.md +1 -1
- package/dist/.setup/accounts-wRqItHug.mjs +0 -206
- package/node_modules/@openclaw/fs-safe/dist/watch-alias.d.ts +0 -6
- package/node_modules/@openclaw/fs-safe/dist/watch-alias.js +0 -88
- package/node_modules/@openclaw/fs-safe/docs/mutation-policy-proof.md +0 -69
- package/node_modules/@openclaw/fs-safe/docs/private-file-store.md +0 -68
- package/node_modules/@openclaw/fs-safe/docs/test-hooks.md +0 -110
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import syncFs, {} from "node:fs";
|
|
2
|
-
import fs
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { createAsyncDirectoryGuard } from "./directory-guard.js";
|
|
5
|
-
import { hasErrorCode
|
|
5
|
+
import { hasErrorCode } from "./file-cleanup.js";
|
|
6
6
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
7
7
|
import { FsSafeError } from "./errors.js";
|
|
8
8
|
import { sameFileIdentityForCleanup, sha256Hex } from "./file-identity.js";
|
|
9
9
|
import { withAsyncDirectoryGuards } from "./guarded-mutation.js";
|
|
10
|
-
import {
|
|
10
|
+
import { inspectAtomicIdentity, wait } from "./atomic-io.js";
|
|
11
11
|
import { registerTempPathForExit } from "./temp-cleanup.js";
|
|
12
12
|
const PUBLISHED_READ_FLAGS = resolveReadOpenFlags();
|
|
13
13
|
function describeFailure(error) {
|
|
@@ -66,49 +66,16 @@ function closeFailure(closeError, params, cleanupFailure) {
|
|
|
66
66
|
: closeError,
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
await removeOwnedPath(params);
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
catch (cleanupError) {
|
|
75
|
-
if (params.throwOnCleanupError) {
|
|
76
|
-
throw cleanupFailure(params.originalFailure, cleanupError);
|
|
77
|
-
}
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function cleanupOwnedPathSync(params) {
|
|
82
|
-
if (!params.identity)
|
|
83
|
-
return true;
|
|
84
|
-
try {
|
|
85
|
-
const current = params.fsModule.lstatSync(params.pathname, { bigint: true });
|
|
86
|
-
if (current.isSymbolicLink() ||
|
|
87
|
-
!current.isFile() ||
|
|
88
|
-
current.nlink !== 1n ||
|
|
89
|
-
!sameFileIdentityForCleanup(current, params.identity)) {
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
params.fsModule.unlinkSync(params.pathname);
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
catch (cleanupError) {
|
|
96
|
-
if (hasErrorCode(cleanupError, "ENOENT"))
|
|
97
|
-
return true;
|
|
98
|
-
if (params.throwOnCleanupError) {
|
|
99
|
-
throw cleanupFailure(params.originalFailure, cleanupError);
|
|
100
|
-
}
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
class AtomicTempOwner {
|
|
69
|
+
export class AtomicTempOwner {
|
|
105
70
|
pathname;
|
|
71
|
+
io;
|
|
106
72
|
resource;
|
|
107
73
|
recordedIdentity;
|
|
108
74
|
exists = false;
|
|
109
75
|
unregister;
|
|
110
|
-
constructor(pathname) {
|
|
76
|
+
constructor(pathname, io) {
|
|
111
77
|
this.pathname = pathname;
|
|
78
|
+
this.io = io;
|
|
112
79
|
this.unregister = registerTempPathForExit(pathname, { singleLinkFile: true });
|
|
113
80
|
}
|
|
114
81
|
start() {
|
|
@@ -133,26 +100,20 @@ class AtomicTempOwner {
|
|
|
133
100
|
this.resource = undefined;
|
|
134
101
|
return resource;
|
|
135
102
|
}
|
|
136
|
-
}
|
|
137
|
-
export class AsyncAtomicTempOwner extends AtomicTempOwner {
|
|
138
103
|
adopt(temp) {
|
|
139
|
-
this.resource = temp.
|
|
104
|
+
this.resource = temp.file;
|
|
140
105
|
this.onIdentity(temp.identity);
|
|
141
106
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}, this.identity);
|
|
107
|
+
inspectOwned(read, pathname, pathnameEntry, expected) {
|
|
108
|
+
return inspectAtomicIdentity(this.io, read, expected, false, stat => assertOwnedFile(stat, pathname, pathnameEntry));
|
|
109
|
+
}
|
|
110
|
+
*assertCurrent(pathname = this.pathname) {
|
|
111
|
+
const openedInspection = this.inspectOwned(() => this.resource.statExact(), pathname, false, this.identity);
|
|
112
|
+
const opened = (this.io.asynchronous ? (yield openedInspection) : openedInspection);
|
|
149
113
|
try {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
assertOwnedFile(stat, pathname, true);
|
|
154
|
-
return stat;
|
|
155
|
-
}, opened);
|
|
114
|
+
const currentInspection = this.inspectOwned(() => this.io.lstatExact(pathname), pathname, true, opened);
|
|
115
|
+
if (this.io.asynchronous)
|
|
116
|
+
yield currentInspection;
|
|
156
117
|
}
|
|
157
118
|
catch (error) {
|
|
158
119
|
if (hasErrorCode(error, "ENOENT")) {
|
|
@@ -161,10 +122,10 @@ export class AsyncAtomicTempOwner extends AtomicTempOwner {
|
|
|
161
122
|
throw error;
|
|
162
123
|
}
|
|
163
124
|
}
|
|
164
|
-
|
|
125
|
+
*assertPublished(pathname, expectedHash, onVerified) {
|
|
165
126
|
let identityCurrent = false;
|
|
166
127
|
try {
|
|
167
|
-
|
|
128
|
+
yield* this.assertCurrent(pathname);
|
|
168
129
|
identityCurrent = true;
|
|
169
130
|
}
|
|
170
131
|
catch (error) {
|
|
@@ -179,7 +140,7 @@ export class AsyncAtomicTempOwner extends AtomicTempOwner {
|
|
|
179
140
|
let published;
|
|
180
141
|
try {
|
|
181
142
|
try {
|
|
182
|
-
published =
|
|
143
|
+
published = yield* this.io.open(pathname, PUBLISHED_READ_FLAGS);
|
|
183
144
|
}
|
|
184
145
|
catch (error) {
|
|
185
146
|
if (hasErrorCode(error, "ELOOP")) {
|
|
@@ -189,163 +150,63 @@ export class AsyncAtomicTempOwner extends AtomicTempOwner {
|
|
|
189
150
|
}
|
|
190
151
|
throw error;
|
|
191
152
|
}
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
await inspectFileIdentity(async () => {
|
|
199
|
-
const stat = fsModule === fs ? syncFs.lstatSync(pathname, { bigint: true })
|
|
200
|
-
: await fsModule.lstat(pathname, { bigint: true });
|
|
201
|
-
assertOwnedFile(stat, pathname, true);
|
|
202
|
-
return stat;
|
|
203
|
-
}, identity);
|
|
204
|
-
if (sha256Hex(await published.readFile()) !== expectedHash) {
|
|
153
|
+
const openedInspection = this.inspectOwned(() => published.statExact(), pathname, false);
|
|
154
|
+
const identity = (this.io.asynchronous ? (yield openedInspection) : openedInspection);
|
|
155
|
+
const currentInspection = this.inspectOwned(() => this.io.lstatExact(pathname), pathname, true, identity);
|
|
156
|
+
if (this.io.asynchronous)
|
|
157
|
+
yield currentInspection;
|
|
158
|
+
if (sha256Hex(yield* published.readFile()) !== expectedHash) {
|
|
205
159
|
throw new FsSafeError("path-mismatch", `Atomic replace published content changed: ${pathname}`);
|
|
206
160
|
}
|
|
207
161
|
onVerified?.(identity);
|
|
208
|
-
const
|
|
209
|
-
|
|
162
|
+
const previous = this.takeResource();
|
|
163
|
+
const closing = previous?.close();
|
|
164
|
+
if (previous && this.io.asynchronous)
|
|
165
|
+
yield closing;
|
|
210
166
|
this.resource = published;
|
|
211
167
|
this.recordedIdentity = identity;
|
|
212
168
|
published = undefined;
|
|
213
169
|
}
|
|
214
170
|
finally {
|
|
215
171
|
try {
|
|
216
|
-
|
|
172
|
+
const closing = published?.close();
|
|
173
|
+
if (published && this.io.asynchronous)
|
|
174
|
+
yield closing;
|
|
217
175
|
}
|
|
218
176
|
catch {
|
|
219
|
-
// Preserve the selected verification or previous-
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
async finish(params) {
|
|
224
|
-
let deferredFailure;
|
|
225
|
-
let cleanupComplete = !this.exists;
|
|
226
|
-
if (this.exists) {
|
|
227
|
-
try {
|
|
228
|
-
cleanupComplete = await cleanupOwnedPath({
|
|
229
|
-
fsModule: params.fsModule,
|
|
230
|
-
pathname: this.pathname,
|
|
231
|
-
identity: this.recordedIdentity,
|
|
232
|
-
originalFailure: params.originalFailure,
|
|
233
|
-
throwOnCleanupError: params.throwOnCleanupError,
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
catch (error) {
|
|
237
|
-
deferredFailure = { error };
|
|
177
|
+
// Preserve the selected verification or previous-resource close failure.
|
|
238
178
|
}
|
|
239
179
|
}
|
|
240
|
-
if (cleanupComplete)
|
|
241
|
-
this.unregister();
|
|
242
|
-
const handle = this.takeResource();
|
|
243
|
-
try {
|
|
244
|
-
await handle?.close();
|
|
245
|
-
}
|
|
246
|
-
catch (closeError) {
|
|
247
|
-
deferredFailure = closeFailure(closeError, params, deferredFailure);
|
|
248
|
-
}
|
|
249
|
-
if (deferredFailure)
|
|
250
|
-
throw deferredFailure.error;
|
|
251
180
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
this.onIdentity(temp.identity);
|
|
257
|
-
}
|
|
258
|
-
assertCurrent(fsModule, pathname = this.pathname) {
|
|
259
|
-
const opened = inspectFileIdentitySync(() => {
|
|
260
|
-
const stat = fsModule.fstatSync(this.resource, { bigint: true });
|
|
261
|
-
assertOwnedFile(stat, pathname, false);
|
|
262
|
-
return stat;
|
|
263
|
-
}, this.identity);
|
|
264
|
-
try {
|
|
265
|
-
inspectFileIdentitySync(() => {
|
|
266
|
-
const stat = fsModule.lstatSync(pathname, { bigint: true });
|
|
267
|
-
assertOwnedFile(stat, pathname, true);
|
|
268
|
-
return stat;
|
|
269
|
-
}, opened);
|
|
270
|
-
}
|
|
271
|
-
catch (error) {
|
|
272
|
-
if (hasErrorCode(error, "ENOENT")) {
|
|
273
|
-
throw missingOwnedFile(pathname, error);
|
|
274
|
-
}
|
|
275
|
-
throw error;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
assertPublished(fsModule, pathname, expectedHash, onVerified) {
|
|
279
|
-
let identityCurrent = false;
|
|
280
|
-
try {
|
|
281
|
-
this.assertCurrent(fsModule, pathname);
|
|
282
|
-
identityCurrent = true;
|
|
283
|
-
}
|
|
284
|
-
catch (error) {
|
|
285
|
-
if (!(error instanceof FsSafeError) || !hasErrorCode(error, "path-mismatch") || !expectedHash) {
|
|
286
|
-
throw error;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
if (identityCurrent) {
|
|
290
|
-
onVerified?.(this.identity);
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
let publishedFd;
|
|
181
|
+
*cleanupOwnedPath(params) {
|
|
182
|
+
const identity = this.recordedIdentity;
|
|
183
|
+
if (!identity)
|
|
184
|
+
return true;
|
|
294
185
|
try {
|
|
295
|
-
|
|
296
|
-
|
|
186
|
+
const observation = this.io.lstatExact(this.pathname);
|
|
187
|
+
const current = this.io.asyncFs && this.io.asyncFs !== fs
|
|
188
|
+
? yield* wait(observation) : observation;
|
|
189
|
+
if (!current.isSymbolicLink() && current.isFile() && current.nlink === 1n &&
|
|
190
|
+
sameFileIdentityForCleanup(current, identity)) {
|
|
191
|
+
yield* this.io.unlink(this.pathname);
|
|
297
192
|
}
|
|
298
|
-
|
|
299
|
-
if (hasErrorCode(error, "ELOOP")) {
|
|
300
|
-
throw new FsSafeError("symlink", `Atomic replace published file became a symlink: ${pathname}`, {
|
|
301
|
-
cause: error,
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
throw error;
|
|
305
|
-
}
|
|
306
|
-
const identity = inspectFileIdentitySync(() => {
|
|
307
|
-
const stat = fsModule.fstatSync(publishedFd, { bigint: true });
|
|
308
|
-
assertOwnedFile(stat, pathname, false);
|
|
309
|
-
return stat;
|
|
310
|
-
});
|
|
311
|
-
inspectFileIdentitySync(() => {
|
|
312
|
-
const stat = fsModule.lstatSync(pathname, { bigint: true });
|
|
313
|
-
assertOwnedFile(stat, pathname, true);
|
|
314
|
-
return stat;
|
|
315
|
-
}, identity);
|
|
316
|
-
if (sha256Hex(fsModule.readFileSync(publishedFd)) !== expectedHash) {
|
|
317
|
-
throw new FsSafeError("path-mismatch", `Atomic replace published content changed: ${pathname}`);
|
|
318
|
-
}
|
|
319
|
-
onVerified?.(identity);
|
|
320
|
-
const previousFd = this.takeResource();
|
|
321
|
-
fsModule.closeSync(previousFd);
|
|
322
|
-
this.resource = publishedFd;
|
|
323
|
-
this.recordedIdentity = identity;
|
|
324
|
-
publishedFd = undefined;
|
|
193
|
+
return true;
|
|
325
194
|
}
|
|
326
|
-
|
|
327
|
-
if (
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
catch {
|
|
332
|
-
// Best-effort close after a rejected content verification.
|
|
333
|
-
}
|
|
195
|
+
catch (cleanupError) {
|
|
196
|
+
if (hasErrorCode(cleanupError, "ENOENT"))
|
|
197
|
+
return true;
|
|
198
|
+
if (params.throwOnCleanupError) {
|
|
199
|
+
throw cleanupFailure(params.originalFailure, cleanupError);
|
|
334
200
|
}
|
|
201
|
+
return false;
|
|
335
202
|
}
|
|
336
203
|
}
|
|
337
|
-
finish(params) {
|
|
204
|
+
*finish(params) {
|
|
338
205
|
let deferredFailure;
|
|
339
206
|
let cleanupComplete = !this.exists;
|
|
340
207
|
if (this.exists) {
|
|
341
208
|
try {
|
|
342
|
-
cleanupComplete =
|
|
343
|
-
fsModule: params.fsModule,
|
|
344
|
-
pathname: this.pathname,
|
|
345
|
-
identity: this.recordedIdentity,
|
|
346
|
-
originalFailure: params.originalFailure,
|
|
347
|
-
throwOnCleanupError: params.throwOnCleanupError,
|
|
348
|
-
});
|
|
209
|
+
cleanupComplete = yield* this.cleanupOwnedPath(params);
|
|
349
210
|
}
|
|
350
211
|
catch (error) {
|
|
351
212
|
deferredFailure = { error };
|
|
@@ -353,14 +214,14 @@ export class SyncAtomicTempOwner extends AtomicTempOwner {
|
|
|
353
214
|
}
|
|
354
215
|
if (cleanupComplete)
|
|
355
216
|
this.unregister();
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
217
|
+
const file = this.takeResource();
|
|
218
|
+
try {
|
|
219
|
+
const closing = file?.close();
|
|
220
|
+
if (file && this.io.asynchronous)
|
|
221
|
+
yield closing;
|
|
222
|
+
}
|
|
223
|
+
catch (closeError) {
|
|
224
|
+
deferredFailure = closeFailure(closeError, params, deferredFailure);
|
|
364
225
|
}
|
|
365
226
|
if (deferredFailure)
|
|
366
227
|
throw deferredFailure.error;
|
|
@@ -4,14 +4,9 @@ import type { RenameIdentityPolicy } from "./pinned-write-types.js";
|
|
|
4
4
|
import type { AtomicMutationOptions } from "./replace-file-mutation.js";
|
|
5
5
|
import type { ReplaceFileCopyFallbackRestorePolicy, ReplaceFileDestinationHardlinkPolicy } from "./replace-file-copy-fallback.js";
|
|
6
6
|
export type ReplaceFileAtomicFileSystem = {
|
|
7
|
-
promises: Pick<typeof fs, "mkdir" | "writeFile" | "rename" | "copyFile" | "unlink" | "rm" | "open" | "stat" | "lstat"
|
|
8
|
-
/** @deprecated Accepted for adapter compatibility but never called. */
|
|
9
|
-
chmod?: typeof fs.chmod;
|
|
10
|
-
};
|
|
7
|
+
promises: Pick<typeof fs, "mkdir" | "writeFile" | "rename" | "copyFile" | "unlink" | "rm" | "open" | "stat" | "lstat">;
|
|
11
8
|
};
|
|
12
9
|
export type ReplaceFileAtomicSyncFileSystem = Pick<typeof syncFs, "mkdirSync" | "readFileSync" | "writeFileSync" | "renameSync" | "copyFileSync" | "unlinkSync" | "rmSync" | "openSync" | "fsyncSync" | "closeSync" | "fstatSync" | "statSync" | "lstatSync" | "ftruncateSync" | "readSync" | "writeSync"> & {
|
|
13
|
-
/** @deprecated Accepted for adapter compatibility but never called. */
|
|
14
|
-
chmodSync?: typeof syncFs.chmodSync;
|
|
15
10
|
fchmodSync?: typeof syncFs.fchmodSync;
|
|
16
11
|
};
|
|
17
12
|
export type ReplaceFileAtomicBaseOptions = AtomicMutationOptions & {
|