@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.
Files changed (225) hide show
  1. package/dist/.setup/{channel-DV4hM2Uf.mjs → channel-CX62T71S.mjs} +146 -245
  2. package/dist/.setup/{channel.runtime-CXQcH5zZ.mjs → channel.runtime-COiaq-Rv.mjs} +6 -12
  3. package/dist/.setup/{chat-D8MlFAZi.mjs → chat-BdyvImsY.mjs} +6 -9
  4. package/dist/.setup/{client-BYG-_IZl.mjs → client-BsBVWJzN.mjs} +1 -1
  5. package/dist/.setup/{doctor-contract-3XC0vbIw.mjs → doctor-contract-B1B9ogdd.mjs} +212 -27
  6. package/dist/.setup/{monitor-D_rsHBZ6.mjs → monitor-7DvwUs4Y.mjs} +5 -6
  7. package/dist/.setup/{monitor.account-DvvY7i6k.mjs → monitor.account-7xVu7XWY.mjs} +190 -393
  8. package/dist/.setup/{probe-_ViqSi0j.mjs → probe-B9o7iey6.mjs} +13 -39
  9. package/dist/.setup/{reply-delivery-result-COAjaukc.mjs → reply-delivery-result-Bt-BWBEA.mjs} +151 -297
  10. package/dist/.setup/{setup-api-C4S5I3ac.mjs → setup-api-DmzX9S01.mjs} +1 -1
  11. package/dist/.setup/{subagent-hooks-BaFoMu8W.mjs → subagent-hooks-CUXg0pC-.mjs} +5 -11
  12. package/dist/.setup/{thread-bindings-EdLXPXzw.mjs → thread-bindings-jW2x5VuN.mjs} +23 -41
  13. package/dist/api.js +234 -297
  14. package/dist/channel-plugin-api.js +1 -1
  15. package/dist/doctor-contract-api.js +2 -2
  16. package/dist/session-binding-contract-api.js +1 -1
  17. package/dist/setup-api.js +1 -1
  18. package/dist/setup-entry.js +1 -1
  19. package/dist/subagent-hooks-api.js +1 -1
  20. package/node_modules/@openclaw/fs-safe/CHANGELOG.md +95 -0
  21. package/node_modules/@openclaw/fs-safe/README.md +70 -379
  22. package/node_modules/@openclaw/fs-safe/dist/absolute-path.js +35 -51
  23. package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts +2 -0
  24. package/node_modules/@openclaw/fs-safe/dist/advanced.js +1 -0
  25. package/node_modules/@openclaw/fs-safe/dist/archive-input.js +2 -0
  26. package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
  27. package/node_modules/@openclaw/fs-safe/dist/archive-staging.d.ts +1 -1
  28. package/node_modules/@openclaw/fs-safe/dist/archive-staging.js +9 -10
  29. package/node_modules/@openclaw/fs-safe/dist/archive.js +2 -5
  30. package/node_modules/@openclaw/fs-safe/dist/atomic-io.d.ts +51 -0
  31. package/node_modules/@openclaw/fs-safe/dist/atomic-io.js +242 -0
  32. package/node_modules/@openclaw/fs-safe/dist/config.d.ts +1 -1
  33. package/node_modules/@openclaw/fs-safe/dist/config.js +1 -1
  34. package/node_modules/@openclaw/fs-safe/dist/copy-file-input.d.ts +1 -1
  35. package/node_modules/@openclaw/fs-safe/dist/copy-file-input.js +2 -2
  36. package/node_modules/@openclaw/fs-safe/dist/copy-tree-portable.js +2 -0
  37. package/node_modules/@openclaw/fs-safe/dist/create.js +12 -5
  38. package/node_modules/@openclaw/fs-safe/dist/directory-guard.d.ts +11 -0
  39. package/node_modules/@openclaw/fs-safe/dist/directory-guard.js +4 -7
  40. package/node_modules/@openclaw/fs-safe/dist/entry-publication-types.d.ts +55 -0
  41. package/node_modules/@openclaw/fs-safe/dist/entry-publication-types.js +1 -0
  42. package/node_modules/@openclaw/fs-safe/dist/entry-publication.d.ts +8 -0
  43. package/node_modules/@openclaw/fs-safe/dist/entry-publication.js +262 -0
  44. package/node_modules/@openclaw/fs-safe/dist/exclusive-create.d.ts +3 -0
  45. package/node_modules/@openclaw/fs-safe/dist/exclusive-create.js +22 -0
  46. package/node_modules/@openclaw/fs-safe/dist/file-cleanup.d.ts +1 -6
  47. package/node_modules/@openclaw/fs-safe/dist/file-cleanup.js +3 -6
  48. package/node_modules/@openclaw/fs-safe/dist/file-identity.js +3 -6
  49. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-io.js +2 -2
  50. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-mutation.js +9 -0
  51. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root.js +4 -6
  52. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-stale-admission.js +1 -1
  53. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.js +8 -0
  54. package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.js +2 -0
  55. package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.js +20 -18
  56. package/node_modules/@openclaw/fs-safe/dist/file-store.js +4 -10
  57. package/node_modules/@openclaw/fs-safe/dist/fs.d.ts +2 -10
  58. package/node_modules/@openclaw/fs-safe/dist/fs.js +2 -10
  59. package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts +3 -4
  60. package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js +6 -18
  61. package/node_modules/@openclaw/fs-safe/dist/guest-dispatch-python.js +1 -1
  62. package/node_modules/@openclaw/fs-safe/dist/guest-native-python.js +0 -2
  63. package/node_modules/@openclaw/fs-safe/dist/guest.js +3 -9
  64. package/node_modules/@openclaw/fs-safe/dist/index.d.ts +1 -1
  65. package/node_modules/@openclaw/fs-safe/dist/index.js +1 -1
  66. package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.js +1 -5
  67. package/node_modules/@openclaw/fs-safe/dist/json.js +19 -37
  68. package/node_modules/@openclaw/fs-safe/dist/move-path.js +2 -0
  69. package/node_modules/@openclaw/fs-safe/dist/mutation-authority.d.ts +1 -0
  70. package/node_modules/@openclaw/fs-safe/dist/mutation-authority.js +9 -1
  71. package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +47 -2
  72. package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts +1 -9
  73. package/node_modules/@openclaw/fs-safe/dist/native-config.js +6 -40
  74. package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.d.ts +2 -0
  75. package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.js +5 -2
  76. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.js +11 -316
  77. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent-windows.d.ts +7 -7
  78. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent-windows.js +28 -175
  79. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.d.ts +15 -0
  80. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.js +418 -0
  81. package/node_modules/@openclaw/fs-safe/dist/native-rename-outcome.js +9 -4
  82. package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +17 -13
  83. package/node_modules/@openclaw/fs-safe/dist/native-staged-symlink.js +6 -24
  84. package/node_modules/@openclaw/fs-safe/dist/native.js +5 -1
  85. package/node_modules/@openclaw/fs-safe/dist/path-case.js +10 -9
  86. package/node_modules/@openclaw/fs-safe/dist/path-scope-lexical.js +4 -1
  87. package/node_modules/@openclaw/fs-safe/dist/path-segment-route.d.ts +1 -0
  88. package/node_modules/@openclaw/fs-safe/dist/path-segment-route.js +3 -0
  89. package/node_modules/@openclaw/fs-safe/dist/path.js +4 -1
  90. package/node_modules/@openclaw/fs-safe/dist/permissions-windows.d.ts +0 -1
  91. package/node_modules/@openclaw/fs-safe/dist/pinned-mutation-admission.js +1 -3
  92. package/node_modules/@openclaw/fs-safe/dist/pinned-write-staged.js +2 -0
  93. package/node_modules/@openclaw/fs-safe/dist/pinned-write.js +9 -10
  94. package/node_modules/@openclaw/fs-safe/dist/private-producer-handoff.js +3 -6
  95. package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.js +2 -2
  96. package/node_modules/@openclaw/fs-safe/dist/publish-file.js +4 -3
  97. package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.d.ts +3 -4
  98. package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.js +18 -32
  99. package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.d.ts +5 -17
  100. package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.js +92 -230
  101. package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.d.ts +4 -15
  102. package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.js +22 -63
  103. package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.d.ts +9 -34
  104. package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.js +78 -83
  105. package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.d.ts +18 -20
  106. package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.js +64 -98
  107. package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.d.ts +16 -33
  108. package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.js +61 -200
  109. package/node_modules/@openclaw/fs-safe/dist/replace-file-types.d.ts +1 -6
  110. package/node_modules/@openclaw/fs-safe/dist/replace-file.js +76 -216
  111. package/node_modules/@openclaw/fs-safe/dist/root-boundary.js +14 -24
  112. package/node_modules/@openclaw/fs-safe/dist/root-context.d.ts +1 -4
  113. package/node_modules/@openclaw/fs-safe/dist/root-context.js +4 -19
  114. package/node_modules/@openclaw/fs-safe/dist/root-create-native.d.ts +52 -0
  115. package/node_modules/@openclaw/fs-safe/dist/root-create-native.js +350 -0
  116. package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.d.ts +35 -0
  117. package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.js +1 -0
  118. package/node_modules/@openclaw/fs-safe/dist/root-directory-list.d.ts +2 -27
  119. package/node_modules/@openclaw/fs-safe/dist/root-directory-list.js +31 -28
  120. package/node_modules/@openclaw/fs-safe/dist/root-directory.js +1 -4
  121. package/node_modules/@openclaw/fs-safe/dist/root-errors.js +34 -0
  122. package/node_modules/@openclaw/fs-safe/dist/root-file.js +9 -21
  123. package/node_modules/@openclaw/fs-safe/dist/root-impl.js +105 -37
  124. package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.d.ts +7 -2
  125. package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.js +67 -38
  126. package/node_modules/@openclaw/fs-safe/dist/root-observed-path.d.ts +1 -1
  127. package/node_modules/@openclaw/fs-safe/dist/root-observed-path.js +0 -2
  128. package/node_modules/@openclaw/fs-safe/dist/root-options.d.ts +2 -3
  129. package/node_modules/@openclaw/fs-safe/dist/root-path-existing.js +3 -1
  130. package/node_modules/@openclaw/fs-safe/dist/root-path-stat.js +68 -85
  131. package/node_modules/@openclaw/fs-safe/dist/root-path.js +6 -1
  132. package/node_modules/@openclaw/fs-safe/dist/root-paths-lexical.d.ts +4 -0
  133. package/node_modules/@openclaw/fs-safe/dist/root-paths-lexical.js +1 -1
  134. package/node_modules/@openclaw/fs-safe/dist/root-paths.js +4 -9
  135. package/node_modules/@openclaw/fs-safe/dist/root-remove-native.d.ts +4 -0
  136. package/node_modules/@openclaw/fs-safe/dist/root-remove-native.js +311 -0
  137. package/node_modules/@openclaw/fs-safe/dist/root-remove.d.ts +11 -0
  138. package/node_modules/@openclaw/fs-safe/dist/root-remove.js +3 -1
  139. package/node_modules/@openclaw/fs-safe/dist/root-walk.d.ts +2 -2
  140. package/node_modules/@openclaw/fs-safe/dist/root-walk.js +1 -3
  141. package/node_modules/@openclaw/fs-safe/dist/root-write-admission.d.ts +3 -3
  142. package/node_modules/@openclaw/fs-safe/dist/root-write-admission.js +8 -10
  143. package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.d.ts +0 -1
  144. package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.js +0 -4
  145. package/node_modules/@openclaw/fs-safe/dist/secret-file.js +12 -9
  146. package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.d.ts +0 -2
  147. package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +2 -0
  148. package/node_modules/@openclaw/fs-safe/dist/sibling-temp.js +7 -4
  149. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.js +13 -6
  150. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.d.ts +0 -3
  151. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js +5 -23
  152. package/node_modules/@openclaw/fs-safe/dist/staged-file-settlement.d.ts +2 -1
  153. package/node_modules/@openclaw/fs-safe/dist/staged-file-settlement.js +11 -6
  154. package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.js +1 -8
  155. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.d.ts +1 -1
  156. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.js +2 -9
  157. package/node_modules/@openclaw/fs-safe/dist/text-atomic.d.ts +1 -6
  158. package/node_modules/@openclaw/fs-safe/dist/trash.js +6 -2
  159. package/node_modules/@openclaw/fs-safe/dist/walk.js +100 -46
  160. package/node_modules/@openclaw/fs-safe/dist/watch-hints.d.ts +7 -0
  161. package/node_modules/@openclaw/fs-safe/dist/watch-hints.js +235 -19
  162. package/node_modules/@openclaw/fs-safe/dist/watch-native.d.ts +21 -2
  163. package/node_modules/@openclaw/fs-safe/dist/watch-native.js +21 -3
  164. package/node_modules/@openclaw/fs-safe/dist/watch-rescan.d.ts +6 -0
  165. package/node_modules/@openclaw/fs-safe/dist/watch-rescan.js +111 -0
  166. package/node_modules/@openclaw/fs-safe/dist/watch-scan.d.ts +13 -0
  167. package/node_modules/@openclaw/fs-safe/dist/watch-scan.js +27 -4
  168. package/node_modules/@openclaw/fs-safe/dist/watch-stream.js +2 -0
  169. package/node_modules/@openclaw/fs-safe/dist/watch.js +131 -40
  170. package/node_modules/@openclaw/fs-safe/dist/windows-path-alias.d.ts +8 -0
  171. package/node_modules/@openclaw/fs-safe/dist/windows-path-alias.js +24 -6
  172. package/node_modules/@openclaw/fs-safe/dist/windows-path-syntax.d.ts +13 -0
  173. package/node_modules/@openclaw/fs-safe/dist/windows-path-syntax.js +51 -0
  174. package/node_modules/@openclaw/fs-safe/docs/advanced.md +4 -0
  175. package/node_modules/@openclaw/fs-safe/docs/atomic.md +4 -1
  176. package/node_modules/@openclaw/fs-safe/docs/config.md +6 -14
  177. package/node_modules/@openclaw/fs-safe/docs/contributing.md +4 -14
  178. package/node_modules/@openclaw/fs-safe/docs/durability.md +6 -29
  179. package/node_modules/@openclaw/fs-safe/docs/entry-publication.md +146 -0
  180. package/node_modules/@openclaw/fs-safe/docs/errors.md +16 -0
  181. package/node_modules/@openclaw/fs-safe/docs/file-store.md +28 -5
  182. package/node_modules/@openclaw/fs-safe/docs/index.md +2 -31
  183. package/node_modules/@openclaw/fs-safe/docs/install.md +10 -31
  184. package/node_modules/@openclaw/fs-safe/docs/json.md +1 -1
  185. package/node_modules/@openclaw/fs-safe/docs/local-roots.md +0 -1
  186. package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +12 -12
  187. package/node_modules/@openclaw/fs-safe/docs/native-helper.md +35 -96
  188. package/node_modules/@openclaw/fs-safe/docs/native.md +22 -20
  189. package/node_modules/@openclaw/fs-safe/docs/path.md +1 -1
  190. package/node_modules/@openclaw/fs-safe/docs/permissions.md +1 -2
  191. package/node_modules/@openclaw/fs-safe/docs/public-api.md +1 -2
  192. package/node_modules/@openclaw/fs-safe/docs/reading.md +1 -2
  193. package/node_modules/@openclaw/fs-safe/docs/root.md +26 -184
  194. package/node_modules/@openclaw/fs-safe/docs/secret-file.md +1 -1
  195. package/node_modules/@openclaw/fs-safe/docs/security-model.md +115 -3
  196. package/node_modules/@openclaw/fs-safe/docs/store.md +2 -2
  197. package/node_modules/@openclaw/fs-safe/docs/temp.md +29 -65
  198. package/node_modules/@openclaw/fs-safe/docs/testing.md +90 -58
  199. package/node_modules/@openclaw/fs-safe/docs/types.md +3 -16
  200. package/node_modules/@openclaw/fs-safe/docs/walk.md +33 -5
  201. package/node_modules/@openclaw/fs-safe/docs/watch.md +96 -14
  202. package/node_modules/@openclaw/fs-safe/docs/writing.md +172 -16
  203. package/node_modules/@openclaw/fs-safe/package.json +10 -10
  204. package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
  205. package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +1 -1
  206. package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
  207. package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +1 -1
  208. package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
  209. package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +1 -1
  210. package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
  211. package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +1 -1
  212. package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
  213. package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +1 -1
  214. package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
  215. package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +1 -1
  216. package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
  217. package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +1 -1
  218. package/package.json +5 -5
  219. package/skills/feishu-wiki/SKILL.md +1 -1
  220. package/dist/.setup/accounts-wRqItHug.mjs +0 -206
  221. package/node_modules/@openclaw/fs-safe/dist/watch-alias.d.ts +0 -6
  222. package/node_modules/@openclaw/fs-safe/dist/watch-alias.js +0 -88
  223. package/node_modules/@openclaw/fs-safe/docs/mutation-policy-proof.md +0 -69
  224. package/node_modules/@openclaw/fs-safe/docs/private-file-store.md +0 -68
  225. 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, {} from "node:fs/promises";
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, removeOwnedPath } from "./file-cleanup.js";
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 { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
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
- async function cleanupOwnedPath(params) {
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.handle;
104
+ this.resource = temp.file;
140
105
  this.onIdentity(temp.identity);
141
106
  }
142
- async assertCurrent(fsModule, pathname = this.pathname) {
143
- const opened = await inspectFileIdentity(async () => {
144
- const stat = fsModule === fs ? syncFs.fstatSync(this.resource.fd, { bigint: true })
145
- : await this.resource.stat({ bigint: true });
146
- assertOwnedFile(stat, pathname, false);
147
- return stat;
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
- await inspectFileIdentity(async () => {
151
- const stat = fsModule === fs ? syncFs.lstatSync(pathname, { bigint: true })
152
- : await fsModule.lstat(pathname, { bigint: true });
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
- async assertPublished(fsModule, pathname, expectedHash, onVerified) {
125
+ *assertPublished(pathname, expectedHash, onVerified) {
165
126
  let identityCurrent = false;
166
127
  try {
167
- await this.assertCurrent(fsModule, pathname);
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 = await fsModule.open(pathname, PUBLISHED_READ_FLAGS);
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 identity = await inspectFileIdentity(async () => {
193
- const stat = fsModule === fs ? syncFs.fstatSync(published.fd, { bigint: true })
194
- : await published.stat({ bigint: true });
195
- assertOwnedFile(stat, pathname, false);
196
- return stat;
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 previousHandle = this.takeResource();
209
- await previousHandle?.close();
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
- await published?.close();
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-handle close failure.
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
- export class SyncAtomicTempOwner extends AtomicTempOwner {
254
- adopt(temp) {
255
- this.resource = temp.fd;
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
- try {
296
- publishedFd = fsModule.openSync(pathname, PUBLISHED_READ_FLAGS);
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
- catch (error) {
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
- finally {
327
- if (publishedFd !== undefined) {
328
- try {
329
- fsModule.closeSync(publishedFd);
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 = cleanupOwnedPathSync({
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 fd = this.takeResource();
357
- if (fd !== undefined) {
358
- try {
359
- params.fsModule.closeSync(fd);
360
- }
361
- catch (closeError) {
362
- deferredFailure = closeFailure(closeError, params, deferredFailure);
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 & {