@openclaw/fs-safe 0.14.0 → 0.16.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 (370) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +38 -10
  3. package/dist/advanced.d.ts +2 -1
  4. package/dist/advanced.d.ts.map +1 -1
  5. package/dist/advanced.js +2 -1
  6. package/dist/archive-kind.d.ts +0 -1
  7. package/dist/archive-kind.d.ts.map +1 -1
  8. package/dist/archive-kind.js +5 -17
  9. package/dist/archive-merge.d.ts.map +1 -1
  10. package/dist/archive-merge.js +113 -46
  11. package/dist/archive-parser.wasm +0 -0
  12. package/dist/archive-read.d.ts.map +1 -1
  13. package/dist/archive-read.js +10 -11
  14. package/dist/archive-tar-stream.d.ts +3 -0
  15. package/dist/archive-tar-stream.d.ts.map +1 -1
  16. package/dist/archive-tar-stream.js +56 -37
  17. package/dist/archive-tar-wasm.d.ts +16 -4
  18. package/dist/archive-tar-wasm.d.ts.map +1 -1
  19. package/dist/archive-tar-wasm.js +134 -34
  20. package/dist/archive-zip-directory.d.ts +4 -0
  21. package/dist/archive-zip-directory.d.ts.map +1 -1
  22. package/dist/archive-zip-directory.js +2 -0
  23. package/dist/archive-zip-entry.d.ts +6 -2
  24. package/dist/archive-zip-entry.d.ts.map +1 -1
  25. package/dist/archive-zip-entry.js +23 -8
  26. package/dist/archive-zip-integrity.d.ts.map +1 -1
  27. package/dist/archive-zip-integrity.js +3 -4
  28. package/dist/archive-zip-loader.d.ts.map +1 -1
  29. package/dist/archive-zip-loader.js +107 -31
  30. package/dist/archive-zip-names.d.ts +1 -0
  31. package/dist/archive-zip-names.d.ts.map +1 -1
  32. package/dist/archive-zip-names.js +6 -0
  33. package/dist/archive.d.ts.map +1 -1
  34. package/dist/archive.js +11 -11
  35. package/dist/bounded-read-stream.d.ts +0 -1
  36. package/dist/bounded-read-stream.d.ts.map +1 -1
  37. package/dist/bounded-read-stream.js +0 -6
  38. package/dist/clone-metadata.d.ts +1 -0
  39. package/dist/clone-metadata.d.ts.map +1 -1
  40. package/dist/clone-metadata.js +6 -2
  41. package/dist/copy-publication.d.ts +6 -0
  42. package/dist/copy-publication.d.ts.map +1 -1
  43. package/dist/copy-publication.js +3 -0
  44. package/dist/copy-tree-portable.d.ts.map +1 -1
  45. package/dist/copy-tree-portable.js +44 -24
  46. package/dist/copy.d.ts.map +1 -1
  47. package/dist/copy.js +29 -11
  48. package/dist/create-directory.d.ts +20 -0
  49. package/dist/create-directory.d.ts.map +1 -0
  50. package/dist/create-directory.js +130 -0
  51. package/dist/create-file-async.d.ts +7 -0
  52. package/dist/create-file-async.d.ts.map +1 -0
  53. package/dist/create-file-async.js +121 -0
  54. package/dist/create-file.d.ts +8 -0
  55. package/dist/create-file.d.ts.map +1 -0
  56. package/dist/create-file.js +190 -0
  57. package/dist/create-owned-file.d.ts +8 -0
  58. package/dist/create-owned-file.d.ts.map +1 -0
  59. package/dist/create-owned-file.js +16 -0
  60. package/dist/create.d.ts +4 -0
  61. package/dist/create.d.ts.map +1 -0
  62. package/dist/create.js +2 -0
  63. package/dist/creation-darwin.d.ts +7 -0
  64. package/dist/creation-darwin.d.ts.map +1 -0
  65. package/dist/creation-darwin.js +79 -0
  66. package/dist/creation-file-state.d.ts +19 -0
  67. package/dist/creation-file-state.d.ts.map +1 -0
  68. package/dist/creation-file-state.js +118 -0
  69. package/dist/creation-path.d.ts +21 -0
  70. package/dist/creation-path.d.ts.map +1 -0
  71. package/dist/creation-path.js +71 -0
  72. package/dist/creation-permissions.d.ts +19 -0
  73. package/dist/creation-permissions.d.ts.map +1 -0
  74. package/dist/creation-permissions.js +125 -0
  75. package/dist/directory-durability.d.ts +1 -1
  76. package/dist/directory-durability.d.ts.map +1 -1
  77. package/dist/directory-durability.js +22 -80
  78. package/dist/directory-guard.d.ts +3 -0
  79. package/dist/directory-guard.d.ts.map +1 -1
  80. package/dist/directory-mode-node.d.ts +2 -0
  81. package/dist/directory-mode-node.d.ts.map +1 -1
  82. package/dist/directory-mode-node.js +8 -0
  83. package/dist/directory-mode-owner.js +5 -5
  84. package/dist/directory-receipt.d.ts +24 -0
  85. package/dist/directory-receipt.d.ts.map +1 -0
  86. package/dist/directory-receipt.js +127 -0
  87. package/dist/file-cleanup.d.ts +19 -0
  88. package/dist/file-cleanup.d.ts.map +1 -0
  89. package/dist/file-cleanup.js +78 -0
  90. package/dist/file-handle-transfer.d.ts +2 -0
  91. package/dist/file-handle-transfer.d.ts.map +1 -1
  92. package/dist/file-handle-transfer.js +57 -2
  93. package/dist/file-identity.d.ts.map +1 -1
  94. package/dist/file-identity.js +18 -4
  95. package/dist/file-lock-sync-admission.d.ts +19 -0
  96. package/dist/file-lock-sync-admission.d.ts.map +1 -0
  97. package/dist/file-lock-sync-admission.js +93 -0
  98. package/dist/file-lock-sync-root-acquire.d.ts +4 -0
  99. package/dist/file-lock-sync-root-acquire.d.ts.map +1 -0
  100. package/dist/file-lock-sync-root-acquire.js +370 -0
  101. package/dist/file-lock-sync-root-arbitration.d.ts +18 -0
  102. package/dist/file-lock-sync-root-arbitration.d.ts.map +1 -0
  103. package/dist/file-lock-sync-root-arbitration.js +66 -0
  104. package/dist/file-lock-sync-root-held.d.ts +34 -0
  105. package/dist/file-lock-sync-root-held.d.ts.map +1 -0
  106. package/dist/file-lock-sync-root-held.js +393 -0
  107. package/dist/file-lock-sync-root-io.d.ts +44 -0
  108. package/dist/file-lock-sync-root-io.d.ts.map +1 -0
  109. package/dist/file-lock-sync-root-io.js +209 -0
  110. package/dist/file-lock-sync-root-mutation.d.ts +17 -0
  111. package/dist/file-lock-sync-root-mutation.d.ts.map +1 -0
  112. package/dist/file-lock-sync-root-mutation.js +277 -0
  113. package/dist/file-lock-sync-root-options.d.ts +20 -0
  114. package/dist/file-lock-sync-root-options.d.ts.map +1 -0
  115. package/dist/file-lock-sync-root-options.js +58 -0
  116. package/dist/file-lock-sync-root-registration.d.ts +2 -0
  117. package/dist/file-lock-sync-root-registration.d.ts.map +1 -0
  118. package/dist/file-lock-sync-root-registration.js +90 -0
  119. package/dist/file-lock-sync-root.d.ts +36 -0
  120. package/dist/file-lock-sync-root.d.ts.map +1 -0
  121. package/dist/file-lock-sync-root.js +361 -0
  122. package/dist/file-lock-sync-stale-admission.d.ts +24 -0
  123. package/dist/file-lock-sync-stale-admission.d.ts.map +1 -0
  124. package/dist/file-lock-sync-stale-admission.js +205 -0
  125. package/dist/file-lock-sync.d.ts.map +1 -1
  126. package/dist/file-lock-sync.js +245 -205
  127. package/dist/file-observation.d.ts +1 -1
  128. package/dist/file-observation.d.ts.map +1 -1
  129. package/dist/file-store-boundary.d.ts +2 -6
  130. package/dist/file-store-boundary.d.ts.map +1 -1
  131. package/dist/file-store-boundary.js +3 -9
  132. package/dist/file-store-prune.d.ts.map +1 -1
  133. package/dist/file-store-prune.js +5 -1
  134. package/dist/file-store-sync-write.d.ts.map +1 -1
  135. package/dist/file-store-sync-write.js +5 -8
  136. package/dist/file-store.d.ts.map +1 -1
  137. package/dist/file-store.js +47 -12
  138. package/dist/guarded-mkdir.d.ts +1 -0
  139. package/dist/guarded-mkdir.d.ts.map +1 -1
  140. package/dist/guarded-mkdir.js +36 -7
  141. package/dist/json-document-store.d.ts.map +1 -1
  142. package/dist/json-document-store.js +22 -15
  143. package/dist/json-durable-queue-ownership.d.ts +0 -1
  144. package/dist/json-durable-queue-ownership.d.ts.map +1 -1
  145. package/dist/json-durable-queue-ownership.js +0 -6
  146. package/dist/move-path.js +1 -1
  147. package/dist/native-binding.d.ts +13 -1
  148. package/dist/native-binding.d.ts.map +1 -1
  149. package/dist/native-fallback-warning.d.ts +4 -0
  150. package/dist/native-fallback-warning.d.ts.map +1 -0
  151. package/dist/native-fallback-warning.js +11 -0
  152. package/dist/native-operations.d.ts +0 -2
  153. package/dist/native-operations.d.ts.map +1 -1
  154. package/dist/native-operations.js +0 -24
  155. package/dist/native-parent-admission.d.ts +5 -2
  156. package/dist/native-parent-admission.d.ts.map +1 -1
  157. package/dist/native-parent-admission.js +27 -7
  158. package/dist/native-pinned-write-windows.d.ts +1 -1
  159. package/dist/native-pinned-write-windows.d.ts.map +1 -1
  160. package/dist/native-pinned-write-windows.js +174 -29
  161. package/dist/native-pinned-write.d.ts.map +1 -1
  162. package/dist/native-pinned-write.js +26 -14
  163. package/dist/native-policy-parent-windows.d.ts +14 -0
  164. package/dist/native-policy-parent-windows.d.ts.map +1 -0
  165. package/dist/native-policy-parent-windows.js +209 -0
  166. package/dist/native-rename-outcome.d.ts +4 -0
  167. package/dist/native-rename-outcome.d.ts.map +1 -0
  168. package/dist/native-rename-outcome.js +8 -0
  169. package/dist/native-staged-file.d.ts +3 -2
  170. package/dist/native-staged-file.d.ts.map +1 -1
  171. package/dist/native-staged-file.js +121 -72
  172. package/dist/output.d.ts.map +1 -1
  173. package/dist/output.js +12 -8
  174. package/dist/owner-dacl.d.ts.map +1 -1
  175. package/dist/owner-dacl.js +10 -4
  176. package/dist/path-prefix.d.ts.map +1 -1
  177. package/dist/path-prefix.js +30 -8
  178. package/dist/path-suffix-aliases.d.ts +2 -0
  179. package/dist/path-suffix-aliases.d.ts.map +1 -1
  180. package/dist/path-suffix-aliases.js +25 -17
  181. package/dist/permission-exec.d.ts +2 -0
  182. package/dist/permission-exec.d.ts.map +1 -1
  183. package/dist/permission-exec.js +150 -21
  184. package/dist/permissions-windows.js +1 -1
  185. package/dist/pinned-mutation-admission.d.ts.map +1 -1
  186. package/dist/pinned-mutation-admission.js +10 -5
  187. package/dist/pinned-mutation-observation.d.ts +0 -1
  188. package/dist/pinned-mutation-observation.d.ts.map +1 -1
  189. package/dist/pinned-mutation-observation.js +0 -19
  190. package/dist/pinned-mutation-shared-route.d.ts +1 -0
  191. package/dist/pinned-mutation-shared-route.d.ts.map +1 -1
  192. package/dist/pinned-mutation-shared-route.js +1 -1
  193. package/dist/pinned-write-input.d.ts +4 -0
  194. package/dist/pinned-write-input.d.ts.map +1 -0
  195. package/dist/pinned-write-input.js +25 -0
  196. package/dist/pinned-write-mode.d.ts +5 -0
  197. package/dist/pinned-write-mode.d.ts.map +1 -0
  198. package/dist/pinned-write-mode.js +24 -0
  199. package/dist/pinned-write-staged.d.ts +6 -0
  200. package/dist/pinned-write-staged.d.ts.map +1 -0
  201. package/dist/pinned-write-staged.js +187 -0
  202. package/dist/pinned-write-types.d.ts +5 -0
  203. package/dist/pinned-write-types.d.ts.map +1 -1
  204. package/dist/pinned-write.d.ts.map +1 -1
  205. package/dist/pinned-write.js +35 -145
  206. package/dist/private-directory.d.ts.map +1 -1
  207. package/dist/private-directory.js +18 -4
  208. package/dist/private-producer-handoff-sync.d.ts +14 -0
  209. package/dist/private-producer-handoff-sync.d.ts.map +1 -0
  210. package/dist/private-producer-handoff-sync.js +114 -0
  211. package/dist/private-producer-handoff.d.ts +22 -4
  212. package/dist/private-producer-handoff.d.ts.map +1 -1
  213. package/dist/private-producer-handoff.js +140 -77
  214. package/dist/private-temp-workspace.d.ts.map +1 -1
  215. package/dist/private-temp-workspace.js +75 -121
  216. package/dist/publish-copy-stage.d.ts +2 -1
  217. package/dist/publish-copy-stage.d.ts.map +1 -1
  218. package/dist/publish-copy-stage.js +16 -7
  219. package/dist/publish-file.d.ts.map +1 -1
  220. package/dist/publish-file.js +2 -2
  221. package/dist/regular-file.d.ts.map +1 -1
  222. package/dist/regular-file.js +1 -15
  223. package/dist/replace-directory.d.ts.map +1 -1
  224. package/dist/replace-directory.js +256 -18
  225. package/dist/replace-file-copy-fallback.d.ts.map +1 -1
  226. package/dist/replace-file-copy-fallback.js +62 -70
  227. package/dist/replace-file-copy-source.d.ts.map +1 -1
  228. package/dist/replace-file-copy-source.js +10 -12
  229. package/dist/replace-file-temp-owner.d.ts +5 -9
  230. package/dist/replace-file-temp-owner.d.ts.map +1 -1
  231. package/dist/replace-file-temp-owner.js +56 -72
  232. package/dist/replace-file.js +6 -6
  233. package/dist/retained-directory-replacement.d.ts +26 -0
  234. package/dist/retained-directory-replacement.d.ts.map +1 -0
  235. package/dist/retained-directory-replacement.js +193 -0
  236. package/dist/root-boundary.d.ts +1 -0
  237. package/dist/root-boundary.d.ts.map +1 -1
  238. package/dist/root-boundary.js +4 -0
  239. package/dist/root-context.d.ts +0 -8
  240. package/dist/root-context.d.ts.map +1 -1
  241. package/dist/root-context.js +0 -3
  242. package/dist/root-create-input.d.ts +8 -1
  243. package/dist/root-create-input.d.ts.map +1 -1
  244. package/dist/root-create-input.js +17 -4
  245. package/dist/root-directory-creation.d.ts +3 -3
  246. package/dist/root-directory-creation.d.ts.map +1 -1
  247. package/dist/root-directory-creation.js +15 -3
  248. package/dist/root-directory-list.d.ts +1 -0
  249. package/dist/root-directory-list.d.ts.map +1 -1
  250. package/dist/root-directory-list.js +1 -0
  251. package/dist/root-impl.d.ts.map +1 -1
  252. package/dist/root-impl.js +46 -17
  253. package/dist/root-move-noreplace.d.ts.map +1 -1
  254. package/dist/root-move-noreplace.js +24 -15
  255. package/dist/root-options.d.ts +12 -4
  256. package/dist/root-options.d.ts.map +1 -1
  257. package/dist/root-path-errors.d.ts +1 -0
  258. package/dist/root-path-errors.d.ts.map +1 -1
  259. package/dist/root-path-errors.js +11 -2
  260. package/dist/root-path-existing.d.ts.map +1 -1
  261. package/dist/root-path-existing.js +11 -35
  262. package/dist/root-path-stat.d.ts.map +1 -1
  263. package/dist/root-path-stat.js +59 -7
  264. package/dist/root-path.js +1 -13
  265. package/dist/root-remove.d.ts +1 -0
  266. package/dist/root-remove.d.ts.map +1 -1
  267. package/dist/root-remove.js +4 -0
  268. package/dist/root-walk.d.ts +1 -1
  269. package/dist/root-walk.d.ts.map +1 -1
  270. package/dist/root-walk.js +17 -2
  271. package/dist/root-write-admission.d.ts +0 -2
  272. package/dist/root-write-admission.d.ts.map +1 -1
  273. package/dist/root-write-admission.js +1 -15
  274. package/dist/root-write-complete-parent.d.ts.map +1 -1
  275. package/dist/root-write-complete-parent.js +7 -23
  276. package/dist/root-write-publication.js +1 -1
  277. package/dist/root-write-verification.d.ts.map +1 -1
  278. package/dist/root-write-verification.js +29 -42
  279. package/dist/secret-file.d.ts.map +1 -1
  280. package/dist/secret-file.js +3 -24
  281. package/dist/secret-read-async.d.ts.map +1 -1
  282. package/dist/secret-read-async.js +3 -24
  283. package/dist/secret-read-policy.d.ts +6 -2
  284. package/dist/secret-read-policy.d.ts.map +1 -1
  285. package/dist/secret-read-policy.js +26 -2
  286. package/dist/secure-file-windows.d.ts +6 -0
  287. package/dist/secure-file-windows.d.ts.map +1 -1
  288. package/dist/secure-file-windows.js +34 -117
  289. package/dist/secure-file.js +2 -2
  290. package/dist/sibling-temp.d.ts.map +1 -1
  291. package/dist/sibling-temp.js +23 -12
  292. package/dist/sidecar-lock-acquire.d.ts +2 -28
  293. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  294. package/dist/sidecar-lock-acquire.js +288 -199
  295. package/dist/sidecar-lock-admission-context.d.ts +19 -0
  296. package/dist/sidecar-lock-admission-context.d.ts.map +1 -0
  297. package/dist/sidecar-lock-admission-context.js +60 -0
  298. package/dist/sidecar-lock-admission-parser.d.ts +43 -0
  299. package/dist/sidecar-lock-admission-parser.d.ts.map +1 -0
  300. package/dist/sidecar-lock-admission-parser.js +113 -0
  301. package/dist/sidecar-lock-admission.d.ts +35 -0
  302. package/dist/sidecar-lock-admission.d.ts.map +1 -0
  303. package/dist/sidecar-lock-admission.js +7 -0
  304. package/dist/sidecar-lock-reclaim.d.ts +9 -4
  305. package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
  306. package/dist/sidecar-lock-reclaim.js +80 -25
  307. package/dist/sidecar-lock-root.d.ts.map +1 -1
  308. package/dist/sidecar-lock-root.js +2 -1
  309. package/dist/sidecar-lock-stale-admission.d.ts +39 -0
  310. package/dist/sidecar-lock-stale-admission.d.ts.map +1 -0
  311. package/dist/sidecar-lock-stale-admission.js +232 -0
  312. package/dist/sidecar-lock-target.d.ts +8 -0
  313. package/dist/sidecar-lock-target.d.ts.map +1 -0
  314. package/dist/sidecar-lock-target.js +55 -0
  315. package/dist/sidecar-lock.d.ts.map +1 -1
  316. package/dist/sidecar-lock.js +100 -16
  317. package/dist/staged-directory.d.ts.map +1 -1
  318. package/dist/staged-directory.js +6 -6
  319. package/dist/staged-file-settlement.d.ts +17 -0
  320. package/dist/staged-file-settlement.d.ts.map +1 -0
  321. package/dist/staged-file-settlement.js +57 -0
  322. package/dist/temp-workspace-descriptor.d.ts.map +1 -1
  323. package/dist/temp-workspace-descriptor.js +9 -27
  324. package/dist/temp-workspace-owner.d.ts.map +1 -1
  325. package/dist/temp-workspace-owner.js +8 -8
  326. package/dist/walk.d.ts +5 -1
  327. package/dist/walk.d.ts.map +1 -1
  328. package/dist/walk.js +19 -6
  329. package/dist/windows-owner.d.ts.map +1 -1
  330. package/dist/windows-owner.js +4 -3
  331. package/dist/windows-security-bridge.cs +336 -0
  332. package/dist/windows-security-bridge.ps1 +15 -0
  333. package/dist/windows-security-command.d.ts +26 -0
  334. package/dist/windows-security-command.d.ts.map +1 -0
  335. package/dist/windows-security-command.js +363 -0
  336. package/dist/windows-security-facts.d.ts +6 -0
  337. package/dist/windows-security-facts.d.ts.map +1 -0
  338. package/dist/windows-security-facts.js +108 -0
  339. package/docs/advanced.md +4 -2
  340. package/docs/archive.md +97 -46
  341. package/docs/atomic.md +85 -8
  342. package/docs/config.md +6 -2
  343. package/docs/contributing.md +44 -4
  344. package/docs/copy.md +37 -0
  345. package/docs/creation.md +128 -0
  346. package/docs/durability.md +24 -0
  347. package/docs/file-store.md +19 -0
  348. package/docs/install.md +31 -7
  349. package/docs/json-store.md +5 -0
  350. package/docs/migrating-to-0.5.md +15 -6
  351. package/docs/migrating-to-0.6.md +9 -4
  352. package/docs/native-helper.md +32 -12
  353. package/docs/native.md +38 -7
  354. package/docs/output.md +6 -0
  355. package/docs/path-prefix.md +10 -0
  356. package/docs/path-suffix-aliases.md +51 -6
  357. package/docs/permissions.md +50 -14
  358. package/docs/public-api.md +3 -2
  359. package/docs/root.md +56 -3
  360. package/docs/secret-file.md +11 -2
  361. package/docs/secure-file.md +9 -4
  362. package/docs/sidecar-lock.md +114 -8
  363. package/docs/staged-file.md +12 -3
  364. package/docs/temp.md +20 -3
  365. package/docs/walk.md +67 -1
  366. package/docs/writing.md +76 -6
  367. package/package.json +19 -16
  368. package/dist/darwin-acl.d.ts +0 -4
  369. package/dist/darwin-acl.d.ts.map +0 -1
  370. package/dist/darwin-acl.js +0 -24
@@ -1,17 +1,23 @@
1
1
  import { FsSafeError } from "./errors.js";
2
2
  import { getNativeBinding } from "./native.js";
3
+ import { getFsSafeNativeConfig } from "./native-config.js";
4
+ import { warnNativeFallback } from "./native-fallback-warning.js";
3
5
  import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
6
+ import { readWindowsSecurityFactsCommand } from "./windows-security-command.js";
4
7
  export function readOwnerAndDacl(targetPath) {
5
8
  if (process.platform !== "win32") {
6
9
  return { status: "unsupported-platform", platform: process.platform };
7
10
  }
8
11
  assertNoWindowsPathAlias(targetPath, "filesystem", "owner and DACL path uses a Windows filesystem namespace alias");
9
12
  const native = getNativeBinding();
10
- if (!native) {
11
- throw new FsSafeError("helper-unavailable", "Windows owner and DACL facts require the matching optional native platform package; " +
12
- "install @openclaw/fs-safe with optional dependencies enabled on a supported platform and use FS_SAFE_NATIVE_MODE=auto or require");
13
+ const inspect = native?.readOwnerAndDacl;
14
+ if (typeof inspect !== "function") {
15
+ if (getFsSafeNativeConfig().mode === "require") {
16
+ throw new FsSafeError("helper-unavailable", "Windows owner and DACL facts require an up-to-date native helper");
17
+ }
18
+ warnNativeFallback("windows-owner-dacl", "Windows owner and DACL inspection uses a slower built-in system command.");
13
19
  }
14
- const facts = native.readOwnerAndDacl(targetPath);
20
+ const facts = typeof inspect === "function" ? inspect.call(native, targetPath) : readWindowsSecurityFactsCommand(targetPath);
15
21
  return {
16
22
  status: "supported",
17
23
  ownerSid: facts.ownerSid,
@@ -1 +1 @@
1
- {"version":3,"file":"path-prefix.d.ts","sourceRoot":"","sources":["../src/path-prefix.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD,CAAC;AAkBF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAsDvE"}
1
+ {"version":3,"file":"path-prefix.d.ts","sourceRoot":"","sources":["../src/path-prefix.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD,CAAC;AAuBF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAuEvE"}
@@ -19,15 +19,23 @@ function resolutionError(code, absolutePath) {
19
19
  code, syscall: "resolvePathPrefix", path: absolutePath,
20
20
  });
21
21
  }
22
+ // Leave ample room for ordinary shallow paths to retain the legacy small-array
23
+ // path. At 32 components, repeated front removal can reindex at most 496 array
24
+ // positions per constructed queue; longer queues use a forward cursor instead.
25
+ const SHIFT_QUEUE_COMPONENT_LIMIT = 32;
22
26
  export function resolvePathPrefixSync(input) {
23
27
  assertNoNulPathInput(input);
24
28
  const absolutePath = absolutePathWithRawSegments(input);
25
29
  let resolved = rawRoot(absolutePath);
26
- const remaining = absolutePath.slice(resolved.length).split(path.sep);
30
+ let remaining = absolutePath.slice(resolved.length).split(path.sep);
31
+ let shiftQueue = remaining.length <= SHIFT_QUEUE_COMPONENT_LIMIT;
32
+ let nextSegment = 0;
33
+ let remainingCount = remaining.length;
27
34
  const visitedStates = new Set();
28
35
  let symlinkHops = 0;
29
- while (remaining.length > 0) {
30
- const segment = remaining.shift();
36
+ while (remainingCount > 0) {
37
+ const segment = shiftQueue ? remaining.shift() : remaining[nextSegment++];
38
+ remainingCount--;
31
39
  if (segment === "")
32
40
  continue;
33
41
  if (segment === "." || segment === "..") {
@@ -51,32 +59,46 @@ export function resolvePathPrefixSync(input) {
51
59
  return {
52
60
  absolutePath,
53
61
  existingPath: realpathSync.native(pathForWindowsFilesystem(resolved)),
54
- unresolvedSegments: [segment, ...remaining],
62
+ unresolvedSegments: shiftQueue ? [segment, ...remaining] : remaining.slice(nextSegment - 1),
55
63
  };
56
64
  }
57
65
  if (!stat.isSymbolicLink()) {
58
- if (!stat.isDirectory() && remaining.length > 0)
66
+ if (!stat.isDirectory() && remainingCount > 0)
59
67
  throw resolutionError("ENOTDIR", absolutePath);
60
68
  resolved = candidate;
61
69
  continue;
62
70
  }
63
- const state = JSON.stringify([String(stat.dev), String(stat.ino), candidate, remaining]);
71
+ const pendingSuffix = shiftQueue ? remaining : remaining.slice(nextSegment);
72
+ const state = JSON.stringify([String(stat.dev), String(stat.ino), candidate, pendingSuffix]);
64
73
  if (symlinkHops >= 64 || visitedStates.has(state))
65
74
  throw resolutionError("ELOOP", absolutePath);
66
75
  visitedStates.add(state);
67
76
  symlinkHops++;
68
77
  const target = fs.readlinkSync(candidate);
69
78
  const rawTarget = path.sep === "\\" ? target.replaceAll("/", "\\") : target;
79
+ let targetSegments;
70
80
  if (path.isAbsolute(rawTarget)) {
71
81
  const targetRoot = rawRoot(rawTarget);
72
82
  // A rooted Windows link target uses the link's drive/share, not cwd's.
73
83
  resolved = path.sep === "\\" && targetRoot === "\\" ? rawRoot(resolved) : targetRoot;
74
- remaining.unshift(...rawTarget.slice(targetRoot.length).split(path.sep));
84
+ targetSegments = rawTarget.slice(targetRoot.length).split(path.sep);
75
85
  }
76
86
  else {
77
87
  // A target's parent traversal applies after resolving its preceding links.
78
- remaining.unshift(...rawTarget.split(path.sep));
88
+ targetSegments = rawTarget.split(path.sep);
79
89
  }
90
+ const expandedCount = targetSegments.length + pendingSuffix.length;
91
+ if (expandedCount <= SHIFT_QUEUE_COMPONENT_LIMIT) {
92
+ // The spread is bounded by the same fixed limit as subsequent shifts.
93
+ remaining = pendingSuffix;
94
+ remaining.unshift(...targetSegments);
95
+ }
96
+ else {
97
+ remaining = targetSegments.concat(pendingSuffix);
98
+ }
99
+ remainingCount = remaining.length;
100
+ shiftQueue = remainingCount <= SHIFT_QUEUE_COMPONENT_LIMIT;
101
+ nextSegment = 0;
80
102
  }
81
103
  return { absolutePath, existingPath: realpathSync.native(pathForWindowsFilesystem(resolved)), unresolvedSegments: [] };
82
104
  }
@@ -2,6 +2,8 @@ export type ProbePathSuffixAliasesOptions = {
2
2
  directory: string;
3
3
  left: string;
4
4
  right: string;
5
+ /** Maximum relative component count; defaults to 32. */
6
+ maxDepth?: number;
5
7
  /** Synchronous caller policy for differing NFC pairs not equivalent under ASCII case folding. */
6
8
  shouldProbeCaseVariants?: (leftNfc: string, rightNfc: string) => boolean;
7
9
  };
@@ -1 +1 @@
1
- {"version":3,"file":"path-suffix-aliases.d.ts","sourceRoot":"","sources":["../src/path-suffix-aliases.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,iGAAiG;IACjG,uBAAuB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1E,CAAC;AA6UF,4FAA4F;AAC5F,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,6BAA6B,GAAG,OAAO,GAAG,SAAS,CA8CtG"}
1
+ {"version":3,"file":"path-suffix-aliases.d.ts","sourceRoot":"","sources":["../src/path-suffix-aliases.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,uBAAuB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1E,CAAC;AAkVF,4FAA4F;AAC5F,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,6BAA6B,GAAG,OAAO,GAAG,SAAS,CAmDtG"}
@@ -15,6 +15,7 @@ const MAX_SUFFIX_DEPTH = 32;
15
15
  const MAX_MKDIR_ATTEMPTS = 128;
16
16
  const MAX_CREATED_DIRECTORIES = 64;
17
17
  const MAX_FORWARD_OBSERVATIONS = 4_096;
18
+ const MAX_SCALED_FORWARD_OBSERVATIONS = 32_768;
18
19
  const PROBE_NAME_LENGTH = 6;
19
20
  const PROBE_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
20
21
  const PROBE_FIRST_ALPHABET = "bdefghijkmoqrstuvwxyz";
@@ -25,7 +26,7 @@ function assertMutationPath(value) {
25
26
  if (value.length > MAX_PATH_LENGTH)
26
27
  unavailable();
27
28
  }
28
- function suffixSegments(value) {
29
+ function suffixSegments(value, maxDepth) {
29
30
  if (typeof value !== "string")
30
31
  throw new TypeError("suffix must be a string");
31
32
  if (value.length > MAX_SUFFIX_LENGTH)
@@ -35,8 +36,8 @@ function suffixSegments(value) {
35
36
  }
36
37
  const windows = process.platform === "win32";
37
38
  const segments = (windows ? value.replaceAll("/", "\\") : value).split(path.sep);
38
- if (segments.length > MAX_SUFFIX_DEPTH)
39
- throw new RangeError("suffix exceeds 32 components");
39
+ if (segments.length > maxDepth)
40
+ throw new RangeError(`suffix exceeds ${maxDepth} components`);
40
41
  if (segments.some(segment => !segment || segment === "." || segment === ".." ||
41
42
  (windows && (segment.includes(":") || /^[ .]+$/u.test(segment) ||
42
43
  isWindowsReservedDeviceName(segment))))) {
@@ -96,14 +97,8 @@ function createPrivateProbeName(nameLength) {
96
97
  return name;
97
98
  }
98
99
  function* asciiCaseProbePairs(nameLength, forbidden) {
99
- let count = 0;
100
- for (let attempt = 0; attempt < 96 && count < 24; attempt++) {
101
- const first = createPrivateProbeName(nameLength);
102
- const second = `${first[0].toUpperCase()}${first.slice(1)}`;
103
- if (!forbidden(first) && !forbidden(second)) {
104
- count++;
105
- yield [first, second];
106
- }
100
+ for (const first of privateProbeNames(nameLength, forbidden)) {
101
+ yield [first, `${first[0].toUpperCase()}${first.slice(1)}`];
107
102
  }
108
103
  }
109
104
  function* privateProbeNames(nameLength, forbidden) {
@@ -128,8 +123,16 @@ class ProbeDirectories {
128
123
  observations = 0;
129
124
  mkdirAttempts = 0;
130
125
  creations = 0;
131
- constructor(requestedDirectory) {
126
+ maxObservations;
127
+ maxMkdirAttempts;
128
+ maxCreations;
129
+ constructor(requestedDirectory, depth) {
132
130
  this.requestedDirectory = requestedDirectory;
131
+ // The suffix-length limit bounds actual depth, so these products remain safe integers.
132
+ const scale = Math.max(1, depth / MAX_SUFFIX_DEPTH);
133
+ this.maxObservations = Math.min(MAX_SCALED_FORWARD_OBSERVATIONS, MAX_FORWARD_OBSERVATIONS * scale * scale);
134
+ this.maxMkdirAttempts = MAX_MKDIR_ATTEMPTS * scale;
135
+ this.maxCreations = MAX_CREATED_DIRECTORIES * scale;
133
136
  this.observe(1);
134
137
  const canonical = realpathSync.native(pathForWindowsFilesystem(requestedDirectory));
135
138
  assertMutationPath(canonical);
@@ -138,7 +141,7 @@ class ProbeDirectories {
138
141
  this.assert(this.root);
139
142
  }
140
143
  reserveObservations(units) {
141
- if (this.observations + units > MAX_FORWARD_OBSERVATIONS)
144
+ if (units > this.maxObservations - this.observations)
142
145
  unavailable();
143
146
  }
144
147
  observe(units, cleanup = false) {
@@ -159,7 +162,7 @@ class ProbeDirectories {
159
162
  }
160
163
  }
161
164
  create(parent, name) {
162
- if (this.mkdirAttempts >= MAX_MKDIR_ATTEMPTS || this.creations >= MAX_CREATED_DIRECTORIES)
165
+ if (this.mkdirAttempts >= this.maxMkdirAttempts || this.creations >= this.maxCreations)
163
166
  unavailable();
164
167
  const probePath = path.join(parent.path, name);
165
168
  assertMutationPath(probePath);
@@ -337,11 +340,16 @@ export function probePathSuffixAliasesSync(options) {
337
340
  const directory = resolvePathPreservingWindowsRoot(requestedDirectory);
338
341
  if (directory.length > MAX_PATH_LENGTH)
339
342
  throw new RangeError("resolved directory exceeds 32768 code units");
343
+ const requestedMaxDepth = options.maxDepth;
344
+ const maxDepth = requestedMaxDepth === undefined ? MAX_SUFFIX_DEPTH : requestedMaxDepth;
345
+ if (!Number.isSafeInteger(maxDepth) || maxDepth < 0) {
346
+ throw new RangeError("maxDepth must be a non-negative safe integer");
347
+ }
340
348
  const leftInput = options.left;
341
349
  const rightInput = options.right;
342
350
  const predicate = options.shouldProbeCaseVariants;
343
- const left = suffixSegments(leftInput);
344
- const right = suffixSegments(rightInput);
351
+ const left = suffixSegments(leftInput, maxDepth);
352
+ const right = suffixSegments(rightInput, maxDepth);
345
353
  if (left.length !== right.length)
346
354
  throw new TypeError("suffixes must have the same component count");
347
355
  if (predicate !== undefined && typeof predicate !== "function") {
@@ -370,7 +378,7 @@ export function probePathSuffixAliasesSync(options) {
370
378
  let observed;
371
379
  let cleaned = true;
372
380
  try {
373
- observed = observeSuffixes(() => owner ??= new ProbeDirectories(directory), left, right, shouldProbe);
381
+ observed = observeSuffixes(() => owner ??= new ProbeDirectories(directory, left.length), left, right, shouldProbe);
374
382
  owner?.assert(owner.root);
375
383
  }
376
384
  catch {
@@ -8,6 +8,8 @@ export type PermissionCommandFailure = {
8
8
  stderr: string;
9
9
  };
10
10
  export declare function formatPermissionErrorDetail(value: string): string;
11
+ /** Formats only caught permission-query failures without invoking user code. */
12
+ export declare function formatCaughtPermissionFailure(error: unknown): string;
11
13
  export declare class PermissionCommandError extends Error implements PermissionCommandFailure {
12
14
  readonly command: string;
13
15
  readonly durationMs: number;
@@ -1 +1 @@
1
- {"version":3,"file":"permission-exec.d.ts","sourceRoot":"","sources":["../src/permission-exec.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,kCAAkC,QAAS,CAAC;AAEzD,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjE;AAgBD,qBAAa,sBAAuB,SAAQ,KAAM,YAAW,wBAAwB;IACnF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YACE,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,OAAO,EACd,SAAS,SAAqC,EAc/C;CACF;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,wBAAwB,GAAG,SAAS,CAgBtC;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,SAAqC,GAC7C,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAa7C"}
1
+ {"version":3,"file":"permission-exec.d.ts","sourceRoot":"","sources":["../src/permission-exec.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,kCAAkC,QAAS,CAAC;AAEzD,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjE;AA4ED,gFAAgF;AAChF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAqBpE;AA2CD,qBAAa,sBAAuB,SAAQ,KAAM,YAAW,wBAAwB;IACnF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YACE,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,OAAO,EACd,SAAS,SAAqC,EAc/C;CACF;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,wBAAwB,GAAG,SAAS,CAgCtC;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,SAAqC,GAC7C,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAa7C"}
@@ -1,6 +1,6 @@
1
1
  import { execFile } from "node:child_process";
2
2
  import path from "node:path";
3
- import { promisify } from "node:util";
3
+ import { promisify, types as utilTypes } from "node:util";
4
4
  import { formatErrorDetail } from "./error-detail.js";
5
5
  const execFileAsync = promisify(execFile);
6
6
  export const DEFAULT_PERMISSION_EXEC_TIMEOUT_MS = 30_000;
@@ -8,15 +8,127 @@ export function formatPermissionErrorDetail(value) {
8
8
  const formatted = formatErrorDetail(value);
9
9
  return formatted.length > 400 ? `${formatted.slice(0, 399)}…` : formatted;
10
10
  }
11
+ const MISSING_DATA_PROPERTY = Object.freeze({ found: false });
12
+ const MAX_CAUGHT_FAILURE_PROTOTYPES = 4;
13
+ const primitiveString = String;
14
+ const isUint8Array = utilTypes.isUint8Array;
15
+ const Uint8ArrayIntrinsic = Uint8Array;
16
+ const typedArrayPrototype = Object.getPrototypeOf(Uint8ArrayIntrinsic.prototype);
17
+ const typedArrayBufferGetter = Object.getOwnPropertyDescriptor(typedArrayPrototype, "buffer").get;
18
+ const typedArrayByteOffsetGetter = Object.getOwnPropertyDescriptor(typedArrayPrototype, "byteOffset").get;
19
+ const typedArrayByteLengthGetter = Object.getOwnPropertyDescriptor(typedArrayPrototype, "byteLength").get;
20
+ const typedArraySet = Object.getOwnPropertyDescriptor(typedArrayPrototype, "set").value;
21
+ const textDecoderDecode = TextDecoder.prototype.decode;
22
+ const stderrDecoder = new TextDecoder("utf-8", {
23
+ fatal: false,
24
+ ignoreBOM: true,
25
+ });
26
+ const MAX_STDERR_BYTES = 1600;
27
+ function isInspectableCaughtObject(value) {
28
+ if ((typeof value !== "object" || value === null) && typeof value !== "function") {
29
+ return false;
30
+ }
31
+ try {
32
+ return !utilTypes.isProxy(value);
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ function dataProperty(value, name) {
39
+ if (!isInspectableCaughtObject(value))
40
+ return MISSING_DATA_PROPERTY;
41
+ let current = value;
42
+ for (let depth = 0; current !== null && depth < MAX_CAUGHT_FAILURE_PROTOTYPES; depth += 1) {
43
+ if (!isInspectableCaughtObject(current))
44
+ return MISSING_DATA_PROPERTY;
45
+ let descriptor;
46
+ try {
47
+ descriptor = Object.getOwnPropertyDescriptor(current, name);
48
+ }
49
+ catch {
50
+ return MISSING_DATA_PROPERTY;
51
+ }
52
+ if (descriptor) {
53
+ return Object.hasOwn(descriptor, "value")
54
+ ? { found: true, value: descriptor.value }
55
+ : MISSING_DATA_PROPERTY;
56
+ }
57
+ try {
58
+ current = Object.getPrototypeOf(current);
59
+ }
60
+ catch {
61
+ return MISSING_DATA_PROPERTY;
62
+ }
63
+ }
64
+ return MISSING_DATA_PROPERTY;
65
+ }
66
+ function caughtPrimitiveDisplay(value) {
67
+ if (value !== null && (typeof value === "object" || typeof value === "function"))
68
+ return undefined;
69
+ return primitiveString(value);
70
+ }
71
+ /** Formats only caught permission-query failures without invoking user code. */
72
+ export function formatCaughtPermissionFailure(error) {
73
+ const primitive = caughtPrimitiveDisplay(error);
74
+ if (primitive !== undefined)
75
+ return formatBoundedCaughtDetail(primitive);
76
+ if (!isInspectableCaughtObject(error)) {
77
+ return "Uninspectable proxy failure";
78
+ }
79
+ const message = dataProperty(error, "message");
80
+ const name = dataProperty(error, "name");
81
+ const rawMessage = message.found && typeof message.value === "string"
82
+ ? message.value : "";
83
+ const rawName = name.found && typeof name.value === "string"
84
+ ? name.value : "";
85
+ const messageText = rawMessage.slice(0, 400);
86
+ const nameText = rawName.slice(0, 400);
87
+ const display = messageText
88
+ ? (nameText ? `${nameText}: ${messageText}` : messageText)
89
+ : nameText || (typeof error === "function" ? "Unknown function failure" : "Unknown object failure");
90
+ return formatBoundedCaughtDetail(display, rawMessage.length > messageText.length || rawName.length > nameText.length);
91
+ }
92
+ function formatBoundedCaughtDetail(value, alreadyTruncated = false) {
93
+ const inputWasTruncated = alreadyTruncated || value.length > 400;
94
+ const formatted = formatPermissionErrorDetail(value.slice(0, 400));
95
+ if (!inputWasTruncated || formatted.endsWith("…"))
96
+ return formatted;
97
+ return `${formatted.slice(0, 399)}…`;
98
+ }
99
+ function safeStderr(value) {
100
+ if (typeof value === "string")
101
+ return formatBoundedCaughtDetail(value);
102
+ try {
103
+ if (!isUint8Array(value))
104
+ return "";
105
+ const backing = Reflect.apply(typedArrayBufferGetter, value, []);
106
+ const byteOffset = Reflect.apply(typedArrayByteOffsetGetter, value, []);
107
+ const byteLength = Reflect.apply(typedArrayByteLengthGetter, value, []);
108
+ const copiedByteLength = byteLength < MAX_STDERR_BYTES
109
+ ? byteLength : MAX_STDERR_BYTES;
110
+ const source = new Uint8ArrayIntrinsic(backing, byteOffset, copiedByteLength);
111
+ const copy = new Uint8ArrayIntrinsic(copiedByteLength);
112
+ Reflect.apply(typedArraySet, copy, [source, 0]);
113
+ const decoded = Reflect.apply(textDecoderDecode, stderrDecoder, [copy]);
114
+ return formatBoundedCaughtDetail(decoded, byteLength > copiedByteLength);
115
+ }
116
+ catch {
117
+ return "";
118
+ }
119
+ }
11
120
  function commandFailureFields(error) {
12
- const fields = error && typeof error === "object" ? error : {};
121
+ const killed = dataProperty(error, "killed");
122
+ const code = dataProperty(error, "code");
123
+ const signal = dataProperty(error, "signal");
124
+ const stderr = dataProperty(error, "stderr");
13
125
  return {
14
- timedOut: "killed" in fields && fields.killed === true &&
15
- "signal" in fields && fields.signal === "SIGKILL",
16
- exitCode: "code" in fields && typeof fields.code === "number" ? fields.code : null,
17
- signal: "signal" in fields && typeof fields.signal === "string" ? fields.signal : null,
18
- stderr: formatPermissionErrorDetail("stderr" in fields && (typeof fields.stderr === "string" || Buffer.isBuffer(fields.stderr))
19
- ? fields.stderr.toString() : ""),
126
+ found: killed.found || code.found || signal.found || stderr.found,
127
+ timedOut: killed.found && killed.value === true &&
128
+ signal.found && signal.value === "SIGKILL",
129
+ exitCode: code.found && typeof code.value === "number" ? code.value : null,
130
+ signal: signal.found && typeof signal.value === "string" ? signal.value : null,
131
+ stderr: stderr.found ? safeStderr(stderr.value) : "",
20
132
  };
21
133
  }
22
134
  export class PermissionCommandError extends Error {
@@ -41,21 +153,38 @@ export class PermissionCommandError extends Error {
41
153
  }
42
154
  }
43
155
  export function getPermissionCommandFailure(error, command, durationMs) {
44
- if (error instanceof PermissionCommandError) {
45
- return {
46
- command: error.command,
47
- durationMs: error.durationMs,
48
- timedOut: error.timedOut,
49
- exitCode: error.exitCode,
50
- signal: error.signal,
51
- stderr: error.stderr,
52
- };
156
+ if (isInspectableCaughtObject(error) && utilTypes.isNativeError(error)) {
157
+ const name = dataProperty(error, "name");
158
+ if (name.found && name.value === "PermissionCommandError") {
159
+ const wrappedCommand = dataProperty(error, "command");
160
+ const wrappedDuration = dataProperty(error, "durationMs");
161
+ const wrappedTimedOut = dataProperty(error, "timedOut");
162
+ const wrappedExitCode = dataProperty(error, "exitCode");
163
+ const wrappedSignal = dataProperty(error, "signal");
164
+ const wrappedStderr = dataProperty(error, "stderr");
165
+ if (wrappedCommand.found && typeof wrappedCommand.value === "string" &&
166
+ wrappedDuration.found && typeof wrappedDuration.value === "number" &&
167
+ Number.isSafeInteger(wrappedDuration.value) && wrappedDuration.value >= 0 &&
168
+ wrappedTimedOut.found && typeof wrappedTimedOut.value === "boolean" &&
169
+ wrappedExitCode.found && (wrappedExitCode.value === null || typeof wrappedExitCode.value === "number") &&
170
+ wrappedSignal.found && (wrappedSignal.value === null || typeof wrappedSignal.value === "string") &&
171
+ wrappedStderr.found) {
172
+ return {
173
+ command: wrappedCommand.value,
174
+ durationMs: wrappedDuration.value,
175
+ timedOut: wrappedTimedOut.value,
176
+ exitCode: wrappedExitCode.value,
177
+ signal: wrappedSignal.value,
178
+ stderr: safeStderr(wrappedStderr.value),
179
+ };
180
+ }
181
+ }
53
182
  }
54
- if (!error || typeof error !== "object" ||
55
- !("code" in error || "signal" in error || "killed" in error || "stderr" in error)) {
183
+ const fields = commandFailureFields(error);
184
+ if (!fields.found)
56
185
  return undefined;
57
- }
58
- return { command, durationMs: Math.round(durationMs), ...commandFailureFields(error) };
186
+ const { found: _found, ...detail } = fields;
187
+ return { command, durationMs: Math.round(durationMs), ...detail };
59
188
  }
60
189
  export async function executePermissionCommand(command, args, timeoutMs = DEFAULT_PERMISSION_EXEC_TIMEOUT_MS) {
61
190
  const startedAt = performance.now();
@@ -96,7 +96,7 @@ export async function inspectWindowsPermissions(params) {
96
96
  env: params.opts?.env,
97
97
  exec: params.opts?.exec ?? defaultPermissionExec,
98
98
  });
99
- if (owner.error) {
99
+ if (owner.error !== undefined) {
100
100
  const error = `Windows owner inspection failed: ${owner.error}`;
101
101
  return { ...unverified, ownerError: owner.error, error, errorDetail: owner.errorDetail, errorCause: owner.errorCause };
102
102
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pinned-mutation-admission.d.ts","sourceRoot":"","sources":["../src/pinned-mutation-admission.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGvF,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,KAAK,EAKV,4BAA4B,EAC7B,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAgCtE,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;CAC1C,CAAC,CAAC;AAEH,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,kBAAkB,GAAG,SAAS,EAC7C,gBAAgB,EAAE,qBAAqB,GAAG,SAAS,GAClD,4BAA4B,GAAG,SAAS,CAO1C;AAuJD,wBAAsB,mCAAmC,CAAC,MAAM,EAAE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yBAAyB,EAAE,MAAM,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,4BAA4B,GAAG,SAAS,CAAC;IACjD,cAAc,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD,GAAG,OAAO,CAAC;IACV,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;CAClD,CAAC,CA2PD"}
1
+ {"version":3,"file":"pinned-mutation-admission.d.ts","sourceRoot":"","sources":["../src/pinned-mutation-admission.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGvF,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,KAAK,EAKV,4BAA4B,EAC7B,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAgCtE,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;CAC1C,CAAC,CAAC;AAEH,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,kBAAkB,GAAG,SAAS,EAC7C,gBAAgB,EAAE,qBAAqB,GAAG,SAAS,GAClD,4BAA4B,GAAG,SAAS,CAO1C;AAuJD,wBAAsB,mCAAmC,CAAC,MAAM,EAAE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yBAAyB,EAAE,MAAM,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,4BAA4B,GAAG,SAAS,CAAC;IACjD,cAAc,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD,GAAG,OAAO,CAAC;IACV,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;CAClD,CAAC,CAgQD"}
@@ -165,6 +165,10 @@ export async function preparePinnedWriteMutationAdmission(params) {
165
165
  selectedTarget: params.resolvedTargetPath,
166
166
  policy,
167
167
  });
168
+ const nativeRoute = sharedRoute ?? (process.platform === "win32" && params.originalPath?.includes("/")
169
+ ? simpleSharedRoute({ rootReal: params.rootReal, rootIdentity: params.rootIdentity,
170
+ originalPath: params.originalPath.replaceAll("/", "\\"), selectedTarget: params.resolvedTargetPath, policy })
171
+ : undefined);
168
172
  let pinnedSession;
169
173
  let epoch;
170
174
  let pending;
@@ -194,13 +198,13 @@ export async function preparePinnedWriteMutationAdmission(params) {
194
198
  }
195
199
  return current;
196
200
  };
197
- const beginSharedParentWalk = sharedRoute ? () => {
201
+ const createSharedParentWalk = (admittedRoute) => {
198
202
  const session = Object.freeze({
199
203
  kind: "shared",
200
- route: sharedRoute.route,
204
+ route: admittedRoute.route,
201
205
  selectedTarget: params.resolvedTargetPath,
202
206
  nativeMode: getFsSafeNativeConfig().mode,
203
- rootIdentity: sharedRoute.rootIdentity,
207
+ rootIdentity: admittedRoute.rootIdentity,
204
208
  authorizationToken: Object.freeze({}),
205
209
  });
206
210
  let disposed = false;
@@ -314,7 +318,7 @@ export async function preparePinnedWriteMutationAdmission(params) {
314
318
  disable();
315
319
  },
316
320
  });
317
- } : undefined;
321
+ };
318
322
  const mutationAdmission = Object.freeze({
319
323
  rejectParentSymlinks: policy.mutationSymlinks === "reject",
320
324
  beginParentWalk: route ? () => {
@@ -329,7 +333,8 @@ export async function preparePinnedWriteMutationAdmission(params) {
329
333
  pending = undefined;
330
334
  return route;
331
335
  } : undefined,
332
- beginSharedParentWalk,
336
+ beginSharedParentWalk: sharedRoute ? () => createSharedParentWalk(sharedRoute) : undefined,
337
+ beginNativeParentWalk: nativeRoute ? () => createSharedParentWalk(nativeRoute) : undefined,
333
338
  tryAuthorizeAtParent(request, parent) {
334
339
  pending = undefined;
335
340
  const reusable = epoch;
@@ -30,7 +30,6 @@ export type MutationPathObservation = Readonly<{
30
30
  export declare function missingMutationSegments(observation: MutationPathObservation): number;
31
31
  export declare function nextMissingMutationPath(observation: MutationPathObservation): string | undefined;
32
32
  export declare function checkedMutationDirectory(pathname: string, canonicalPath: string, stat: Pick<BigIntStats, "dev" | "ino" | "mode" | "nlink">, observeCurrent?: MutationDirectoryObserver): MutationDirectoryObservation;
33
- export declare function mutationDirectoryObservationCurrent(observation: MutationDirectoryObservation): boolean;
34
33
  export declare function mutationObservationUsesDirectory(observation: MutationPathObservation, directory: MutationDirectoryObservation): boolean;
35
34
  export declare function observeMutationPath(pathname: string): MutationPathObservation | undefined;
36
35
  export declare function mutationObservationCurrent(observation: MutationPathObservation): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"pinned-mutation-observation.d.ts","sourceRoot":"","sources":["../src/pinned-mutation-observation.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAM/C,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH,QAAA,MAAM,2BAA2B,eAAmD,CAAC;AAGrF,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,CAAC,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,MAAM,wBAAwB,GAAG,SAAS,CAAC;AAEnF,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,CAAC,2BAA2B,CAAC,EAAE,IAAI,CAAC;CACrC,CAAC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AA6BH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,uBAAuB,GAAG,MAAM,CAEpF;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,uBAAuB,GAAG,MAAM,GAAG,SAAS,CAGhG;AAKD,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,EACzD,cAAc,CAAC,EAAE,yBAAyB,GACzC,4BAA4B,CAY9B;AAQD,wBAAgB,mCAAmC,CACjD,WAAW,EAAE,4BAA4B,GACxC,OAAO,CAgBT;AAED,wBAAgB,gCAAgC,CAC9C,WAAW,EAAE,uBAAuB,EACpC,SAAS,EAAE,4BAA4B,GACtC,OAAO,CAMT;AAGD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS,CA0BzF;AAED,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,uBAAuB,GAAG,OAAO,CAaxF;AAKD,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,SAAS,uBAAuB,EAAE,EAChD,WAAW,EAAE,SAAS,4BAA4B,EAAE,GACnD,OAAO,CAiET;AAID,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,uBAAuB,EACpC,MAAM,EAAE,4BAA4B,EACpC,KAAK,EAAE,4BAA4B,GAClC,uBAAuB,GAAG,SAAS,CAiBrC"}
1
+ {"version":3,"file":"pinned-mutation-observation.d.ts","sourceRoot":"","sources":["../src/pinned-mutation-observation.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAM/C,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH,QAAA,MAAM,2BAA2B,eAAmD,CAAC;AAGrF,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,CAAC,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,MAAM,wBAAwB,GAAG,SAAS,CAAC;AAEnF,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,CAAC,2BAA2B,CAAC,EAAE,IAAI,CAAC;CACrC,CAAC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AA6BH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,uBAAuB,GAAG,MAAM,CAEpF;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,uBAAuB,GAAG,MAAM,GAAG,SAAS,CAGhG;AAKD,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,EACzD,cAAc,CAAC,EAAE,yBAAyB,GACzC,4BAA4B,CAY9B;AAQD,wBAAgB,gCAAgC,CAC9C,WAAW,EAAE,uBAAuB,EACpC,SAAS,EAAE,4BAA4B,GACtC,OAAO,CAMT;AAGD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS,CA0BzF;AAED,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,uBAAuB,GAAG,OAAO,CAaxF;AAKD,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,SAAS,uBAAuB,EAAE,EAChD,WAAW,EAAE,SAAS,4BAA4B,EAAE,GACnD,OAAO,CAiET;AAID,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,uBAAuB,EACpC,MAAM,EAAE,4BAA4B,EACpC,KAAK,EAAE,4BAA4B,GAClC,uBAAuB,GAAG,SAAS,CAiBrC"}
@@ -54,25 +54,6 @@ function checkedDirectory(observation) {
54
54
  path.isAbsolute(observation.path) && path.isAbsolute(observation.canonicalPath) &&
55
55
  directoryMode(observation.identity.mode);
56
56
  }
57
- export function mutationDirectoryObservationCurrent(observation) {
58
- if (!checkedDirectory(observation))
59
- return false;
60
- try {
61
- const observed = directoryObservers.get(observation)?.();
62
- if (observed) {
63
- return directoryMode(observed.identity.mode) &&
64
- sameIdentity(observation.identity, observed.identity) &&
65
- observed.canonicalPath === observation.canonicalPath;
66
- }
67
- const stat = inspectFileIdentitySync(() => fs.lstatSync(observation.path, { bigint: true }));
68
- return stat.isDirectory() && !stat.isSymbolicLink() &&
69
- sameIdentity(observation.identity, stat) &&
70
- realpathSync.native(observation.path) === observation.canonicalPath;
71
- }
72
- catch {
73
- return false;
74
- }
75
- }
76
57
  export function mutationObservationUsesDirectory(observation, directory) {
77
58
  return checkedDirectory(directory) &&
78
59
  observation.ancestor === directory.path &&
@@ -9,6 +9,7 @@ type SharedMutationPolicy = Readonly<{
9
9
  denyMutations?: DenyMutationPolicy;
10
10
  mutationSymlinks?: MutationSymlinkPolicy;
11
11
  }>;
12
+ export declare function ordinaryWindowsSegments(relativePath: string): boolean;
12
13
  export declare function ordinarySharedAbsoluteInsideRoot(rootReal: string, candidatePath: string, rootIdentity: ExactRootIdentity): boolean;
13
14
  export declare function simpleSharedRoute(params: {
14
15
  rootReal: string;
@@ -1 +1 @@
1
- {"version":3,"file":"pinned-mutation-shared-route.d.ts","sourceRoot":"","sources":["../src/pinned-mutation-shared-route.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAG9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEtE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEvE,KAAK,oBAAoB,GAAG,QAAQ,CAAC;IACnC,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;CAC1C,CAAC,CAAC;AA+BH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,iBAAiB,GAC9B,OAAO,CAeT;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,oBAAoB,CAAC;CAC9B,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,iBAAiB,CAAA;CAAE,GAAG,SAAS,CAqBjE"}
1
+ {"version":3,"file":"pinned-mutation-shared-route.d.ts","sourceRoot":"","sources":["../src/pinned-mutation-shared-route.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAG9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEtE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEvE,KAAK,oBAAoB,GAAG,QAAQ,CAAC;IACnC,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;CAC1C,CAAC,CAAC;AAQH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAMrE;AAiBD,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,iBAAiB,GAC9B,OAAO,CAeT;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,oBAAoB,CAAC;CAC9B,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,iBAAiB,CAAA;CAAE,GAAG,SAAS,CAqBjE"}
@@ -7,7 +7,7 @@ function windowsReservedDeviceSegment(segment) {
7
7
  const stem = segment.slice(0, extension < 0 ? segment.length : extension).toUpperCase();
8
8
  return WINDOWS_RESERVED_DEVICE_NAMES.has(stem);
9
9
  }
10
- function ordinaryWindowsSegments(relativePath) {
10
+ export function ordinaryWindowsSegments(relativePath) {
11
11
  if (relativePath === "" || relativePath.includes("/") || relativePath.includes("\0"))
12
12
  return false;
13
13
  const segments = relativePath.split("\\");
@@ -0,0 +1,4 @@
1
+ import type { FileHandle } from "node:fs/promises";
2
+ import type { PinnedWriteInput } from "./pinned-write-types.js";
3
+ export declare function writePinnedInput(target: FileHandle | number, input: PinnedWriteInput, maxBytes?: number, assertBeforeMutation?: () => void): Promise<void>;
4
+ //# sourceMappingURL=pinned-write-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pinned-write-input.d.ts","sourceRoot":"","sources":["../src/pinned-write-input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,GAAG,MAAM,EAC3B,KAAK,EAAE,gBAAgB,EACvB,QAAQ,CAAC,EAAE,MAAM,EACjB,oBAAoB,CAAC,EAAE,MAAM,IAAI,GAChC,OAAO,CAAC,IAAI,CAAC,CAoBf"}
@@ -0,0 +1,25 @@
1
+ import { writeCopyFileToFd } from "./copy-file-input.js";
2
+ import { FsSafeError } from "./errors.js";
3
+ import { writeAllToFile } from "./write-file-handle.js";
4
+ export async function writePinnedInput(target, input, maxBytes, assertBeforeMutation) {
5
+ if (input.kind === "file") {
6
+ await writeCopyFileToFd(typeof target === "number" ? target : target.fd, input, maxBytes, assertBeforeMutation);
7
+ return;
8
+ }
9
+ let bytes = 0;
10
+ const write = async (data) => {
11
+ bytes += data.byteLength;
12
+ if (maxBytes !== undefined && bytes > maxBytes) {
13
+ throw new FsSafeError("too-large", `file exceeds limit of ${maxBytes} bytes (got at least ${bytes})`);
14
+ }
15
+ await writeAllToFile(target, data, { assertBeforeMutation });
16
+ };
17
+ if (input.kind === "buffer") {
18
+ await write(typeof input.data === "string" ? Buffer.from(input.data, input.encoding ?? "utf8") : input.data);
19
+ }
20
+ else {
21
+ for await (const chunk of input.stream) {
22
+ await write(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,5 @@
1
+ import type { FileHandle } from "node:fs/promises";
2
+ export declare function assertPinnedWriteMode(fd: number, mode: number): void;
3
+ export declare function preparePinnedWriteMode(handle: FileHandle, createdMode: number, assertBeforeMutation?: () => void): Promise<(() => void) | undefined>;
4
+ export declare function pinnedWriteModeAssertion(fd: number, mode: number, assertBeforeMutation?: () => void): () => void;
5
+ //# sourceMappingURL=pinned-write-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pinned-write-mode.d.ts","sourceRoot":"","sources":["../src/pinned-write-mode.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAKpE;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,MAAM,EACnB,oBAAoB,CAAC,EAAE,MAAM,IAAI,GAChC,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC,CAKnC;AAED,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,oBAAoB,CAAC,EAAE,MAAM,IAAI,GAChC,MAAM,IAAI,CAKZ"}