@openclaw/fs-safe 0.12.0 → 0.13.1

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 (395) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +12 -7
  3. package/dist/absolute-path.d.ts.map +1 -1
  4. package/dist/absolute-path.js +32 -11
  5. package/dist/advanced.d.ts +2 -0
  6. package/dist/advanced.d.ts.map +1 -1
  7. package/dist/advanced.js +2 -0
  8. package/dist/archive-input.d.ts.map +1 -1
  9. package/dist/archive-input.js +6 -2
  10. package/dist/archive-merge.d.ts.map +1 -1
  11. package/dist/archive-merge.js +15 -2
  12. package/dist/archive-native.d.ts.map +1 -1
  13. package/dist/archive-native.js +7 -19
  14. package/dist/archive-plan.js +1 -1
  15. package/dist/archive-read.d.ts.map +1 -1
  16. package/dist/archive-read.js +18 -13
  17. package/dist/archive-staging.d.ts.map +1 -1
  18. package/dist/archive-staging.js +43 -10
  19. package/dist/archive-tar-inspect.d.ts.map +1 -1
  20. package/dist/archive-tar-inspect.js +4 -1
  21. package/dist/archive-zip-admission.d.ts +1 -1
  22. package/dist/archive-zip-admission.d.ts.map +1 -1
  23. package/dist/archive-zip-admission.js +2 -2
  24. package/dist/archive-zip-directory.d.ts +3 -0
  25. package/dist/archive-zip-directory.d.ts.map +1 -1
  26. package/dist/archive-zip-directory.js +13 -2
  27. package/dist/archive-zip-loader.d.ts +3 -2
  28. package/dist/archive-zip-loader.d.ts.map +1 -1
  29. package/dist/archive-zip-loader.js +30 -4
  30. package/dist/archive-zip-manifest.d.ts +5 -0
  31. package/dist/archive-zip-manifest.d.ts.map +1 -0
  32. package/dist/archive-zip-manifest.js +22 -0
  33. package/dist/archive-zip-names.d.ts +6 -1
  34. package/dist/archive-zip-names.d.ts.map +1 -1
  35. package/dist/archive-zip-names.js +35 -14
  36. package/dist/archive-zip-preflight.d.ts.map +1 -1
  37. package/dist/archive-zip-preflight.js +3 -2
  38. package/dist/archive.d.ts.map +1 -1
  39. package/dist/archive.js +9 -4
  40. package/dist/copy-file-input.d.ts +1 -1
  41. package/dist/copy-file-input.d.ts.map +1 -1
  42. package/dist/copy-file-input.js +2 -0
  43. package/dist/darwin-acl.d.ts +4 -0
  44. package/dist/darwin-acl.d.ts.map +1 -0
  45. package/dist/darwin-acl.js +24 -0
  46. package/dist/deny-mutations.d.ts.map +1 -1
  47. package/dist/deny-mutations.js +8 -2
  48. package/dist/directory-durability.d.ts.map +1 -1
  49. package/dist/directory-durability.js +67 -23
  50. package/dist/directory-entry-path.d.ts +3 -0
  51. package/dist/directory-entry-path.d.ts.map +1 -0
  52. package/dist/directory-entry-path.js +21 -0
  53. package/dist/directory-guard.d.ts +17 -1
  54. package/dist/directory-guard.d.ts.map +1 -1
  55. package/dist/directory-guard.js +134 -48
  56. package/dist/directory-mode-node.d.ts +12 -0
  57. package/dist/directory-mode-node.d.ts.map +1 -1
  58. package/dist/directory-mode-node.js +102 -4
  59. package/dist/effective-uid.d.ts +2 -0
  60. package/dist/effective-uid.d.ts.map +1 -0
  61. package/dist/effective-uid.js +25 -0
  62. package/dist/file-handle-transfer.d.ts.map +1 -1
  63. package/dist/file-handle-transfer.js +98 -27
  64. package/dist/file-hash.d.ts.map +1 -1
  65. package/dist/file-hash.js +3 -0
  66. package/dist/file-lock-sync.d.ts.map +1 -1
  67. package/dist/file-lock-sync.js +36 -6
  68. package/dist/file-lock.d.ts.map +1 -1
  69. package/dist/file-lock.js +29 -9
  70. package/dist/file-observation.d.ts +1 -1
  71. package/dist/file-observation.d.ts.map +1 -1
  72. package/dist/file-store-boundary.d.ts +6 -2
  73. package/dist/file-store-boundary.d.ts.map +1 -1
  74. package/dist/file-store-boundary.js +20 -65
  75. package/dist/file-store-copy-source.d.ts +5 -0
  76. package/dist/file-store-copy-source.d.ts.map +1 -0
  77. package/dist/file-store-copy-source.js +31 -0
  78. package/dist/file-store-path.d.ts.map +1 -1
  79. package/dist/file-store-path.js +4 -1
  80. package/dist/file-store-sync-directory.d.ts +16 -0
  81. package/dist/file-store-sync-directory.d.ts.map +1 -0
  82. package/dist/file-store-sync-directory.js +349 -0
  83. package/dist/file-store.d.ts.map +1 -1
  84. package/dist/file-store.js +11 -28
  85. package/dist/filename.d.ts.map +1 -1
  86. package/dist/filename.js +65 -20
  87. package/dist/fs.d.ts.map +1 -1
  88. package/dist/fs.js +3 -2
  89. package/dist/guarded-mkdir.d.ts +8 -0
  90. package/dist/guarded-mkdir.d.ts.map +1 -1
  91. package/dist/guarded-mkdir.js +176 -27
  92. package/dist/guest.d.ts.map +1 -1
  93. package/dist/guest.js +4 -1
  94. package/dist/home-dir.d.ts.map +1 -1
  95. package/dist/home-dir.js +73 -10
  96. package/dist/install-path.d.ts.map +1 -1
  97. package/dist/install-path.js +54 -19
  98. package/dist/json-durable-queue-ownership.d.ts +6 -0
  99. package/dist/json-durable-queue-ownership.d.ts.map +1 -1
  100. package/dist/json-durable-queue-ownership.js +89 -42
  101. package/dist/json-durable-queue-paths.d.ts +11 -0
  102. package/dist/json-durable-queue-paths.d.ts.map +1 -0
  103. package/dist/json-durable-queue-paths.js +42 -0
  104. package/dist/json-durable-queue-read.d.ts.map +1 -1
  105. package/dist/json-durable-queue-read.js +2 -0
  106. package/dist/json-durable-queue.d.ts.map +1 -1
  107. package/dist/json-durable-queue.js +50 -58
  108. package/dist/json-store.d.ts.map +1 -1
  109. package/dist/json-store.js +5 -1
  110. package/dist/json.d.ts.map +1 -1
  111. package/dist/json.js +54 -22
  112. package/dist/local-file-access.d.ts.map +1 -1
  113. package/dist/local-file-access.js +4 -0
  114. package/dist/local-file-descriptor.d.ts +17 -0
  115. package/dist/local-file-descriptor.d.ts.map +1 -0
  116. package/dist/local-file-descriptor.js +84 -0
  117. package/dist/local-roots.d.ts.map +1 -1
  118. package/dist/local-roots.js +35 -7
  119. package/dist/move-path-cleanup.d.ts +2 -0
  120. package/dist/move-path-cleanup.d.ts.map +1 -1
  121. package/dist/move-path-cleanup.js +44 -18
  122. package/dist/move-path.d.ts.map +1 -1
  123. package/dist/move-path.js +31 -6
  124. package/dist/native-binding.d.ts +17 -0
  125. package/dist/native-binding.d.ts.map +1 -1
  126. package/dist/native-binding.js +8 -1
  127. package/dist/native-directory-observation.d.ts +17 -0
  128. package/dist/native-directory-observation.d.ts.map +1 -0
  129. package/dist/native-directory-observation.js +37 -0
  130. package/dist/native-operations.d.ts.map +1 -1
  131. package/dist/native-operations.js +6 -4
  132. package/dist/native-parent-admission.d.ts +32 -0
  133. package/dist/native-parent-admission.d.ts.map +1 -0
  134. package/dist/native-parent-admission.js +127 -0
  135. package/dist/native-pinned-write-windows.d.ts +0 -1
  136. package/dist/native-pinned-write-windows.d.ts.map +1 -1
  137. package/dist/native-pinned-write-windows.js +8 -9
  138. package/dist/native-pinned-write.d.ts.map +1 -1
  139. package/dist/native-pinned-write.js +314 -42
  140. package/dist/native-staged-file.d.ts +4 -4
  141. package/dist/native-staged-file.d.ts.map +1 -1
  142. package/dist/native-staged-file.js +20 -10
  143. package/dist/native.d.ts +1 -1
  144. package/dist/native.d.ts.map +1 -1
  145. package/dist/native.js +7 -2
  146. package/dist/output.d.ts.map +1 -1
  147. package/dist/output.js +15 -5
  148. package/dist/overwrite-file-handle.d.ts.map +1 -1
  149. package/dist/overwrite-file-handle.js +5 -1
  150. package/dist/owner-dacl.d.ts.map +1 -1
  151. package/dist/owner-dacl.js +2 -0
  152. package/dist/path-policy.d.ts.map +1 -1
  153. package/dist/path-policy.js +7 -2
  154. package/dist/path-prefix.d.ts +7 -0
  155. package/dist/path-prefix.d.ts.map +1 -0
  156. package/dist/path-prefix.js +82 -0
  157. package/dist/path-scope-lexical.d.ts.map +1 -1
  158. package/dist/path-scope-lexical.js +18 -8
  159. package/dist/path-segment-route.d.ts +7 -0
  160. package/dist/path-segment-route.d.ts.map +1 -0
  161. package/dist/path-segment-route.js +24 -0
  162. package/dist/path-suffix-aliases.d.ts +10 -0
  163. package/dist/path-suffix-aliases.d.ts.map +1 -0
  164. package/dist/path-suffix-aliases.js +386 -0
  165. package/dist/path.d.ts.map +1 -1
  166. package/dist/path.js +16 -5
  167. package/dist/permissions-windows.d.ts.map +1 -1
  168. package/dist/permissions-windows.js +14 -3
  169. package/dist/permissions.d.ts.map +1 -1
  170. package/dist/permissions.js +37 -8
  171. package/dist/pinned-mutation-admission.d.ts +25 -0
  172. package/dist/pinned-mutation-admission.d.ts.map +1 -0
  173. package/dist/pinned-mutation-admission.js +425 -0
  174. package/dist/pinned-mutation-observation.d.ts +34 -0
  175. package/dist/pinned-mutation-observation.d.ts.map +1 -0
  176. package/dist/pinned-mutation-observation.js +142 -0
  177. package/dist/pinned-mutation-shared-route.d.ts +24 -0
  178. package/dist/pinned-mutation-shared-route.d.ts.map +1 -0
  179. package/dist/pinned-mutation-shared-route.js +70 -0
  180. package/dist/pinned-open.d.ts +6 -0
  181. package/dist/pinned-open.d.ts.map +1 -1
  182. package/dist/pinned-open.js +28 -10
  183. package/dist/pinned-write-types.d.ts +75 -0
  184. package/dist/pinned-write-types.d.ts.map +1 -0
  185. package/dist/pinned-write-types.js +1 -0
  186. package/dist/pinned-write.d.ts +7 -33
  187. package/dist/pinned-write.d.ts.map +1 -1
  188. package/dist/pinned-write.js +151 -17
  189. package/dist/private-directory.d.ts.map +1 -1
  190. package/dist/private-directory.js +2 -0
  191. package/dist/private-producer-handoff.d.ts +16 -0
  192. package/dist/private-producer-handoff.d.ts.map +1 -0
  193. package/dist/private-producer-handoff.js +272 -0
  194. package/dist/private-temp-workspace.d.ts +2 -39
  195. package/dist/private-temp-workspace.d.ts.map +1 -1
  196. package/dist/private-temp-workspace.js +183 -77
  197. package/dist/publish-file.d.ts.map +1 -1
  198. package/dist/publish-file.js +38 -32
  199. package/dist/regular-file.d.ts.map +1 -1
  200. package/dist/regular-file.js +56 -45
  201. package/dist/replace-directory.d.ts.map +1 -1
  202. package/dist/replace-directory.js +12 -5
  203. package/dist/replace-file-temp-owner.d.ts +1 -0
  204. package/dist/replace-file-temp-owner.d.ts.map +1 -1
  205. package/dist/replace-file-temp-owner.js +12 -1
  206. package/dist/replace-file.d.ts.map +1 -1
  207. package/dist/replace-file.js +24 -24
  208. package/dist/root-boundary.d.ts +4 -0
  209. package/dist/root-boundary.d.ts.map +1 -1
  210. package/dist/root-boundary.js +6 -1
  211. package/dist/root-context.d.ts +12 -1
  212. package/dist/root-context.d.ts.map +1 -1
  213. package/dist/root-context.js +57 -11
  214. package/dist/root-directory-creation.d.ts +13 -0
  215. package/dist/root-directory-creation.d.ts.map +1 -0
  216. package/dist/root-directory-creation.js +212 -0
  217. package/dist/root-directory-list.d.ts +16 -4
  218. package/dist/root-directory-list.d.ts.map +1 -1
  219. package/dist/root-directory-list.js +180 -39
  220. package/dist/root-directory.d.ts +23 -0
  221. package/dist/root-directory.d.ts.map +1 -0
  222. package/dist/root-directory.js +141 -0
  223. package/dist/root-errors.d.ts.map +1 -1
  224. package/dist/root-errors.js +12 -1
  225. package/dist/root-file-final-admission.d.ts +21 -0
  226. package/dist/root-file-final-admission.d.ts.map +1 -0
  227. package/dist/root-file-final-admission.js +83 -0
  228. package/dist/root-file.d.ts.map +1 -1
  229. package/dist/root-file.js +103 -24
  230. package/dist/root-impl.d.ts +1 -0
  231. package/dist/root-impl.d.ts.map +1 -1
  232. package/dist/root-impl.js +289 -317
  233. package/dist/root-move-noreplace.d.ts +14 -0
  234. package/dist/root-move-noreplace.d.ts.map +1 -0
  235. package/dist/root-move-noreplace.js +202 -0
  236. package/dist/root-observed-path.d.ts +9 -0
  237. package/dist/root-observed-path.d.ts.map +1 -0
  238. package/dist/root-observed-path.js +95 -0
  239. package/dist/root-path-errors.d.ts +12 -0
  240. package/dist/root-path-errors.d.ts.map +1 -0
  241. package/dist/root-path-errors.js +13 -0
  242. package/dist/root-path-existing.d.ts.map +1 -1
  243. package/dist/root-path-existing.js +53 -20
  244. package/dist/root-path-observation.d.ts +63 -0
  245. package/dist/root-path-observation.d.ts.map +1 -0
  246. package/dist/root-path-observation.js +180 -0
  247. package/dist/root-path-stat.d.ts +5 -0
  248. package/dist/root-path-stat.d.ts.map +1 -0
  249. package/dist/root-path-stat.js +101 -0
  250. package/dist/root-path-symlink.d.ts.map +1 -1
  251. package/dist/root-path-symlink.js +23 -4
  252. package/dist/root-path.d.ts +11 -0
  253. package/dist/root-path.d.ts.map +1 -1
  254. package/dist/root-path.js +215 -53
  255. package/dist/root-paths-lexical.d.ts +9 -0
  256. package/dist/root-paths-lexical.d.ts.map +1 -0
  257. package/dist/root-paths-lexical.js +22 -0
  258. package/dist/root-paths.d.ts +3 -25
  259. package/dist/root-paths.d.ts.map +1 -1
  260. package/dist/root-paths.js +77 -154
  261. package/dist/root-read-admission.d.ts +26 -0
  262. package/dist/root-read-admission.d.ts.map +1 -0
  263. package/dist/root-read-admission.js +94 -0
  264. package/dist/root-remove-identity.d.ts +15 -0
  265. package/dist/root-remove-identity.d.ts.map +1 -0
  266. package/dist/root-remove-identity.js +89 -0
  267. package/dist/root-remove-receipt.d.ts +17 -0
  268. package/dist/root-remove-receipt.d.ts.map +1 -0
  269. package/dist/root-remove-receipt.js +37 -0
  270. package/dist/root-remove.d.ts +2 -1
  271. package/dist/root-remove.d.ts.map +1 -1
  272. package/dist/root-remove.js +172 -10
  273. package/dist/root-write-admission.d.ts +68 -0
  274. package/dist/root-write-admission.d.ts.map +1 -0
  275. package/dist/root-write-admission.js +322 -0
  276. package/dist/root-write-compatibility.d.ts +13 -0
  277. package/dist/root-write-compatibility.d.ts.map +1 -0
  278. package/dist/root-write-compatibility.js +74 -0
  279. package/dist/root-write-complete-parent.d.ts +42 -0
  280. package/dist/root-write-complete-parent.d.ts.map +1 -0
  281. package/dist/root-write-complete-parent.js +195 -0
  282. package/dist/root-write-publication.d.ts +24 -0
  283. package/dist/root-write-publication.d.ts.map +1 -0
  284. package/dist/root-write-publication.js +85 -0
  285. package/dist/root-write-verification.d.ts.map +1 -1
  286. package/dist/root-write-verification.js +6 -4
  287. package/dist/secret-file.d.ts.map +1 -1
  288. package/dist/secret-file.js +62 -24
  289. package/dist/secret-read-async.d.ts.map +1 -1
  290. package/dist/secret-read-async.js +18 -13
  291. package/dist/secret-read-policy.d.ts.map +1 -1
  292. package/dist/secret-read-policy.js +5 -1
  293. package/dist/secure-file.d.ts.map +1 -1
  294. package/dist/secure-file.js +92 -7
  295. package/dist/secure-temp-dir.d.ts +6 -3
  296. package/dist/secure-temp-dir.d.ts.map +1 -1
  297. package/dist/secure-temp-dir.js +121 -101
  298. package/dist/secure-temp-repair.d.ts +35 -0
  299. package/dist/secure-temp-repair.d.ts.map +1 -0
  300. package/dist/secure-temp-repair.js +106 -0
  301. package/dist/sibling-staged-file.d.ts +3 -2
  302. package/dist/sibling-staged-file.d.ts.map +1 -1
  303. package/dist/sibling-staged-file.js +179 -55
  304. package/dist/sibling-temp.d.ts.map +1 -1
  305. package/dist/sibling-temp.js +27 -13
  306. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  307. package/dist/sidecar-lock-acquire.js +44 -14
  308. package/dist/sidecar-lock-root.d.ts.map +1 -1
  309. package/dist/sidecar-lock-root.js +4 -2
  310. package/dist/staged-directory.d.ts +14 -5
  311. package/dist/staged-directory.d.ts.map +1 -1
  312. package/dist/staged-directory.js +54 -3
  313. package/dist/standalone-publication-path.d.ts +2 -0
  314. package/dist/standalone-publication-path.d.ts.map +1 -0
  315. package/dist/standalone-publication-path.js +6 -0
  316. package/dist/stat-observation.d.ts +11 -0
  317. package/dist/stat-observation.d.ts.map +1 -0
  318. package/dist/stat-observation.js +64 -0
  319. package/dist/strict-file-identity.d.ts.map +1 -1
  320. package/dist/strict-file-identity.js +39 -2
  321. package/dist/symlink-parents.d.ts.map +1 -1
  322. package/dist/symlink-parents.js +7 -2
  323. package/dist/temp-target.d.ts +2 -0
  324. package/dist/temp-target.d.ts.map +1 -1
  325. package/dist/temp-target.js +130 -3
  326. package/dist/temp-workspace-admission.d.ts +22 -0
  327. package/dist/temp-workspace-admission.d.ts.map +1 -0
  328. package/dist/temp-workspace-admission.js +374 -0
  329. package/dist/temp-workspace-child-admission.d.ts +13 -0
  330. package/dist/temp-workspace-child-admission.d.ts.map +1 -0
  331. package/dist/temp-workspace-child-admission.js +95 -0
  332. package/dist/temp-workspace-descriptor.d.ts +48 -0
  333. package/dist/temp-workspace-descriptor.d.ts.map +1 -0
  334. package/dist/temp-workspace-descriptor.js +363 -0
  335. package/dist/temp-workspace-identity.d.ts +15 -0
  336. package/dist/temp-workspace-identity.d.ts.map +1 -0
  337. package/dist/temp-workspace-identity.js +41 -0
  338. package/dist/temp-workspace-owner.d.ts +7 -6
  339. package/dist/temp-workspace-owner.d.ts.map +1 -1
  340. package/dist/temp-workspace-owner.js +121 -61
  341. package/dist/temp-workspace-permissions.d.ts +4 -0
  342. package/dist/temp-workspace-permissions.d.ts.map +1 -0
  343. package/dist/temp-workspace-permissions.js +32 -0
  344. package/dist/temp-workspace-types.d.ts +40 -0
  345. package/dist/temp-workspace-types.d.ts.map +1 -0
  346. package/dist/temp-workspace-types.js +1 -0
  347. package/dist/temp.d.ts +1 -1
  348. package/dist/temp.d.ts.map +1 -1
  349. package/dist/temp.js +1 -1
  350. package/dist/test-hooks.d.ts +7 -0
  351. package/dist/test-hooks.d.ts.map +1 -1
  352. package/dist/text-atomic.d.ts.map +1 -1
  353. package/dist/text-atomic.js +3 -1
  354. package/dist/trash.d.ts.map +1 -1
  355. package/dist/trash.js +54 -8
  356. package/dist/walk.d.ts.map +1 -1
  357. package/dist/walk.js +9 -6
  358. package/dist/windows-owner.d.ts.map +1 -1
  359. package/dist/windows-owner.js +5 -0
  360. package/dist/windows-path-alias.d.ts +39 -0
  361. package/dist/windows-path-alias.d.ts.map +1 -0
  362. package/dist/windows-path-alias.js +153 -0
  363. package/docs/advanced.md +25 -0
  364. package/docs/archive.md +23 -2
  365. package/docs/atomic.md +27 -3
  366. package/docs/copy.md +3 -0
  367. package/docs/durability.md +14 -0
  368. package/docs/errors.md +14 -6
  369. package/docs/file-store.md +24 -3
  370. package/docs/filename.md +14 -7
  371. package/docs/install-path.md +2 -2
  372. package/docs/install.md +8 -7
  373. package/docs/json-store.md +5 -1
  374. package/docs/json.md +11 -0
  375. package/docs/mutation-policy-proof.md +65 -0
  376. package/docs/native-helper.md +41 -11
  377. package/docs/native.md +32 -8
  378. package/docs/output.md +33 -11
  379. package/docs/path-prefix.md +64 -0
  380. package/docs/path-suffix-aliases.md +159 -0
  381. package/docs/path.md +11 -0
  382. package/docs/private-file-store.md +14 -0
  383. package/docs/public-api.md +9 -0
  384. package/docs/quickstart.md +1 -1
  385. package/docs/reading.md +8 -1
  386. package/docs/root.md +18 -3
  387. package/docs/secret-file.md +3 -0
  388. package/docs/secure-file.md +6 -2
  389. package/docs/security-model.md +75 -8
  390. package/docs/sidecar-lock.md +28 -1
  391. package/docs/store.md +5 -1
  392. package/docs/temp.md +260 -36
  393. package/docs/test-hooks.md +14 -0
  394. package/docs/writing.md +38 -8
  395. package/package.json +10 -10
@@ -2,10 +2,15 @@ import path from "node:path";
2
2
  import { FsSafeError } from "./errors.js";
3
3
  import { assertNoNulPathInput, isPathInside } from "./path.js";
4
4
  import { resolvePathViaExistingAncestor } from "./root-path-existing.js";
5
+ import { assertNoWindowsPathAlias, resolvePathPreservingWindowsRoot, } from "./windows-path-alias.js";
5
6
  export async function resolveMutationComparablePaths(rawPath) {
6
7
  assertNoNulPathInput(rawPath, "path contains a NUL byte");
7
- const resolved = path.resolve(rawPath);
8
- return new Set([resolved, await resolvePathViaExistingAncestor(resolved)]);
8
+ assertNoWindowsPathAlias(rawPath, "filesystem", "mutation path uses a Windows filesystem namespace alias");
9
+ const resolved = resolvePathPreservingWindowsRoot(rawPath);
10
+ assertNoWindowsPathAlias(resolved, "filesystem", "mutation path uses a Windows filesystem namespace alias");
11
+ const canonical = await resolvePathViaExistingAncestor(resolved);
12
+ assertNoWindowsPathAlias(canonical, "filesystem", "mutation path uses a Windows filesystem namespace alias");
13
+ return new Set([resolved, canonical]);
9
14
  }
10
15
  function isSamePath(left, right) {
11
16
  return isPathInside(left, right) && isPathInside(right, left);
@@ -20,6 +25,7 @@ function policyPathEntries(entries) {
20
25
  throw new FsSafeError("invalid-path", "deny mutation paths must be non-empty");
21
26
  }
22
27
  assertNoNulPathInput(entry, "deny mutation path contains a NUL byte");
28
+ assertNoWindowsPathAlias(entry, "filesystem", "deny mutation path uses a Windows filesystem namespace alias");
23
29
  if (!path.isAbsolute(entry)) {
24
30
  throw new FsSafeError("invalid-path", "deny mutation paths must be absolute");
25
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"directory-durability.d.ts","sourceRoot":"","sources":["../src/directory-durability.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAM7C,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG7E,MAAM,MAAM,oBAAoB,GAC5B;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG;IACvD,UAAU,EAAE,oBAAoB,GAAG;QAAE,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wBAAwB,CAAC,EAAE,gBAAgB,CAAC;IAC5C,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD,CAAC;AAgKF,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CAa1B;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAmB/B;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,oBAAoB,CAuCtB;AAED,wBAAsB,uBAAuB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF;AAED,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAMvE;AAuBD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,uBAAuB,CAAC,CA8ElC"}
1
+ {"version":3,"file":"directory-durability.d.ts","sourceRoot":"","sources":["../src/directory-durability.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAM7C,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAI7E,MAAM,MAAM,oBAAoB,GAC5B;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG;IACvD,UAAU,EAAE,oBAAoB,GAAG;QAAE,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wBAAwB,CAAC,EAAE,gBAAgB,CAAC;IAC5C,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD,CAAC;AAwOF,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CAe1B;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAqB/B;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,oBAAoB,CAyCtB;AAED,wBAAsB,uBAAuB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF;AAED,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAMvE;AAiCD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,uBAAuB,CAAC,CA2FlC"}
@@ -4,6 +4,7 @@ import path from "node:path";
4
4
  import { ensureAbsoluteDirectory } from "./absolute-path.js";
5
5
  import { FsSafeError } from "./errors.js";
6
6
  import { sameFileIdentity } from "./file-identity.js";
7
+ import { assertNoWindowsPathAlias, pathForWindowsFilesystem, resolvePathPreservingWindowsRoot } from "./windows-path-alias.js";
7
8
  import { realpathSync } from "./realpath.js";
8
9
  function directoryOpenFlags() {
9
10
  if (process.platform === "win32") {
@@ -42,39 +43,67 @@ function assertDirectory(identity, pathname, label) {
42
43
  throw new FsSafeError("not-file", `${label} must be a real directory: ${pathname}`);
43
44
  }
44
45
  }
46
+ function ownDirectoryReceipt(receipt) {
47
+ const pathname = receipt.path;
48
+ const realPath = receipt.realPath;
49
+ const identity = receipt.identity;
50
+ return { path: pathname, realPath, identity };
51
+ }
52
+ function assertDirectoryReceiptPaths(receipt, label) {
53
+ assertNoWindowsPathAlias(receipt.path, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
54
+ assertNoWindowsPathAlias(receipt.realPath, "filesystem", `${label} real path uses a Windows filesystem namespace alias`);
55
+ }
45
56
  async function createDirectoryReceipt(directoryPath, label) {
46
- const resolvedPath = path.resolve(directoryPath);
47
- const identity = fsSync.lstatSync(resolvedPath);
57
+ assertNoWindowsPathAlias(directoryPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
58
+ const resolvedPath = resolvePathPreservingWindowsRoot(directoryPath);
59
+ assertNoWindowsPathAlias(resolvedPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
60
+ const operationPath = pathForWindowsFilesystem(resolvedPath);
61
+ const identity = fsSync.lstatSync(operationPath);
48
62
  assertDirectory(identity, resolvedPath, label);
63
+ const realPath = realpathSync.native(operationPath);
64
+ assertNoWindowsPathAlias(realPath, "filesystem", `${label} real path uses a Windows filesystem namespace alias`);
49
65
  return {
50
66
  path: resolvedPath,
51
- realPath: realpathSync.native(resolvedPath),
67
+ realPath,
52
68
  identity,
53
69
  };
54
70
  }
55
71
  function createDirectoryReceiptSync(directoryPath, label) {
56
- const resolvedPath = path.resolve(directoryPath);
57
- const identity = fsSync.lstatSync(resolvedPath);
72
+ assertNoWindowsPathAlias(directoryPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
73
+ const resolvedPath = resolvePathPreservingWindowsRoot(directoryPath);
74
+ assertNoWindowsPathAlias(resolvedPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
75
+ const operationPath = pathForWindowsFilesystem(resolvedPath);
76
+ const identity = fsSync.lstatSync(operationPath);
58
77
  assertDirectory(identity, resolvedPath, label);
78
+ const realPath = realpathSync(operationPath);
79
+ assertNoWindowsPathAlias(realPath, "filesystem", `${label} real path uses a Windows filesystem namespace alias`);
59
80
  return {
60
81
  path: resolvedPath,
61
- realPath: realpathSync(resolvedPath),
82
+ realPath,
62
83
  identity,
63
84
  };
64
85
  }
65
86
  async function assertDirectoryReceiptCurrent(receipt, label) {
66
- const currentIdentity = fsSync.lstatSync(receipt.path);
87
+ assertDirectoryReceiptPaths(receipt, label);
88
+ const operationPath = pathForWindowsFilesystem(receipt.path);
89
+ const currentIdentity = fsSync.lstatSync(operationPath);
67
90
  assertDirectory(currentIdentity, receipt.path, label);
91
+ const realPath = realpathSync.native(operationPath);
92
+ assertNoWindowsPathAlias(realPath, "filesystem", `${label} real path uses a Windows filesystem namespace alias`);
68
93
  if (!sameFileIdentity(receipt.identity, currentIdentity) ||
69
- (realpathSync.native(receipt.path)) !== receipt.realPath) {
94
+ realPath !== receipt.realPath) {
70
95
  throw new FsSafeError("path-mismatch", `${label} changed during durable directory operation: ${receipt.path}`);
71
96
  }
72
97
  }
73
98
  function assertDirectoryReceiptCurrentSync(receipt, label) {
74
- const currentIdentity = fsSync.lstatSync(receipt.path);
99
+ assertDirectoryReceiptPaths(receipt, label);
100
+ const operationPath = pathForWindowsFilesystem(receipt.path);
101
+ const currentIdentity = fsSync.lstatSync(operationPath);
75
102
  assertDirectory(currentIdentity, receipt.path, label);
103
+ const realPath = realpathSync(operationPath);
104
+ assertNoWindowsPathAlias(realPath, "filesystem", `${label} real path uses a Windows filesystem namespace alias`);
76
105
  if (!sameFileIdentity(receipt.identity, currentIdentity) ||
77
- realpathSync(receipt.path) !== receipt.realPath) {
106
+ realPath !== receipt.realPath) {
78
107
  throw new FsSafeError("path-mismatch", `${label} changed during durable directory operation: ${receipt.path}`);
79
108
  }
80
109
  }
@@ -88,19 +117,21 @@ async function assertOpenDirectoryCurrent(handle, receipt, label) {
88
117
  }
89
118
  class PinnedDirectoryImpl {
90
119
  receipt;
120
+ #authority;
91
121
  #handle;
92
122
  #label;
93
123
  #closed = false;
94
124
  constructor(handle, receipt, label) {
95
125
  this.#handle = handle;
96
- this.receipt = receipt;
126
+ this.#authority = receipt;
127
+ this.receipt = ownDirectoryReceipt(receipt);
97
128
  this.#label = label;
98
129
  }
99
130
  async assertCurrent() {
100
131
  if (this.#closed) {
101
132
  throw new FsSafeError("helper-failed", `${this.#label} pin is already closed`);
102
133
  }
103
- await assertOpenDirectoryCurrent(this.#handle, this.receipt, this.#label);
134
+ await assertOpenDirectoryCurrent(this.#handle, this.#authority, this.#label);
104
135
  }
105
136
  async sync() {
106
137
  await this.assertCurrent();
@@ -127,9 +158,11 @@ class PinnedDirectoryImpl {
127
158
  }
128
159
  export async function pinDirectory(directory, options = {}) {
129
160
  const label = options.label ?? "directory";
130
- const receipt = typeof directory === "string" ? await createDirectoryReceipt(directory, label) : directory;
161
+ const receipt = typeof directory === "string"
162
+ ? await createDirectoryReceipt(directory, label)
163
+ : ownDirectoryReceipt(directory);
131
164
  await assertDirectoryReceiptCurrent(receipt, label);
132
- const handle = await fs.open(receipt.path, directoryOpenFlags());
165
+ const handle = await fs.open(pathForWindowsFilesystem(receipt.path), directoryOpenFlags());
133
166
  try {
134
167
  await assertOpenDirectoryCurrent(handle, receipt, label);
135
168
  return new PinnedDirectoryImpl(handle, receipt, label);
@@ -141,7 +174,9 @@ export async function pinDirectory(directory, options = {}) {
141
174
  }
142
175
  export async function syncDirectory(directory, options = {}) {
143
176
  const label = options.label ?? "directory";
144
- const receipt = typeof directory === "string" ? await createDirectoryReceipt(directory, label) : directory;
177
+ const receipt = typeof directory === "string"
178
+ ? await createDirectoryReceipt(directory, label)
179
+ : ownDirectoryReceipt(directory);
145
180
  let pinned;
146
181
  try {
147
182
  pinned = await pinDirectory(receipt, { label });
@@ -162,11 +197,13 @@ export async function syncDirectory(directory, options = {}) {
162
197
  }
163
198
  export function syncDirectorySync(directory, options = {}) {
164
199
  const label = options.label ?? "directory";
165
- const receipt = typeof directory === "string" ? createDirectoryReceiptSync(directory, label) : directory;
200
+ const receipt = typeof directory === "string"
201
+ ? createDirectoryReceiptSync(directory, label)
202
+ : ownDirectoryReceipt(directory);
166
203
  assertDirectoryReceiptCurrentSync(receipt, label);
167
204
  let descriptor;
168
205
  try {
169
- descriptor = fsSync.openSync(receipt.path, directoryOpenFlags());
206
+ descriptor = fsSync.openSync(pathForWindowsFilesystem(receipt.path), directoryOpenFlags());
170
207
  }
171
208
  catch (error) {
172
209
  if (!isWindowsDirectoryOpenUnsupported(error)) {
@@ -211,7 +248,9 @@ export function syncDirectoryBestEffortSync(directoryPath) {
211
248
  }
212
249
  }
213
250
  async function findExistingAncestorReceipt(targetPath, label) {
214
- let currentPath = path.resolve(targetPath);
251
+ assertNoWindowsPathAlias(targetPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
252
+ let currentPath = resolvePathPreservingWindowsRoot(targetPath);
253
+ assertNoWindowsPathAlias(currentPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
215
254
  while (true) {
216
255
  try {
217
256
  return await createDirectoryReceipt(currentPath, label);
@@ -229,12 +268,16 @@ async function findExistingAncestorReceipt(targetPath, label) {
229
268
  }
230
269
  }
231
270
  export async function ensureDurableDirectory(options) {
232
- const directoryPath = path.resolve(options.directoryPath);
233
271
  const label = options.label ?? "directory";
272
+ const requestedDirectoryPath = options.directoryPath;
273
+ assertNoWindowsPathAlias(requestedDirectoryPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
274
+ const directoryPath = resolvePathPreservingWindowsRoot(requestedDirectoryPath);
275
+ assertNoWindowsPathAlias(directoryPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
234
276
  const ancestorReceipt = await findExistingAncestorReceipt(directoryPath, label);
235
277
  const targetExists = ancestorReceipt.path === directoryPath;
236
- if (options.expectedExistingIdentity &&
237
- (!targetExists || !sameFileIdentity(options.expectedExistingIdentity, ancestorReceipt.identity))) {
278
+ const expectedExistingIdentity = options.expectedExistingIdentity;
279
+ if (expectedExistingIdentity &&
280
+ (!targetExists || !sameFileIdentity(expectedExistingIdentity, ancestorReceipt.identity))) {
238
281
  throw new FsSafeError("path-mismatch", `${label} changed before durable directory pinning: ${directoryPath}`);
239
282
  }
240
283
  const ancestor = await pinDirectory(ancestorReceipt, { label });
@@ -242,8 +285,9 @@ export async function ensureDurableDirectory(options) {
242
285
  try {
243
286
  await ancestor.assertCurrent();
244
287
  if (!targetExists) {
245
- if (options.create) {
246
- await options.create(directoryPath);
288
+ const create = options.create;
289
+ if (create) {
290
+ await Reflect.apply(create, options, [directoryPath]);
247
291
  }
248
292
  else {
249
293
  const created = await ensureAbsoluteDirectory(directoryPath, {
@@ -0,0 +1,3 @@
1
+ /** Strip only trailing separators: lstat must inspect the entry, not follow a leaf link. */
2
+ export declare function directoryEntryPath(dir: string, platform?: NodeJS.Platform): string;
3
+ //# sourceMappingURL=directory-entry-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directory-entry-path.d.ts","sourceRoot":"","sources":["../src/directory-entry-path.ts"],"names":[],"mappings":"AAEA,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,kBAAmB,GAAG,MAAM,CAenF"}
@@ -0,0 +1,21 @@
1
+ import path from "node:path";
2
+ /** Strip only trailing separators: lstat must inspect the entry, not follow a leaf link. */
3
+ export function directoryEntryPath(dir, platform = process.platform) {
4
+ const windows = platform === "win32";
5
+ if (typeof dir === "string") {
6
+ const last = dir[dir.length - 1];
7
+ if (last !== "/" && (!windows || last !== "\\"))
8
+ return dir;
9
+ }
10
+ let rootLength = (windows ? path.win32 : path.posix).parse(dir).root.length;
11
+ if (windows && /^[\\/]{2}[?.][\\/]UNC[\\/]/i.test(dir)) {
12
+ // Node parses the namespace prefix as the root; retain the complete UNC share.
13
+ const uncRoot = path.win32.parse(`\\\\${dir.slice(8)}`).root;
14
+ if (uncRoot.length > 1)
15
+ rootLength = Math.max(rootLength, uncRoot.length + 6);
16
+ }
17
+ let end = dir.length;
18
+ while (end > rootLength && (dir[end - 1] === "/" || (windows && dir[end - 1] === "\\")))
19
+ end--;
20
+ return end === rootLength || end === dir.length ? dir : dir.slice(0, end);
21
+ }
@@ -1,4 +1,5 @@
1
1
  import type { BigIntStats, Stats } from "node:fs";
2
+ import { type ExactStatIdentity, type StatObservationReceipt } from "./stat-observation.js";
2
3
  export type AsyncDirectoryGuard<T extends Stats | BigIntStats = Stats> = {
3
4
  dir: string;
4
5
  realPath: string;
@@ -21,6 +22,7 @@ export declare function assertDirectoryIdentitySync(observedPath: string, expect
21
22
  }): void;
22
23
  export declare function createAsyncDirectoryGuard(dir: string, options: {
23
24
  bigint: true;
25
+ initial?: BigIntStats;
24
26
  }): Promise<AsyncDirectoryGuard<BigIntStats>>;
25
27
  export declare function createAsyncDirectoryGuard(dir: string, options?: {
26
28
  bigint?: false;
@@ -37,5 +39,19 @@ export declare function createNearestExistingDirectoryGuard(rootReal: string, ta
37
39
  }): Promise<AnyAsyncDirectoryGuard>;
38
40
  export declare function createNearestExistingSyncDirectoryGuard(rootReal: string, targetPath: string): SyncDirectoryGuard;
39
41
  export declare function inspectDirectoryIdentity(dir: string, expected?: Pick<BigIntStats, "dev" | "ino">): Promise<BigIntStats>;
40
- export declare function inspectDirectoryIdentitySync(dir: string, expected?: Pick<BigIntStats, "dev" | "ino">): BigIntStats;
42
+ export declare function observeDirectoryIdentitySync(dir: string, options: {
43
+ bigint: true;
44
+ }): BigIntStats;
45
+ export declare function observeDirectoryIdentitySync(dir: string, options?: {
46
+ bigint?: false;
47
+ }): Stats;
48
+ export declare function inspectDirectoryIdentitySync(dir: string, expected?: Pick<BigIntStats, "dev" | "ino">, initial?: BigIntStats, platform?: NodeJS.Platform): BigIntStats;
49
+ export type DirectoryObservationGuard = StatObservationReceipt & {
50
+ dir: string;
51
+ realPath: string;
52
+ };
53
+ export declare function extendDirectoryObservationGuard(observation: StatObservationReceipt, dir: string, realPath: string): DirectoryObservationGuard;
54
+ export declare function inspectDirectoryObservationSync(dir: string, expected?: ExactStatIdentity): StatObservationReceipt;
55
+ export declare function assertDirectoryObservationSync(dir: string, expected: ExactStatIdentity): Stats | BigIntStats;
56
+ export declare function assertDirectoryObservationGuardSync(guard: DirectoryObservationGuard): void;
41
57
  //# sourceMappingURL=directory-guard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"directory-guard.d.ts","sourceRoot":"","sources":["../src/directory-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAUlD,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,KAAK,GAAG,WAAW,GAAG,KAAK,IAAI;IACvE,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,CAAC,CAAC;CACT,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,mBAAmB,CAAC,KAAK,GAAG,WAAW,CAAC,CAAC;AAE9E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAGnF;AAED,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,KAAK,GAAG,KAAK,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACvE,IAAI,CAKN;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,MAAM,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC;AAC7H,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AACnH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAStH,wBAAsB,yBAAyB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAY5F;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAMxE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,GAAG,sBAAsB,GAAG,IAAI,CAajG;AAED,wBAAgB,mCAAmC,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AACxH,wBAAgB,mCAAmC,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAqBzJ,wBAAgB,uCAAuC,CACrD,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,kBAAkB,CAcpB;AAGD,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAE7H;AAmBD,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,GAC1C,WAAW,CAQb"}
1
+ {"version":3,"file":"directory-guard.d.ts","sourceRoot":"","sources":["../src/directory-guard.ts"],"names":[],"mappings":"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"}
@@ -5,61 +5,102 @@ import { sameFileIdentity } from "./file-identity.js";
5
5
  import { inspectFileIdentitySync } from "./strict-file-identity.js";
6
6
  import { isNotFoundPathError } from "./path.js";
7
7
  import { directoryComponentNotDirectoryError } from "./root-errors.js";
8
+ import { assertNoWindowsPathAlias, pathForWindowsFilesystem, resolvePathPreservingWindowsRoot, } from "./windows-path-alias.js";
8
9
  import { realpathSync } from "./realpath.js";
10
+ import { directoryEntryPath } from "./directory-entry-path.js";
11
+ import { assertStatObservationSync, inspectStatObservationSync, } from "./stat-observation.js";
9
12
  export async function readDirectoryIdentity(dir) {
10
13
  const guard = await createAsyncDirectoryGuard(dir, { bigint: true });
11
14
  return Object.freeze({ dev: guard.stat.dev, ino: guard.stat.ino, realPath: guard.realPath });
12
15
  }
13
16
  export function assertDirectoryIdentitySync(observedPath, expected) {
14
- inspectDirectoryIdentitySync(observedPath, expected);
15
- if (expected.realPath !== undefined && realpathSync.native(observedPath) !== expected.realPath) {
17
+ const operationPath = directoryOperationPath(observedPath);
18
+ const expectedDev = expected.dev;
19
+ const expectedIno = expected.ino;
20
+ const expectedRealPath = expected.realPath;
21
+ if (expectedRealPath !== undefined)
22
+ assertNoWindowsPathAlias(expectedRealPath, "filesystem");
23
+ inspectDirectoryIdentityAtPathSync(operationPath, { dev: expectedDev, ino: expectedIno });
24
+ if (expectedRealPath === undefined)
25
+ return;
26
+ const realPath = realpathSync.native(operationPath);
27
+ assertNoWindowsPathAlias(realPath, "filesystem");
28
+ if (realPath !== expectedRealPath) {
16
29
  throw new FsSafeError("path-mismatch", "directory changed during operation");
17
30
  }
18
31
  }
19
32
  export async function createAsyncDirectoryGuard(dir, options) {
20
- const stat = options?.bigint ? inspectDirectoryIdentitySync(dir) : fsSync.lstatSync(dir);
33
+ const operationPath = directoryOperationPath(dir);
34
+ const stat = options?.bigint
35
+ ? inspectDirectoryIdentityAtPathSync(operationPath, undefined, options.initial)
36
+ : fsSync.lstatSync(operationPath);
21
37
  if (stat.isSymbolicLink() || !stat.isDirectory()) {
22
38
  throw directoryComponentNotDirectoryError();
23
39
  }
24
- return { dir, realPath: realpathSync.native(dir), stat };
40
+ const realPath = realpathSync.native(operationPath);
41
+ assertNoWindowsPathAlias(realPath, "filesystem");
42
+ return { dir, realPath, stat };
25
43
  }
26
44
  export async function assertAsyncDirectoryGuard(guard) {
27
- if (typeof guard.stat.dev === "bigint" && typeof guard.stat.ino === "bigint") {
28
- assertDirectoryIdentitySync(guard.dir, { dev: guard.stat.dev, ino: guard.stat.ino, realPath: guard.realPath });
29
- return;
30
- }
31
- const stat = fsSync.lstatSync(guard.dir);
45
+ const dir = guard.dir;
46
+ const operationPath = directoryOperationPath(dir);
47
+ const expectedRealPath = guard.realPath;
48
+ assertNoWindowsPathAlias(expectedRealPath, "filesystem");
49
+ const expectedStat = guard.stat;
50
+ const expectedIdentity = { dev: expectedStat.dev, ino: expectedStat.ino };
51
+ const stat = typeof expectedIdentity.dev === "bigint" && typeof expectedIdentity.ino === "bigint"
52
+ ? inspectDirectoryIdentityAtPathSync(operationPath, {
53
+ dev: expectedIdentity.dev,
54
+ ino: expectedIdentity.ino,
55
+ })
56
+ : fsSync.lstatSync(operationPath);
32
57
  if (stat.isSymbolicLink() || !stat.isDirectory()) {
33
58
  throw directoryComponentNotDirectoryError();
34
59
  }
35
- if (!sameFileIdentity(stat, guard.stat) || realpathSync.native(guard.dir) !== guard.realPath) {
60
+ if (!sameFileIdentity(stat, expectedIdentity)) {
61
+ throw new FsSafeError("path-mismatch", "directory changed during operation");
62
+ }
63
+ const realPath = realpathSync.native(operationPath);
64
+ assertNoWindowsPathAlias(realPath, "filesystem");
65
+ if (realPath !== expectedRealPath) {
36
66
  throw new FsSafeError("path-mismatch", "directory changed during operation");
37
67
  }
38
68
  }
39
69
  export function createSyncDirectoryGuard(dir) {
40
- const stat = fsSync.lstatSync(dir);
70
+ const operationPath = directoryOperationPath(dir);
71
+ const stat = fsSync.lstatSync(operationPath);
41
72
  if (stat.isSymbolicLink() || !stat.isDirectory()) {
42
73
  throw directoryComponentNotDirectoryError();
43
74
  }
44
- return { dir, realPath: realpathSync(dir), stat };
75
+ const realPath = realpathSync(operationPath);
76
+ assertNoWindowsPathAlias(realPath, "filesystem");
77
+ return { dir, realPath, stat };
45
78
  }
46
79
  export function assertSyncDirectoryGuard(guard) {
47
- if (typeof guard.stat.dev === "bigint" && typeof guard.stat.ino === "bigint") {
48
- assertDirectoryIdentitySync(guard.dir, { dev: guard.stat.dev, ino: guard.stat.ino, realPath: guard.realPath });
49
- return;
50
- }
51
- const stat = fsSync.lstatSync(guard.dir);
80
+ const dir = guard.dir;
81
+ const operationPath = directoryOperationPath(dir);
82
+ const expectedRealPath = guard.realPath;
83
+ assertNoWindowsPathAlias(expectedRealPath, "filesystem");
84
+ const expectedStat = guard.stat;
85
+ const expectedIdentity = { dev: expectedStat.dev, ino: expectedStat.ino };
86
+ const stat = typeof expectedIdentity.dev === "bigint" && typeof expectedIdentity.ino === "bigint"
87
+ ? inspectDirectoryIdentityAtPathSync(operationPath, { dev: expectedIdentity.dev, ino: expectedIdentity.ino })
88
+ : fsSync.lstatSync(operationPath);
52
89
  if (stat.isSymbolicLink() || !stat.isDirectory()) {
53
90
  throw directoryComponentNotDirectoryError();
54
91
  }
55
- const realPath = realpathSync(guard.dir);
56
- if (!sameFileIdentity(stat, guard.stat) || realPath !== guard.realPath) {
92
+ const realPath = typeof expectedIdentity.ino === "bigint"
93
+ ? realpathSync.native(operationPath) : realpathSync(operationPath);
94
+ assertNoWindowsPathAlias(realPath, "filesystem");
95
+ if (!sameFileIdentity(stat, expectedIdentity) || realPath !== expectedRealPath) {
57
96
  throw new FsSafeError("path-mismatch", "directory changed during operation");
58
97
  }
59
98
  }
60
99
  export async function createNearestExistingDirectoryGuard(rootReal, targetPath, options = { bigint: false }) {
61
- let current = path.resolve(targetPath);
62
- const root = path.resolve(rootReal);
100
+ assertNoWindowsPathAlias(rootReal, "filesystem");
101
+ assertNoWindowsPathAlias(targetPath, "filesystem");
102
+ let current = resolvePathPreservingWindowsRoot(targetPath);
103
+ const root = resolvePathPreservingWindowsRoot(rootReal);
63
104
  while (current !== root) {
64
105
  try {
65
106
  return await createAsyncDirectoryGuard(current, options);
@@ -74,8 +115,10 @@ export async function createNearestExistingDirectoryGuard(rootReal, targetPath,
74
115
  return await createAsyncDirectoryGuard(root, options);
75
116
  }
76
117
  export function createNearestExistingSyncDirectoryGuard(rootReal, targetPath) {
77
- let current = path.resolve(targetPath);
78
- const root = path.resolve(rootReal);
118
+ assertNoWindowsPathAlias(rootReal, "filesystem");
119
+ assertNoWindowsPathAlias(targetPath, "filesystem");
120
+ let current = resolvePathPreservingWindowsRoot(targetPath);
121
+ const root = resolvePathPreservingWindowsRoot(rootReal);
79
122
  while (current !== root) {
80
123
  try {
81
124
  return createSyncDirectoryGuard(current);
@@ -91,34 +134,77 @@ export function createNearestExistingSyncDirectoryGuard(rootReal, targetPath) {
91
134
  }
92
135
  // Recovery receipts must retain every identity bit, including on Windows.
93
136
  export async function inspectDirectoryIdentity(dir, expected) {
94
- return inspectDirectoryIdentitySync(dir, expected);
95
- }
96
- function directoryEntryPath(dir) {
97
- const windows = process.platform === "win32";
98
- if (typeof dir === "string") {
99
- const last = dir[dir.length - 1];
100
- if (last !== "/" && (!windows || last !== "\\"))
101
- return dir;
102
- }
103
- let rootLength = (windows ? path.win32 : path.posix).parse(dir).root.length;
104
- if (windows && /^[\\/]{2}[?.][\\/]UNC[\\/]/i.test(dir)) {
105
- // Node parses the namespace prefix as the root; retain the complete UNC share instead.
106
- const uncRoot = path.win32.parse(`\\\\${dir.slice(8)}`).root;
107
- if (uncRoot.length > 1)
108
- rootLength = Math.max(rootLength, uncRoot.length + 6);
109
- }
110
- let end = dir.length;
111
- while (end > rootLength && (dir[end - 1] === "/" || (windows && dir[end - 1] === "\\")))
112
- end--;
113
- return end === rootLength || end === dir.length ? dir : dir.slice(0, end);
114
- }
115
- export function inspectDirectoryIdentitySync(dir, expected) {
116
- // A trailing separator makes lstat follow a final directory symlink.
117
- const entryPath = directoryEntryPath(dir);
137
+ const operationPath = directoryOperationPath(dir);
138
+ const expectedIdentity = expected === undefined
139
+ ? undefined
140
+ : { dev: expected.dev, ino: expected.ino };
141
+ return inspectDirectoryIdentityAtPathSync(operationPath, expectedIdentity);
142
+ }
143
+ function directoryOperationPath(dir) {
144
+ assertNoWindowsPathAlias(dir, "filesystem");
145
+ return pathForWindowsFilesystem(directoryEntryPath(dir));
146
+ }
147
+ export function observeDirectoryIdentitySync(dir, options) {
148
+ const entryPath = directoryOperationPath(dir);
149
+ const stat = options?.bigint
150
+ ? fsSync.lstatSync(entryPath, { bigint: true })
151
+ : fsSync.lstatSync(entryPath);
152
+ if (stat.isSymbolicLink() || !stat.isDirectory())
153
+ throw directoryComponentNotDirectoryError();
154
+ return stat;
155
+ }
156
+ export function inspectDirectoryIdentitySync(dir, expected, initial, platform = process.platform) {
157
+ const operationPath = directoryOperationPath(dir);
158
+ const expectedIdentity = expected === undefined
159
+ ? undefined
160
+ : { dev: expected.dev, ino: expected.ino };
161
+ return inspectDirectoryIdentityAtPathSync(operationPath, expectedIdentity, initial, platform);
162
+ }
163
+ function inspectDirectoryIdentityAtPathSync(operationPath, expected, initial, platform = process.platform) {
118
164
  return inspectFileIdentitySync(() => {
119
- const stat = fsSync.lstatSync(entryPath, { bigint: true });
165
+ // Traversal can supply the first exact observation. A bounded retry still
166
+ // uses the admitted operation path and retains every known identity bit.
167
+ const stat = initial ?? fsSync.lstatSync(operationPath, { bigint: true });
168
+ initial = undefined;
169
+ if (stat.isSymbolicLink() || !stat.isDirectory())
170
+ throw directoryComponentNotDirectoryError();
171
+ return stat;
172
+ }, expected, platform);
173
+ }
174
+ export function extendDirectoryObservationGuard(observation, dir, realPath) {
175
+ const guard = observation;
176
+ guard.dir = dir;
177
+ guard.realPath = realPath;
178
+ return guard;
179
+ }
180
+ // Only stat/list receipts use this metadata fast path. Recovery and publication
181
+ // callers retain the BigIntStats contract of inspectDirectoryIdentitySync.
182
+ export function inspectDirectoryObservationSync(dir, expected) {
183
+ const entryPath = directoryOperationPath(dir);
184
+ return inspectStatObservationSync(bigint => {
185
+ const stat = bigint ? fsSync.lstatSync(entryPath, { bigint: true }) : fsSync.lstatSync(entryPath);
120
186
  if (stat.isSymbolicLink() || !stat.isDirectory())
121
187
  throw directoryComponentNotDirectoryError();
122
188
  return stat;
123
189
  }, expected);
124
190
  }
191
+ export function assertDirectoryObservationSync(dir, expected) {
192
+ const entryPath = directoryOperationPath(dir);
193
+ return assertStatObservationSync(bigint => {
194
+ const stat = bigint ? fsSync.lstatSync(entryPath, { bigint: true }) : fsSync.lstatSync(entryPath);
195
+ if (stat.isSymbolicLink() || !stat.isDirectory())
196
+ throw directoryComponentNotDirectoryError();
197
+ return stat;
198
+ }, expected);
199
+ }
200
+ export function assertDirectoryObservationGuardSync(guard) {
201
+ const dir = guard.dir;
202
+ const expectedRealPath = guard.realPath;
203
+ assertNoWindowsPathAlias(expectedRealPath, "filesystem");
204
+ assertDirectoryObservationSync(dir, guard.identity);
205
+ const realPath = realpathSync.native(directoryOperationPath(dir));
206
+ assertNoWindowsPathAlias(realPath, "filesystem");
207
+ if (realPath !== expectedRealPath) {
208
+ throw new FsSafeError("path-mismatch", "directory changed during operation");
209
+ }
210
+ }
@@ -1,8 +1,20 @@
1
1
  import { type BigIntStats } from "node:fs";
2
2
  import { type DirectoryModeOwner } from "./directory-mode-owner.js";
3
+ export declare function nodeDirectorySearchOnlyFlags(): {
4
+ flags: number;
5
+ proc: boolean;
6
+ } | undefined;
3
7
  /** Real Node only: injected filesystem adapters must retain descriptor-chmod semantics. */
4
8
  export declare function pinNodeDirectoryForMode(dirPath: string, options?: {
5
9
  expectedIdentity?: BigIntStats;
6
10
  ownerUid?: number;
7
11
  }): Promise<DirectoryModeOwner>;
12
+ /** Synchronous counterpart with the same no-follow, identity, and owner checks. */
13
+ export declare function pinNodeDirectoryForModeSync(dirPath: string, options?: {
14
+ expectedIdentity?: BigIntStats;
15
+ ownerUid?: number;
16
+ }): {
17
+ apply(mode: number, check?: () => void): void;
18
+ close(): void;
19
+ };
8
20
  //# sourceMappingURL=directory-mode-node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"directory-mode-node.d.ts","sourceRoot":"","sources":["../src/directory-mode-node.ts"],"names":[],"mappings":"AAAA,OAAe,EAAa,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAK9D,OAAO,EAA0C,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAW5G,2FAA2F;AAC3F,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClE,OAAO,CAAC,kBAAkB,CAAC,CAsE7B"}
1
+ {"version":3,"file":"directory-mode-node.d.ts","sourceRoot":"","sources":["../src/directory-mode-node.ts"],"names":[],"mappings":"AAAA,OAAe,EAAa,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAK9D,OAAO,EAA0C,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE5G,wBAAgB,4BAA4B,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAO3F;AAED,2FAA2F;AAC3F,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClE,OAAO,CAAC,kBAAkB,CAAC,CAsE7B;AAED,mFAAmF;AACnF,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClE;IAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAAC,KAAK,IAAI,IAAI,CAAA;CAAE,CAsFlE"}