@openclaw/fs-safe 0.11.0 → 0.13.0

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 (416) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +15 -8
  3. package/dist/absolute-path.d.ts.map +1 -1
  4. package/dist/absolute-path.js +32 -11
  5. package/dist/advanced.d.ts +3 -1
  6. package/dist/advanced.d.ts.map +1 -1
  7. package/dist/advanced.js +3 -1
  8. package/dist/archive-entry.d.ts.map +1 -1
  9. package/dist/archive-entry.js +4 -3
  10. package/dist/archive-gzip-tail.d.ts.map +1 -1
  11. package/dist/archive-gzip-tail.js +13 -9
  12. package/dist/archive-input.d.ts.map +1 -1
  13. package/dist/archive-input.js +6 -2
  14. package/dist/archive-merge.d.ts.map +1 -1
  15. package/dist/archive-merge.js +15 -2
  16. package/dist/archive-native.d.ts.map +1 -1
  17. package/dist/archive-native.js +7 -19
  18. package/dist/archive-plan.js +1 -1
  19. package/dist/archive-read.d.ts.map +1 -1
  20. package/dist/archive-read.js +55 -46
  21. package/dist/archive-staging.d.ts.map +1 -1
  22. package/dist/archive-staging.js +43 -10
  23. package/dist/archive-tar-inspect.d.ts.map +1 -1
  24. package/dist/archive-tar-inspect.js +4 -1
  25. package/dist/archive-zip-admission.d.ts +1 -1
  26. package/dist/archive-zip-admission.d.ts.map +1 -1
  27. package/dist/archive-zip-admission.js +2 -2
  28. package/dist/archive-zip-directory.d.ts +3 -0
  29. package/dist/archive-zip-directory.d.ts.map +1 -1
  30. package/dist/archive-zip-directory.js +13 -2
  31. package/dist/archive-zip-loader.d.ts +3 -2
  32. package/dist/archive-zip-loader.d.ts.map +1 -1
  33. package/dist/archive-zip-loader.js +30 -4
  34. package/dist/archive-zip-manifest.d.ts +5 -0
  35. package/dist/archive-zip-manifest.d.ts.map +1 -0
  36. package/dist/archive-zip-manifest.js +22 -0
  37. package/dist/archive-zip-names.d.ts +6 -1
  38. package/dist/archive-zip-names.d.ts.map +1 -1
  39. package/dist/archive-zip-names.js +50 -17
  40. package/dist/archive-zip-preflight.d.ts.map +1 -1
  41. package/dist/archive-zip-preflight.js +3 -2
  42. package/dist/archive.d.ts.map +1 -1
  43. package/dist/archive.js +9 -4
  44. package/dist/bounded-read.js +2 -2
  45. package/dist/darwin-acl.d.ts +4 -0
  46. package/dist/darwin-acl.d.ts.map +1 -0
  47. package/dist/darwin-acl.js +24 -0
  48. package/dist/deny-mutations.d.ts.map +1 -1
  49. package/dist/deny-mutations.js +8 -2
  50. package/dist/device-path.d.ts.map +1 -1
  51. package/dist/device-path.js +5 -3
  52. package/dist/directory-durability.d.ts.map +1 -1
  53. package/dist/directory-durability.js +67 -23
  54. package/dist/directory-entry-path.d.ts +3 -0
  55. package/dist/directory-entry-path.d.ts.map +1 -0
  56. package/dist/directory-entry-path.js +21 -0
  57. package/dist/directory-guard.d.ts +17 -1
  58. package/dist/directory-guard.d.ts.map +1 -1
  59. package/dist/directory-guard.js +134 -48
  60. package/dist/directory-mode-node.d.ts +12 -0
  61. package/dist/directory-mode-node.d.ts.map +1 -1
  62. package/dist/directory-mode-node.js +102 -4
  63. package/dist/effective-uid.d.ts +2 -0
  64. package/dist/effective-uid.d.ts.map +1 -0
  65. package/dist/effective-uid.js +25 -0
  66. package/dist/file-handle-transfer.d.ts.map +1 -1
  67. package/dist/file-handle-transfer.js +98 -27
  68. package/dist/file-hash.d.ts.map +1 -1
  69. package/dist/file-hash.js +12 -2
  70. package/dist/file-lock-sync.d.ts.map +1 -1
  71. package/dist/file-lock-sync.js +36 -6
  72. package/dist/file-lock.d.ts.map +1 -1
  73. package/dist/file-lock.js +29 -9
  74. package/dist/file-observation.d.ts +1 -1
  75. package/dist/file-observation.d.ts.map +1 -1
  76. package/dist/file-store-boundary.d.ts +6 -2
  77. package/dist/file-store-boundary.d.ts.map +1 -1
  78. package/dist/file-store-boundary.js +20 -65
  79. package/dist/file-store-copy-source.d.ts +5 -0
  80. package/dist/file-store-copy-source.d.ts.map +1 -0
  81. package/dist/file-store-copy-source.js +31 -0
  82. package/dist/file-store-path.d.ts.map +1 -1
  83. package/dist/file-store-path.js +4 -1
  84. package/dist/file-store-prune.d.ts.map +1 -1
  85. package/dist/file-store-prune.js +9 -1
  86. package/dist/file-store-sync-directory.d.ts +16 -0
  87. package/dist/file-store-sync-directory.d.ts.map +1 -0
  88. package/dist/file-store-sync-directory.js +349 -0
  89. package/dist/file-store.d.ts.map +1 -1
  90. package/dist/file-store.js +11 -28
  91. package/dist/filename.d.ts +1 -0
  92. package/dist/filename.d.ts.map +1 -1
  93. package/dist/filename.js +85 -23
  94. package/dist/fs.d.ts.map +1 -1
  95. package/dist/fs.js +3 -2
  96. package/dist/guarded-mkdir.d.ts +10 -0
  97. package/dist/guarded-mkdir.d.ts.map +1 -1
  98. package/dist/guarded-mkdir.js +217 -33
  99. package/dist/guest.d.ts.map +1 -1
  100. package/dist/guest.js +16 -5
  101. package/dist/home-dir.d.ts.map +1 -1
  102. package/dist/home-dir.js +73 -10
  103. package/dist/install-path.d.ts +6 -0
  104. package/dist/install-path.d.ts.map +1 -1
  105. package/dist/install-path.js +67 -19
  106. package/dist/json-durable-queue-ownership.d.ts +8 -0
  107. package/dist/json-durable-queue-ownership.d.ts.map +1 -1
  108. package/dist/json-durable-queue-ownership.js +134 -43
  109. package/dist/json-durable-queue-paths.d.ts +11 -0
  110. package/dist/json-durable-queue-paths.d.ts.map +1 -0
  111. package/dist/json-durable-queue-paths.js +42 -0
  112. package/dist/json-durable-queue-read.d.ts +6 -0
  113. package/dist/json-durable-queue-read.d.ts.map +1 -0
  114. package/dist/json-durable-queue-read.js +61 -0
  115. package/dist/json-durable-queue.d.ts +1 -1
  116. package/dist/json-durable-queue.d.ts.map +1 -1
  117. package/dist/json-durable-queue.js +83 -134
  118. package/dist/json-store.d.ts.map +1 -1
  119. package/dist/json-store.js +5 -1
  120. package/dist/json.d.ts.map +1 -1
  121. package/dist/json.js +54 -22
  122. package/dist/local-file-access.d.ts.map +1 -1
  123. package/dist/local-file-access.js +4 -0
  124. package/dist/local-file-descriptor.d.ts +17 -0
  125. package/dist/local-file-descriptor.d.ts.map +1 -0
  126. package/dist/local-file-descriptor.js +84 -0
  127. package/dist/local-roots.d.ts.map +1 -1
  128. package/dist/local-roots.js +35 -7
  129. package/dist/move-path-cleanup.d.ts +2 -0
  130. package/dist/move-path-cleanup.d.ts.map +1 -1
  131. package/dist/move-path-cleanup.js +44 -18
  132. package/dist/move-path.d.ts.map +1 -1
  133. package/dist/move-path.js +31 -6
  134. package/dist/native-binding.d.ts +21 -0
  135. package/dist/native-binding.d.ts.map +1 -1
  136. package/dist/native-directory-observation.d.ts +17 -0
  137. package/dist/native-directory-observation.d.ts.map +1 -0
  138. package/dist/native-directory-observation.js +37 -0
  139. package/dist/native-parent-admission.d.ts +31 -0
  140. package/dist/native-parent-admission.d.ts.map +1 -0
  141. package/dist/native-parent-admission.js +124 -0
  142. package/dist/native-pinned-write-windows.d.ts +0 -1
  143. package/dist/native-pinned-write-windows.d.ts.map +1 -1
  144. package/dist/native-pinned-write-windows.js +0 -3
  145. package/dist/native-pinned-write.d.ts.map +1 -1
  146. package/dist/native-pinned-write.js +309 -40
  147. package/dist/output.d.ts.map +1 -1
  148. package/dist/output.js +15 -5
  149. package/dist/overwrite-file-handle.d.ts.map +1 -1
  150. package/dist/overwrite-file-handle.js +5 -1
  151. package/dist/owner-dacl.d.ts.map +1 -1
  152. package/dist/owner-dacl.js +2 -0
  153. package/dist/path-policy.d.ts.map +1 -1
  154. package/dist/path-policy.js +7 -2
  155. package/dist/path-prefix.d.ts +7 -0
  156. package/dist/path-prefix.d.ts.map +1 -0
  157. package/dist/path-prefix.js +82 -0
  158. package/dist/path-scope-lexical.d.ts +14 -0
  159. package/dist/path-scope-lexical.d.ts.map +1 -0
  160. package/dist/path-scope-lexical.js +37 -0
  161. package/dist/path-segment-route.d.ts +7 -0
  162. package/dist/path-segment-route.d.ts.map +1 -0
  163. package/dist/path-segment-route.js +24 -0
  164. package/dist/path-suffix-aliases.d.ts +10 -0
  165. package/dist/path-suffix-aliases.d.ts.map +1 -0
  166. package/dist/path-suffix-aliases.js +386 -0
  167. package/dist/path.d.ts.map +1 -1
  168. package/dist/path.js +35 -6
  169. package/dist/permissions-windows.d.ts.map +1 -1
  170. package/dist/permissions-windows.js +14 -3
  171. package/dist/permissions.d.ts.map +1 -1
  172. package/dist/permissions.js +37 -8
  173. package/dist/pinned-mutation-admission.d.ts +25 -0
  174. package/dist/pinned-mutation-admission.d.ts.map +1 -0
  175. package/dist/pinned-mutation-admission.js +425 -0
  176. package/dist/pinned-mutation-observation.d.ts +34 -0
  177. package/dist/pinned-mutation-observation.d.ts.map +1 -0
  178. package/dist/pinned-mutation-observation.js +142 -0
  179. package/dist/pinned-mutation-shared-route.d.ts +24 -0
  180. package/dist/pinned-mutation-shared-route.d.ts.map +1 -0
  181. package/dist/pinned-mutation-shared-route.js +70 -0
  182. package/dist/pinned-open.d.ts +6 -0
  183. package/dist/pinned-open.d.ts.map +1 -1
  184. package/dist/pinned-open.js +28 -10
  185. package/dist/pinned-write-types.d.ts +75 -0
  186. package/dist/pinned-write-types.d.ts.map +1 -0
  187. package/dist/pinned-write-types.js +1 -0
  188. package/dist/pinned-write.d.ts +7 -33
  189. package/dist/pinned-write.d.ts.map +1 -1
  190. package/dist/pinned-write.js +152 -17
  191. package/dist/private-directory.d.ts.map +1 -1
  192. package/dist/private-directory.js +2 -0
  193. package/dist/private-producer-handoff.d.ts +16 -0
  194. package/dist/private-producer-handoff.d.ts.map +1 -0
  195. package/dist/private-producer-handoff.js +272 -0
  196. package/dist/private-temp-workspace.d.ts +2 -39
  197. package/dist/private-temp-workspace.d.ts.map +1 -1
  198. package/dist/private-temp-workspace.js +183 -77
  199. package/dist/publish-file.d.ts.map +1 -1
  200. package/dist/publish-file.js +33 -29
  201. package/dist/regular-file.d.ts.map +1 -1
  202. package/dist/regular-file.js +56 -45
  203. package/dist/replace-directory.d.ts.map +1 -1
  204. package/dist/replace-directory.js +12 -5
  205. package/dist/replace-file-temp-owner.d.ts +1 -0
  206. package/dist/replace-file-temp-owner.d.ts.map +1 -1
  207. package/dist/replace-file-temp-owner.js +12 -1
  208. package/dist/replace-file.d.ts.map +1 -1
  209. package/dist/replace-file.js +24 -24
  210. package/dist/root-boundary.d.ts +29 -0
  211. package/dist/root-boundary.d.ts.map +1 -0
  212. package/dist/root-boundary.js +182 -0
  213. package/dist/root-context.d.ts +12 -1
  214. package/dist/root-context.d.ts.map +1 -1
  215. package/dist/root-context.js +89 -16
  216. package/dist/root-directory-creation.d.ts +13 -0
  217. package/dist/root-directory-creation.d.ts.map +1 -0
  218. package/dist/root-directory-creation.js +212 -0
  219. package/dist/root-directory-list.d.ts +16 -4
  220. package/dist/root-directory-list.d.ts.map +1 -1
  221. package/dist/root-directory-list.js +182 -33
  222. package/dist/root-directory.d.ts +23 -0
  223. package/dist/root-directory.d.ts.map +1 -0
  224. package/dist/root-directory.js +141 -0
  225. package/dist/root-errors.d.ts.map +1 -1
  226. package/dist/root-errors.js +12 -1
  227. package/dist/root-file-final-admission.d.ts +21 -0
  228. package/dist/root-file-final-admission.d.ts.map +1 -0
  229. package/dist/root-file-final-admission.js +83 -0
  230. package/dist/root-file.d.ts.map +1 -1
  231. package/dist/root-file.js +103 -24
  232. package/dist/root-impl.d.ts +1 -0
  233. package/dist/root-impl.d.ts.map +1 -1
  234. package/dist/root-impl.js +316 -325
  235. package/dist/root-move-noreplace.d.ts +14 -0
  236. package/dist/root-move-noreplace.d.ts.map +1 -0
  237. package/dist/root-move-noreplace.js +202 -0
  238. package/dist/root-move-preflight.d.ts +8 -0
  239. package/dist/root-move-preflight.d.ts.map +1 -0
  240. package/dist/root-move-preflight.js +16 -0
  241. package/dist/root-observed-path.d.ts +9 -0
  242. package/dist/root-observed-path.d.ts.map +1 -0
  243. package/dist/root-observed-path.js +95 -0
  244. package/dist/root-path-errors.d.ts +12 -0
  245. package/dist/root-path-errors.d.ts.map +1 -0
  246. package/dist/root-path-errors.js +13 -0
  247. package/dist/root-path-existing.d.ts +2 -0
  248. package/dist/root-path-existing.d.ts.map +1 -1
  249. package/dist/root-path-existing.js +63 -22
  250. package/dist/root-path-observation.d.ts +63 -0
  251. package/dist/root-path-observation.d.ts.map +1 -0
  252. package/dist/root-path-observation.js +180 -0
  253. package/dist/root-path-stat.d.ts +5 -0
  254. package/dist/root-path-stat.d.ts.map +1 -0
  255. package/dist/root-path-stat.js +101 -0
  256. package/dist/root-path-symlink.d.ts.map +1 -1
  257. package/dist/root-path-symlink.js +23 -4
  258. package/dist/root-path.d.ts +13 -0
  259. package/dist/root-path.d.ts.map +1 -1
  260. package/dist/root-path.js +263 -73
  261. package/dist/root-paths-lexical.d.ts +9 -0
  262. package/dist/root-paths-lexical.d.ts.map +1 -0
  263. package/dist/root-paths-lexical.js +22 -0
  264. package/dist/root-paths.d.ts +3 -29
  265. package/dist/root-paths.d.ts.map +1 -1
  266. package/dist/root-paths.js +89 -178
  267. package/dist/root-read-admission.d.ts +26 -0
  268. package/dist/root-read-admission.d.ts.map +1 -0
  269. package/dist/root-read-admission.js +94 -0
  270. package/dist/root-remove-identity.d.ts +15 -0
  271. package/dist/root-remove-identity.d.ts.map +1 -0
  272. package/dist/root-remove-identity.js +89 -0
  273. package/dist/root-remove-receipt.d.ts +17 -0
  274. package/dist/root-remove-receipt.d.ts.map +1 -0
  275. package/dist/root-remove-receipt.js +37 -0
  276. package/dist/root-remove.d.ts +2 -1
  277. package/dist/root-remove.d.ts.map +1 -1
  278. package/dist/root-remove.js +172 -10
  279. package/dist/root-walk.d.ts.map +1 -1
  280. package/dist/root-walk.js +2 -1
  281. package/dist/root-write-admission.d.ts +68 -0
  282. package/dist/root-write-admission.d.ts.map +1 -0
  283. package/dist/root-write-admission.js +322 -0
  284. package/dist/root-write-compatibility.d.ts +13 -0
  285. package/dist/root-write-compatibility.d.ts.map +1 -0
  286. package/dist/root-write-compatibility.js +74 -0
  287. package/dist/root-write-complete-parent.d.ts +42 -0
  288. package/dist/root-write-complete-parent.d.ts.map +1 -0
  289. package/dist/root-write-complete-parent.js +195 -0
  290. package/dist/root-write-mode.d.ts +2 -0
  291. package/dist/root-write-mode.d.ts.map +1 -1
  292. package/dist/root-write-mode.js +20 -7
  293. package/dist/root-write-publication.d.ts +24 -0
  294. package/dist/root-write-publication.d.ts.map +1 -0
  295. package/dist/root-write-publication.js +85 -0
  296. package/dist/root-write-verification.d.ts.map +1 -1
  297. package/dist/root-write-verification.js +18 -7
  298. package/dist/safe-path-segment.d.ts.map +1 -1
  299. package/dist/safe-path-segment.js +3 -1
  300. package/dist/secret-file.d.ts.map +1 -1
  301. package/dist/secret-file.js +62 -24
  302. package/dist/secret-read-async.d.ts.map +1 -1
  303. package/dist/secret-read-async.js +18 -13
  304. package/dist/secret-read-policy.d.ts.map +1 -1
  305. package/dist/secret-read-policy.js +5 -1
  306. package/dist/secure-file-windows.d.ts +10 -0
  307. package/dist/secure-file-windows.d.ts.map +1 -0
  308. package/dist/secure-file-windows.js +186 -0
  309. package/dist/secure-file.d.ts.map +1 -1
  310. package/dist/secure-file.js +98 -10
  311. package/dist/secure-temp-dir.d.ts +6 -3
  312. package/dist/secure-temp-dir.d.ts.map +1 -1
  313. package/dist/secure-temp-dir.js +121 -101
  314. package/dist/secure-temp-repair.d.ts +35 -0
  315. package/dist/secure-temp-repair.d.ts.map +1 -0
  316. package/dist/secure-temp-repair.js +106 -0
  317. package/dist/sibling-staged-file.d.ts +3 -1
  318. package/dist/sibling-staged-file.d.ts.map +1 -1
  319. package/dist/sibling-staged-file.js +181 -50
  320. package/dist/sibling-temp.d.ts.map +1 -1
  321. package/dist/sibling-temp.js +27 -12
  322. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  323. package/dist/sidecar-lock-acquire.js +45 -15
  324. package/dist/sidecar-lock-root.d.ts.map +1 -1
  325. package/dist/sidecar-lock-root.js +4 -2
  326. package/dist/sidecar-lock.d.ts.map +1 -1
  327. package/dist/sidecar-lock.js +2 -3
  328. package/dist/staged-directory.d.ts +14 -5
  329. package/dist/staged-directory.d.ts.map +1 -1
  330. package/dist/staged-directory.js +54 -3
  331. package/dist/standalone-publication-path.d.ts +2 -0
  332. package/dist/standalone-publication-path.d.ts.map +1 -0
  333. package/dist/standalone-publication-path.js +6 -0
  334. package/dist/stat-observation.d.ts +11 -0
  335. package/dist/stat-observation.d.ts.map +1 -0
  336. package/dist/stat-observation.js +64 -0
  337. package/dist/strict-file-identity.d.ts.map +1 -1
  338. package/dist/strict-file-identity.js +39 -2
  339. package/dist/symlink-parents.d.ts.map +1 -1
  340. package/dist/symlink-parents.js +7 -2
  341. package/dist/temp-target.d.ts +2 -0
  342. package/dist/temp-target.d.ts.map +1 -1
  343. package/dist/temp-target.js +133 -4
  344. package/dist/temp-workspace-admission.d.ts +22 -0
  345. package/dist/temp-workspace-admission.d.ts.map +1 -0
  346. package/dist/temp-workspace-admission.js +374 -0
  347. package/dist/temp-workspace-child-admission.d.ts +13 -0
  348. package/dist/temp-workspace-child-admission.d.ts.map +1 -0
  349. package/dist/temp-workspace-child-admission.js +95 -0
  350. package/dist/temp-workspace-descriptor.d.ts +48 -0
  351. package/dist/temp-workspace-descriptor.d.ts.map +1 -0
  352. package/dist/temp-workspace-descriptor.js +363 -0
  353. package/dist/temp-workspace-identity.d.ts +15 -0
  354. package/dist/temp-workspace-identity.d.ts.map +1 -0
  355. package/dist/temp-workspace-identity.js +41 -0
  356. package/dist/temp-workspace-owner.d.ts +7 -6
  357. package/dist/temp-workspace-owner.d.ts.map +1 -1
  358. package/dist/temp-workspace-owner.js +121 -61
  359. package/dist/temp-workspace-permissions.d.ts +4 -0
  360. package/dist/temp-workspace-permissions.d.ts.map +1 -0
  361. package/dist/temp-workspace-permissions.js +32 -0
  362. package/dist/temp-workspace-types.d.ts +40 -0
  363. package/dist/temp-workspace-types.d.ts.map +1 -0
  364. package/dist/temp-workspace-types.js +1 -0
  365. package/dist/temp.d.ts +1 -1
  366. package/dist/temp.d.ts.map +1 -1
  367. package/dist/temp.js +1 -1
  368. package/dist/test-hooks.d.ts +7 -0
  369. package/dist/test-hooks.d.ts.map +1 -1
  370. package/dist/text-atomic.d.ts.map +1 -1
  371. package/dist/text-atomic.js +3 -1
  372. package/dist/trash.d.ts.map +1 -1
  373. package/dist/trash.js +54 -8
  374. package/dist/walk.d.ts.map +1 -1
  375. package/dist/walk.js +20 -16
  376. package/dist/windows-owner.d.ts.map +1 -1
  377. package/dist/windows-owner.js +5 -0
  378. package/dist/windows-path-alias.d.ts +39 -0
  379. package/dist/windows-path-alias.d.ts.map +1 -0
  380. package/dist/windows-path-alias.js +153 -0
  381. package/docs/advanced.md +28 -1
  382. package/docs/archive.md +29 -2
  383. package/docs/atomic.md +27 -3
  384. package/docs/contributing.md +4 -1
  385. package/docs/copy.md +4 -1
  386. package/docs/durability.md +18 -2
  387. package/docs/errors.md +14 -6
  388. package/docs/file-store.md +30 -3
  389. package/docs/filename.md +21 -7
  390. package/docs/guest.md +5 -0
  391. package/docs/install-path.md +61 -15
  392. package/docs/install.md +12 -8
  393. package/docs/json-store.md +5 -1
  394. package/docs/json.md +11 -0
  395. package/docs/mutation-policy-proof.md +65 -0
  396. package/docs/native-helper.md +28 -9
  397. package/docs/native.md +46 -10
  398. package/docs/output.md +33 -11
  399. package/docs/path-prefix.md +64 -0
  400. package/docs/path-suffix-aliases.md +159 -0
  401. package/docs/path.md +12 -1
  402. package/docs/permissions.md +26 -1
  403. package/docs/private-file-store.md +14 -0
  404. package/docs/public-api.md +14 -0
  405. package/docs/quickstart.md +1 -1
  406. package/docs/reading.md +8 -1
  407. package/docs/root.md +21 -4
  408. package/docs/secret-file.md +3 -0
  409. package/docs/secure-file.md +21 -16
  410. package/docs/security-model.md +76 -9
  411. package/docs/sidecar-lock.md +28 -1
  412. package/docs/store.md +27 -2
  413. package/docs/temp.md +262 -34
  414. package/docs/test-hooks.md +14 -0
  415. package/docs/writing.md +38 -8
  416. package/package.json +10 -10
@@ -1,16 +1,20 @@
1
- import { randomUUID } from "node:crypto";
2
- import fsSync from "node:fs";
1
+ import { randomInt, randomUUID } from "node:crypto";
2
+ import fsSync, {} from "node:fs";
3
3
  import fs from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import { fileStore, fileStoreSync, } from "./file-store.js";
6
6
  import { FsSafeError } from "./errors.js";
7
7
  import { isNotFoundPathError } from "./path.js";
8
- import { realpathSync } from "./realpath.js";
9
- import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
8
+ import { inspectDirectoryIdentitySync } from "./directory-guard.js";
10
9
  import { throwFsSafeReadError } from "./root-errors.js";
11
10
  import { matchRootFileOpenFailure, openRootFileSync, } from "./root-file.js";
12
11
  import { registerTempPathForExit, } from "./temp-cleanup.js";
13
12
  import { TempWorkspaceCleanupCapability, TempWorkspaceCleanupOwner, } from "./temp-workspace-owner.js";
13
+ import { assertNoWindowsPathAlias, hasWindowsPathAlias, } from "./windows-path-alias.js";
14
+ import { TempWorkspaceRetainedChild } from "./temp-workspace-descriptor.js";
15
+ import { admitRetainedTempWorkspaceChild, admitRetainedTempWorkspaceChildSync, validateInitialTempWorkspaceChild, } from "./temp-workspace-child-admission.js";
16
+ import { admitTempWorkspaceRoot, admitTempWorkspaceRootSync, } from "./temp-workspace-admission.js";
17
+ import { validateTempWorkspaceDirMode } from "./temp-workspace-permissions.js";
14
18
  function resolveTempWorkspaceCleanupSafety(value) {
15
19
  if (value === undefined || value === "compatible")
16
20
  return "compatible";
@@ -25,8 +29,43 @@ function sanitizeTempPrefix(prefix) {
25
29
  }
26
30
  return sanitized.endsWith("-") ? sanitized : `${sanitized}-`;
27
31
  }
32
+ const TEMP_WORKSPACE_SUFFIX_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
33
+ const TEMP_WORKSPACE_SUFFIX_SPACE = TEMP_WORKSPACE_SUFFIX_ALPHABET.length ** 6;
34
+ const TEMP_WORKSPACE_DIRECT_CREATE_ATTEMPTS = 64;
35
+ function randomTempWorkspaceChildPath(childPrefix) {
36
+ let encoded = randomInt(TEMP_WORKSPACE_SUFFIX_SPACE);
37
+ let suffix = "";
38
+ for (let index = 0; index < 6; index += 1) {
39
+ suffix = TEMP_WORKSPACE_SUFFIX_ALPHABET[encoded % TEMP_WORKSPACE_SUFFIX_ALPHABET.length] + suffix;
40
+ encoded = Math.floor(encoded / TEMP_WORKSPACE_SUFFIX_ALPHABET.length);
41
+ }
42
+ return `${childPrefix}${suffix}`;
43
+ }
44
+ function canCreateTempWorkspaceWithRequestedMode(dirMode) {
45
+ return (process.platform === "linux" || process.platform === "darwin") && dirMode !== 0o700 &&
46
+ (dirMode & 0o700) === 0o700 && (dirMode & 0o7000) === 0 && (dirMode & 0o022) === 0;
47
+ }
48
+ function createTempWorkspaceWithRequestedModeSync(childPrefix, dirMode, prepareChildCreation) {
49
+ let collision;
50
+ for (let attempt = 0; attempt < TEMP_WORKSPACE_DIRECT_CREATE_ATTEMPTS; attempt += 1) {
51
+ const candidate = randomTempWorkspaceChildPath(childPrefix);
52
+ prepareChildCreation();
53
+ try {
54
+ fsSync.mkdirSync(candidate, { mode: dirMode, recursive: false });
55
+ return candidate;
56
+ }
57
+ catch (error) {
58
+ if (error.code !== "EEXIST")
59
+ throw error;
60
+ collision = error;
61
+ }
62
+ }
63
+ throw collision;
64
+ }
28
65
  function resolveWorkspaceLeaf(dir, fileName) {
29
- return path.join(dir, assertWorkspaceFileName(fileName));
66
+ const resolved = path.join(dir, assertWorkspaceFileName(fileName));
67
+ assertNoWindowsPathAlias(resolved, "filesystem", "temp workspace path uses a Windows filesystem namespace alias");
68
+ return resolved;
30
69
  }
31
70
  function assertWorkspaceFileName(fileName) {
32
71
  const value = fileName.trim();
@@ -36,6 +75,7 @@ function assertWorkspaceFileName(fileName) {
36
75
  value.includes("\0") ||
37
76
  value.includes("/") ||
38
77
  value.includes("\\") ||
78
+ hasWindowsPathAlias(value, "relative") ||
39
79
  path.basename(value) !== value) {
40
80
  throw new Error(`Invalid temp workspace file name: ${JSON.stringify(fileName)}`);
41
81
  }
@@ -67,55 +107,60 @@ function throwTempWorkspaceOpenFailure(failure) {
67
107
  },
68
108
  });
69
109
  }
70
- async function ensurePrivateDirectory(dir, mode) {
71
- await fs.mkdir(recursiveMkdirPath(dir), { recursive: true, mode });
72
- const stat = fsSync.statSync(dir);
73
- if (!stat.isDirectory()) {
74
- throw new Error(`Temp root must be a directory: ${dir}`);
75
- }
76
- await fs.chmod(dir, mode).catch(() => undefined);
77
- }
78
- function ensurePrivateDirectorySync(dir, mode) {
79
- fsSync.mkdirSync(recursiveMkdirPath(dir), { recursive: true, mode });
80
- const stat = fsSync.statSync(dir);
81
- if (!stat.isDirectory()) {
82
- throw new Error(`Temp root must be a directory: ${dir}`);
83
- }
84
- try {
85
- fsSync.chmodSync(dir, mode);
86
- }
87
- catch {
88
- // Best-effort on platforms that do not enforce POSIX modes.
89
- }
90
- }
91
- async function createTempWorkspace(options) {
110
+ async function createTempWorkspace(options, scopedPrefix = false) {
111
+ const rootDir = options.rootDir;
112
+ assertNoWindowsPathAlias(rootDir, "filesystem", "temp workspace root uses a Windows filesystem namespace alias");
92
113
  const dirMode = options.dirMode ?? 0o700;
114
+ validateTempWorkspaceDirMode(dirMode);
93
115
  const mode = options.mode ?? 0o600;
94
116
  const cleanupSafety = resolveTempWorkspaceCleanupSafety(options.cleanupSafety);
95
- const requestedRoot = path.resolve(options.rootDir);
96
- let root = requestedRoot;
97
- try {
98
- root = realpathSync.native(requestedRoot);
99
- }
100
- catch {
101
- root = requestedRoot;
102
- }
103
- await ensurePrivateDirectory(root, dirMode);
104
- const capability = new TempWorkspaceCleanupCapability(root, cleanupSafety);
117
+ const admission = await admitTempWorkspaceRoot(rootDir);
118
+ const root = admission.dir;
119
+ assertNoWindowsPathAlias(root, "filesystem", "temp workspace root uses a Windows filesystem namespace alias");
120
+ // Capture and sanitize caller-controlled prefix data before retaining descriptors.
121
+ const rawPrefix = options.prefix;
122
+ const workspacePrefix = scopedPrefix
123
+ ? `${sanitizeTempPrefix(rawPrefix)}${randomUUID()}-`
124
+ : rawPrefix;
125
+ const childPrefix = path.join(root, sanitizeTempPrefix(workspacePrefix));
126
+ assertNoWindowsPathAlias(childPrefix, "filesystem", "temp workspace path uses a Windows filesystem namespace alias");
127
+ const capability = new TempWorkspaceCleanupCapability(root, cleanupSafety, admission, dirMode);
105
128
  let dir;
106
129
  let stat;
130
+ let retainedChild;
131
+ let retainChildDescriptor = false;
107
132
  let cleanupOwner;
108
133
  let unregisterTempDir;
109
134
  try {
110
- dir = await fs.mkdtemp(path.join(root, sanitizeTempPrefix(options.prefix)));
111
- await fs.chmod(dir, dirMode).catch(() => undefined);
112
- stat = fsSync.lstatSync(dir, { bigint: true });
113
- if (stat.isSymbolicLink() || !stat.isDirectory()) {
114
- throw new Error(`Temp workspace must be a directory: ${dir}`);
115
- }
135
+ // Native capability discovery is complete before this synchronous
136
+ // boundary. The existing canonical-root route now captures the complete
137
+ // ancestry and associates its provisional parent descriptor here, then
138
+ // dispatches mkdtemp without yielding or invoking another probe.
139
+ capability.prepareChildCreation();
140
+ dir = await fs.mkdtemp(childPrefix);
141
+ assertNoWindowsPathAlias(dir, "filesystem", "temp workspace path uses a Windows filesystem namespace alias");
116
142
  if (capability.parent)
117
143
  capability.assertCurrent();
118
- cleanupOwner = new TempWorkspaceCleanupOwner(dir, stat, capability);
144
+ else
145
+ admission.assertCurrent();
146
+ stat = inspectDirectoryIdentitySync(dir);
147
+ const needsModeInitialization = validateInitialTempWorkspaceChild(stat, admission.ownerUid, dirMode);
148
+ // Retain while the child still has its private creation mode so an
149
+ // explicit dirMode such as 0 cannot make identity descriptor acquisition fail.
150
+ retainedChild = TempWorkspaceRetainedChild.retain(dir, stat);
151
+ const modeInitialization = admitRetainedTempWorkspaceChild(retainedChild, needsModeInitialization, admission, dirMode);
152
+ if (modeInitialization)
153
+ await modeInitialization;
154
+ retainChildDescriptor = capability.admitChildDescriptor(retainedChild.ensureReadable());
155
+ // Final adoption order is deliberate: complete ancestry, retained cleanup
156
+ // parent, then descriptor and named checks of the original child identity.
157
+ if (capability.parent)
158
+ capability.assertAncestryCurrent();
159
+ else
160
+ admission.assertAncestry();
161
+ stat = retainedChild.finalizeAdmission(admission.ownerUid, dirMode);
162
+ cleanupOwner = new TempWorkspaceCleanupOwner(retainedChild, capability, retainChildDescriptor);
163
+ retainedChild = undefined;
119
164
  unregisterTempDir = registerTempPathForExit(dir, {
120
165
  cleanupSync: () => cleanupOwner.cleanupSync(),
121
166
  });
@@ -124,8 +169,26 @@ async function createTempWorkspace(options) {
124
169
  try {
125
170
  if (cleanupOwner)
126
171
  cleanupOwner.cleanupSync();
127
- else
128
- capability.close();
172
+ else {
173
+ const closeErrors = [];
174
+ try {
175
+ retainedChild?.close();
176
+ }
177
+ catch (closeError) {
178
+ closeErrors.push(closeError);
179
+ }
180
+ try {
181
+ capability.close();
182
+ }
183
+ catch (closeError) {
184
+ closeErrors.push(closeError);
185
+ }
186
+ if (closeErrors.length === 1)
187
+ throw closeErrors[0];
188
+ if (closeErrors.length > 1) {
189
+ throw new AggregateError(closeErrors, "temp workspace admission descriptor close failed");
190
+ }
191
+ }
129
192
  }
130
193
  catch (cleanupError) {
131
194
  throw new AggregateError([error, cleanupError], "temp workspace creation and cleanup both failed");
@@ -178,10 +241,7 @@ export async function tempWorkspace(options) {
178
241
  return await createTempWorkspace(options);
179
242
  }
180
243
  export async function withTempWorkspace(options, run) {
181
- const workspace = await createTempWorkspace({
182
- ...options,
183
- prefix: `${sanitizeTempPrefix(options.prefix)}${randomUUID()}-`,
184
- });
244
+ const workspace = await createTempWorkspace(options, true);
185
245
  try {
186
246
  return await run(workspace);
187
247
  }
@@ -189,39 +249,67 @@ export async function withTempWorkspace(options, run) {
189
249
  await workspace.cleanup();
190
250
  }
191
251
  }
192
- export function tempWorkspaceSync(options) {
252
+ function createTempWorkspaceSync(options, scopedPrefix = false) {
253
+ const rootDir = options.rootDir;
254
+ assertNoWindowsPathAlias(rootDir, "filesystem", "temp workspace root uses a Windows filesystem namespace alias");
193
255
  const dirMode = options.dirMode ?? 0o700;
256
+ validateTempWorkspaceDirMode(dirMode);
194
257
  const mode = options.mode ?? 0o600;
195
258
  const cleanupSafety = resolveTempWorkspaceCleanupSafety(options.cleanupSafety);
196
- const requestedRoot = path.resolve(options.rootDir);
197
- let root = requestedRoot;
198
- try {
199
- root = realpathSync.native(requestedRoot);
200
- }
201
- catch {
202
- root = requestedRoot;
203
- }
204
- ensurePrivateDirectorySync(root, dirMode);
205
- const capability = new TempWorkspaceCleanupCapability(root, cleanupSafety);
259
+ const admission = admitTempWorkspaceRootSync(rootDir);
260
+ const root = admission.dir;
261
+ assertNoWindowsPathAlias(root, "filesystem", "temp workspace root uses a Windows filesystem namespace alias");
262
+ // Capture and sanitize caller-controlled prefix data before retaining descriptors.
263
+ const rawPrefix = options.prefix;
264
+ const workspacePrefix = scopedPrefix
265
+ ? `${sanitizeTempPrefix(rawPrefix)}${randomUUID()}-`
266
+ : rawPrefix;
267
+ const childPrefix = path.join(root, sanitizeTempPrefix(workspacePrefix));
268
+ assertNoWindowsPathAlias(childPrefix, "filesystem", "temp workspace path uses a Windows filesystem namespace alias");
269
+ const capability = new TempWorkspaceCleanupCapability(root, cleanupSafety, admission, dirMode);
206
270
  let dir;
207
271
  let stat;
272
+ let retainedChild;
273
+ let retainChildDescriptor = false;
274
+ let needsModeInitialization;
208
275
  let cleanupOwner;
209
276
  let unregisterTempDir;
210
277
  try {
211
- dir = fsSync.mkdtempSync(path.join(root, sanitizeTempPrefix(options.prefix)));
212
- try {
213
- fsSync.chmodSync(dir, dirMode);
278
+ const directRequestedMode = canCreateTempWorkspaceWithRequestedMode(dirMode);
279
+ if (directRequestedMode) {
280
+ dir = createTempWorkspaceWithRequestedModeSync(childPrefix, dirMode, () => capability.prepareChildCreation());
214
281
  }
215
- catch {
216
- // Best-effort on platforms that do not enforce POSIX modes.
217
- }
218
- stat = fsSync.lstatSync(dir, { bigint: true });
219
- if (stat.isSymbolicLink() || !stat.isDirectory()) {
220
- throw new Error(`Temp workspace must be a directory: ${dir}`);
282
+ else {
283
+ capability.prepareChildCreation();
284
+ dir = fsSync.mkdtempSync(childPrefix);
221
285
  }
286
+ assertNoWindowsPathAlias(dir, "filesystem", "temp workspace path uses a Windows filesystem namespace alias");
222
287
  if (capability.parent)
223
288
  capability.assertCurrent();
224
- cleanupOwner = new TempWorkspaceCleanupOwner(dir, stat, capability);
289
+ else
290
+ admission.assertCurrent();
291
+ if (directRequestedMode) {
292
+ const created = TempWorkspaceRetainedChild.retainCreated(dir);
293
+ retainedChild = created.retained;
294
+ stat = created.stat;
295
+ needsModeInitialization = validateInitialTempWorkspaceChild(stat, admission.ownerUid, dirMode);
296
+ }
297
+ else {
298
+ stat = inspectDirectoryIdentitySync(dir);
299
+ needsModeInitialization = validateInitialTempWorkspaceChild(stat, admission.ownerUid, dirMode);
300
+ retainedChild = TempWorkspaceRetainedChild.retain(dir, stat);
301
+ }
302
+ admitRetainedTempWorkspaceChildSync(retainedChild, needsModeInitialization, admission, dirMode);
303
+ retainChildDescriptor = capability.admitChildDescriptor(retainedChild.ensureReadable());
304
+ // Match async adoption: complete ancestry and retained cleanup authority
305
+ // precede descriptor and named child security-state checks.
306
+ if (capability.parent)
307
+ capability.assertAncestryCurrent();
308
+ else
309
+ admission.assertAncestry();
310
+ stat = retainedChild.finalizeAdmission(admission.ownerUid, dirMode);
311
+ cleanupOwner = new TempWorkspaceCleanupOwner(retainedChild, capability, retainChildDescriptor);
312
+ retainedChild = undefined;
225
313
  unregisterTempDir = registerTempPathForExit(dir, {
226
314
  cleanupSync: () => cleanupOwner.cleanupSync(),
227
315
  });
@@ -230,8 +318,26 @@ export function tempWorkspaceSync(options) {
230
318
  try {
231
319
  if (cleanupOwner)
232
320
  cleanupOwner.cleanupSync();
233
- else
234
- capability.close();
321
+ else {
322
+ const closeErrors = [];
323
+ try {
324
+ retainedChild?.close();
325
+ }
326
+ catch (closeError) {
327
+ closeErrors.push(closeError);
328
+ }
329
+ try {
330
+ capability.close();
331
+ }
332
+ catch (closeError) {
333
+ closeErrors.push(closeError);
334
+ }
335
+ if (closeErrors.length === 1)
336
+ throw closeErrors[0];
337
+ if (closeErrors.length > 1) {
338
+ throw new AggregateError(closeErrors, "temp workspace admission descriptor close failed");
339
+ }
340
+ }
235
341
  }
236
342
  catch (cleanupError) {
237
343
  throw new AggregateError([error, cleanupError], "temp workspace creation and cleanup both failed");
@@ -293,11 +399,11 @@ export function tempWorkspaceSync(options) {
293
399
  },
294
400
  };
295
401
  }
402
+ export function tempWorkspaceSync(options) {
403
+ return createTempWorkspaceSync(options);
404
+ }
296
405
  export function withTempWorkspaceSync(options, run) {
297
- const workspace = tempWorkspaceSync({
298
- ...options,
299
- prefix: `${sanitizeTempPrefix(options.prefix)}${randomUUID()}-`,
300
- });
406
+ const workspace = createTempWorkspaceSync(options, true);
301
407
  try {
302
408
  return run(workspace);
303
409
  }
@@ -1 +1 @@
1
- {"version":3,"file":"publish-file.d.ts","sourceRoot":"","sources":["../src/publish-file.ts"],"names":[],"mappings":"AACA,OAAe,EAAoB,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAI/D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAML,KAAK,qCAAqC,EAC3C,MAAM,2BAA2B,CAAC;AAGnC,YAAY,EACV,2BAA2B,EAC3B,wCAAwC,EACxC,kCAAkC,EAClC,gCAAgC,EAChC,qCAAqC,GACtC,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,4BAA4B,GACpC,cAAc,GACd,eAAe,GACf,kBAAkB,CAAC;AAEvB,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,EAAE,UAAU,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;IAC3D,QAAQ,EAAE,KAAK,CAAC;IAChB,aAAa,EAAE,oBAAoB,CAAC;CACrC,CAAC;AAkBF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE/D;AA2ND,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,CAAC,EAAE,gBAAgB,CAAC;IAC1C,QAAQ,EAAE,4BAA4B,CAAC;IACvC,aAAa,CAAC,EAAE,qCAAqC,CAAC;IACtD,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA4MtC"}
1
+ {"version":3,"file":"publish-file.d.ts","sourceRoot":"","sources":["../src/publish-file.ts"],"names":[],"mappings":"AACA,OAAe,EAAoB,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAI/D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAML,KAAK,qCAAqC,EAC3C,MAAM,2BAA2B,CAAC;AAKnC,YAAY,EACV,2BAA2B,EAC3B,wCAAwC,EACxC,kCAAkC,EAClC,gCAAgC,EAChC,qCAAqC,GACtC,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,4BAA4B,GAAG,cAAc,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAEjG,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,EAAE,UAAU,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;IAC3D,QAAQ,EAAE,KAAK,CAAC;IAChB,aAAa,EAAE,oBAAoB,CAAC;CACrC,CAAC;AAIF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE/D;AAyND,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,CAAC,EAAE,gBAAgB,CAAC;IAC1C,QAAQ,EAAE,4BAA4B,CAAC;IACvC,aAAa,CAAC,EAAE,qCAAqC,CAAC;IACtD,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA6NtC"}
@@ -10,28 +10,15 @@ import { syncFileBestEffortSync } from "./file-sync.js";
10
10
  import { getNativeBinding, requireNativeBinding } from "./native.js";
11
11
  import { resolveReadOpenFlags } from "./read-open-flags.js";
12
12
  import { directorySyncFailure, publicationFailure, rememberCreatedTarget, } from "./publish-file-failure.js";
13
+ import { admitStandalonePublicationPath } from "./standalone-publication-path.js";
13
14
  import { getFsSafeTestHooks } from "./test-hooks.js";
14
- const HARDLINK_FALLBACK_CODES = new Set([
15
- "EPERM",
16
- "EXDEV",
17
- "ENOTSUP",
18
- "EOPNOTSUPP",
19
- "ENOSYS",
20
- ]);
21
- const NATIVE_COPY_FALLBACK_CODES = new Set([
22
- "EINVAL",
23
- "ENOSYS",
24
- "ENOTSUP",
25
- "EOPNOTSUPP",
26
- "EPERM",
27
- "EXDEV",
28
- ]);
15
+ import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
16
+ const HARDLINK_FALLBACK_CODES = new Set(["EPERM", "EXDEV", "ENOTSUP", "EOPNOTSUPP", "ENOSYS"]);
17
+ const NATIVE_COPY_FALLBACK_CODES = new Set(["EINVAL", "ENOSYS", "ENOTSUP", "EOPNOTSUPP", "EPERM", "EXDEV"]);
29
18
  export function isHardlinkFallbackError(error) {
30
19
  return HARDLINK_FALLBACK_CODES.has(error?.code ?? "");
31
20
  }
32
- function sourceOpenFlags() {
33
- return resolveReadOpenFlags();
34
- }
21
+ function sourceOpenFlags() { return resolveReadOpenFlags(); }
35
22
  function directoryOpenFlags() {
36
23
  return (fsSync.constants.O_RDONLY |
37
24
  (typeof fsSync.constants.O_DIRECTORY === "number" ? fsSync.constants.O_DIRECTORY : 0));
@@ -190,12 +177,27 @@ async function syncPublishedParent(params) {
190
177
  }
191
178
  }
192
179
  export async function publishFileExclusive(params) {
193
- const sourcePath = path.resolve(params.sourcePath);
194
- const targetPath = path.resolve(params.targetPath);
180
+ const sourcePathInput = admitStandalonePublicationPath(params.sourcePath, "publication source uses a Windows filesystem namespace alias");
181
+ const targetPathInput = admitStandalonePublicationPath(params.targetPath, "publication target uses a Windows filesystem namespace alias");
182
+ const parentReceiptInput = params.parentReceipt;
183
+ const parentReceipt = parentReceiptInput
184
+ ? { path: parentReceiptInput.path, realPath: parentReceiptInput.realPath,
185
+ identity: parentReceiptInput.identity }
186
+ : undefined;
187
+ if (parentReceipt) {
188
+ assertNoWindowsPathAlias(parentReceipt.path, "filesystem", "publication parent uses a Windows filesystem namespace alias");
189
+ }
190
+ const sourcePath = path.resolve(sourcePathInput);
191
+ const targetPath = path.resolve(targetPathInput);
192
+ assertNoWindowsPathAlias(sourcePath, "filesystem", "publication source uses a Windows filesystem namespace alias");
193
+ assertNoWindowsPathAlias(targetPath, "filesystem", "publication target uses a Windows filesystem namespace alias");
195
194
  const parentPath = path.dirname(targetPath);
196
- if (params.parentReceipt && path.resolve(params.parentReceipt.path) !== parentPath) {
195
+ if (parentReceipt && path.resolve(parentReceipt.path) !== parentPath) {
197
196
  throw new FsSafeError("path-mismatch", "publication parent receipt does not match target parent");
198
197
  }
198
+ if (parentReceipt) {
199
+ assertNoWindowsPathAlias(parentReceipt.realPath, "filesystem", "publication parent uses a Windows filesystem namespace alias");
200
+ }
199
201
  const sourcePathStat = fsSync.lstatSync(sourcePath);
200
202
  if (sourcePathStat.isSymbolicLink() || !sourcePathStat.isFile()) {
201
203
  throw new FsSafeError("not-file", "publication source must be a regular file");
@@ -204,38 +206,40 @@ export async function publishFileExclusive(params) {
204
206
  let parent;
205
207
  let sourceNativeParent;
206
208
  let targetNativeParent;
209
+ const strategy = params.strategy;
207
210
  const failure = {
208
- phase: params.strategy === "rename-noreplace" ? "rename-create" : "hardlink-create",
211
+ phase: strategy === "rename-noreplace" ? "rename-create" : "hardlink-create",
209
212
  targetCreated: false,
210
213
  preserveTarget: false,
211
214
  };
212
215
  try {
213
- parent = await pinDirectory(params.parentReceipt ?? parentPath, {
216
+ parent = await pinDirectory(parentReceipt ?? parentPath, {
214
217
  label: "publication parent",
215
218
  });
216
219
  const sourceIdentity = fsSync.fstatSync(source.fd);
217
220
  const sourceExactIdentity = fsSync.fstatSync(source.fd, { bigint: true });
218
221
  const sourcePathExactIdentity = fsSync.lstatSync(sourcePath, { bigint: true });
222
+ const expectedSourceIdentity = params.expectedSourceIdentity;
219
223
  if (sourcePathExactIdentity.isSymbolicLink() ||
220
224
  !sourcePathExactIdentity.isFile() ||
221
225
  !sameFileIdentity(sourcePathExactIdentity, sourceExactIdentity) ||
222
- (params.expectedSourceIdentity &&
223
- !sameFileIdentity(params.expectedSourceIdentity, typeof params.expectedSourceIdentity.dev === "bigint" ||
224
- typeof params.expectedSourceIdentity.ino === "bigint"
226
+ (expectedSourceIdentity &&
227
+ !sameFileIdentity(expectedSourceIdentity, typeof expectedSourceIdentity.dev === "bigint" ||
228
+ typeof expectedSourceIdentity.ino === "bigint"
225
229
  ? sourceExactIdentity
226
230
  : sourceIdentity))) {
227
231
  throw new FsSafeError("path-mismatch", "publication source identity did not match");
228
232
  }
229
233
  await parent.assertCurrent();
230
234
  await assertPinnedSourceCurrent({ sourcePath, handle: source, identity: sourceExactIdentity });
231
- const native = params.strategy === "rename-noreplace"
235
+ const native = strategy === "rename-noreplace"
232
236
  ? requireNativeBinding()
233
237
  : getNativeBinding();
234
238
  if (native) {
235
239
  sourceNativeParent = await openNativeParent(sourcePath);
236
240
  targetNativeParent = await openNativeParent(targetPath);
237
241
  }
238
- if (params.strategy === "rename-noreplace") {
242
+ if (strategy === "rename-noreplace") {
239
243
  const binding = requireNativeBinding();
240
244
  binding.renameNoReplace(sourceNativeParent.handle.fd, sourceNativeParent.basename, targetNativeParent.handle.fd, targetNativeParent.basename);
241
245
  rememberCreatedTarget(failure, sourceExactIdentity, "rename-verify");
@@ -301,7 +305,7 @@ export async function publishFileExclusive(params) {
301
305
  catch (error) {
302
306
  if (failure.targetCreated ||
303
307
  !isHardlinkFallbackError(error) ||
304
- params.strategy === "link-required") {
308
+ strategy === "link-required") {
305
309
  throw error;
306
310
  }
307
311
  }
@@ -1 +1 @@
1
- {"version":3,"file":"regular-file.d.ts","sourceRoot":"","sources":["../src/regular-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,KAAK,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,MAAM,MAAM,SAAS,CAAC;AAmB7B,MAAM,MAAM,qBAAqB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAExF,KAAK,8BAA8B,GAAG,IAAI,CACxC,OAAO,MAAM,CAAC,SAAS,EACvB,UAAU,GAAG,SAAS,GAAG,UAAU,CACpC,GACC,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,SAAS,EAAE,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC;AAEtE,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,8BAAiD,GAC3D,MAAM,CASR;AAaD,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CActF;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CAc3E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CA6D3C;AA2DD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IACpF,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,CAAC;CACb,CAoCA;AAmBD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgFxF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,CAgF7E"}
1
+ {"version":3,"file":"regular-file.d.ts","sourceRoot":"","sources":["../src/regular-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,KAAK,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,MAAM,MAAM,SAAS,CAAC;AAuB7B,MAAM,MAAM,qBAAqB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAExF,KAAK,8BAA8B,GAAG,IAAI,CACxC,OAAO,MAAM,CAAC,SAAS,EACvB,UAAU,GAAG,SAAS,GAAG,UAAU,CACpC,GACC,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,SAAS,EAAE,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC;AAEtE,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,8BAAiD,GAC3D,MAAM,CASR;AAaD,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAetF;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CAe3E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CA+D3C;AA2DD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IACpF,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,CAAC;CACb,CAsCA;AAmBD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFxF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,CAkF7E"}