@vibe-agent-toolkit/utils 0.2.0-rc.11 → 0.2.0-rc.12

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 (322) hide show
  1. package/README.md +111 -9
  2. package/dist/archive/archive.d.ts +129 -0
  3. package/dist/archive/archive.d.ts.map +1 -0
  4. package/dist/archive/archive.js +223 -0
  5. package/dist/archive/archive.js.map +1 -0
  6. package/dist/archive/entries.d.ts +132 -0
  7. package/dist/archive/entries.d.ts.map +1 -0
  8. package/dist/archive/entries.js +223 -0
  9. package/dist/archive/entries.js.map +1 -0
  10. package/dist/archive/limits.d.ts +39 -0
  11. package/dist/archive/limits.d.ts.map +1 -0
  12. package/dist/archive/limits.js +59 -0
  13. package/dist/archive/limits.js.map +1 -0
  14. package/dist/archive/records.d.ts +14 -0
  15. package/dist/archive/records.d.ts.map +1 -0
  16. package/dist/archive/records.js +3 -0
  17. package/dist/archive/records.js.map +1 -0
  18. package/dist/archive/tar-reader.d.ts +18 -0
  19. package/dist/archive/tar-reader.d.ts.map +1 -0
  20. package/dist/archive/tar-reader.js +173 -0
  21. package/dist/archive/tar-reader.js.map +1 -0
  22. package/dist/archive/zip-reader.d.ts +76 -0
  23. package/dist/archive/zip-reader.d.ts.map +1 -0
  24. package/dist/archive/zip-reader.js +376 -0
  25. package/dist/archive/zip-reader.js.map +1 -0
  26. package/dist/archive.d.ts +14 -0
  27. package/dist/archive.d.ts.map +1 -0
  28. package/dist/archive.js +12 -0
  29. package/dist/archive.js.map +1 -0
  30. package/dist/asset-reference.d.ts +17 -1
  31. package/dist/asset-reference.d.ts.map +1 -1
  32. package/dist/asset-reference.js +31 -7
  33. package/dist/asset-reference.js.map +1 -1
  34. package/dist/dirent-kind.d.ts +13 -40
  35. package/dist/dirent-kind.d.ts.map +1 -1
  36. package/dist/dirent-kind.js +21 -69
  37. package/dist/dirent-kind.js.map +1 -1
  38. package/dist/entrypoint.d.ts +2 -2
  39. package/dist/entrypoint.d.ts.map +1 -1
  40. package/dist/entrypoint.js +4 -3
  41. package/dist/entrypoint.js.map +1 -1
  42. package/dist/env-flag.d.ts +2 -0
  43. package/dist/env-flag.d.ts.map +1 -1
  44. package/dist/env-flag.js +2 -0
  45. package/dist/env-flag.js.map +1 -1
  46. package/dist/errors/confirmed-absent.d.ts +41 -0
  47. package/dist/errors/confirmed-absent.d.ts.map +1 -0
  48. package/dist/errors/confirmed-absent.js +43 -0
  49. package/dist/errors/confirmed-absent.js.map +1 -0
  50. package/dist/errors/errno-table.d.ts +177 -0
  51. package/dist/errors/errno-table.d.ts.map +1 -0
  52. package/dist/errors/errno-table.js +343 -0
  53. package/dist/errors/errno-table.js.map +1 -0
  54. package/dist/errors/fs-boundary.d.ts +36 -0
  55. package/dist/errors/fs-boundary.d.ts.map +1 -0
  56. package/dist/errors/fs-boundary.js +121 -0
  57. package/dist/errors/fs-boundary.js.map +1 -0
  58. package/dist/errors/fs-fault.d.ts +176 -0
  59. package/dist/errors/fs-fault.d.ts.map +1 -0
  60. package/dist/errors/fs-fault.js +215 -0
  61. package/dist/errors/fs-fault.js.map +1 -0
  62. package/dist/errors/git-errno.d.ts +13 -0
  63. package/dist/errors/git-errno.d.ts.map +1 -0
  64. package/dist/errors/git-errno.js +45 -0
  65. package/dist/errors/git-errno.js.map +1 -0
  66. package/dist/errors/path-present.d.ts +72 -0
  67. package/dist/errors/path-present.d.ts.map +1 -0
  68. package/dist/errors/path-present.js +110 -0
  69. package/dist/errors/path-present.js.map +1 -0
  70. package/dist/errors/rag-index-empty.d.ts +16 -0
  71. package/dist/errors/rag-index-empty.d.ts.map +1 -0
  72. package/dist/errors/rag-index-empty.js +16 -0
  73. package/dist/errors/rag-index-empty.js.map +1 -0
  74. package/dist/errors/suppressed-faults.d.ts +34 -0
  75. package/dist/errors/suppressed-faults.d.ts.map +1 -0
  76. package/dist/errors/suppressed-faults.js +66 -0
  77. package/dist/errors/suppressed-faults.js.map +1 -0
  78. package/dist/file-crawler.d.ts +13 -18
  79. package/dist/file-crawler.d.ts.map +1 -1
  80. package/dist/file-crawler.js +140 -24
  81. package/dist/file-crawler.js.map +1 -1
  82. package/dist/fs-utils.d.ts +75 -50
  83. package/dist/fs-utils.d.ts.map +1 -1
  84. package/dist/fs-utils.js +148 -158
  85. package/dist/fs-utils.js.map +1 -1
  86. package/dist/fs.d.ts +4 -4
  87. package/dist/fs.d.ts.map +1 -1
  88. package/dist/fs.js +4 -4
  89. package/dist/fs.js.map +1 -1
  90. package/dist/git-snapshot.d.ts +25 -17
  91. package/dist/git-snapshot.d.ts.map +1 -1
  92. package/dist/git-snapshot.js +65 -11
  93. package/dist/git-snapshot.js.map +1 -1
  94. package/dist/git-tracker.d.ts +11 -3
  95. package/dist/git-tracker.d.ts.map +1 -1
  96. package/dist/git-tracker.js +29 -6
  97. package/dist/git-tracker.js.map +1 -1
  98. package/dist/git-utils.d.ts.map +1 -1
  99. package/dist/git-utils.js +7 -35
  100. package/dist/git-utils.js.map +1 -1
  101. package/dist/git.d.ts +1 -1
  102. package/dist/git.d.ts.map +1 -1
  103. package/dist/git.js +1 -1
  104. package/dist/git.js.map +1 -1
  105. package/dist/gitignore-checker.d.ts.map +1 -1
  106. package/dist/gitignore-checker.js +5 -4
  107. package/dist/gitignore-checker.js.map +1 -1
  108. package/dist/in-order.d.ts +93 -0
  109. package/dist/in-order.d.ts.map +1 -0
  110. package/dist/in-order.js +165 -0
  111. package/dist/in-order.js.map +1 -0
  112. package/dist/index.d.ts +20 -4
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/index.js +30 -4
  115. package/dist/index.js.map +1 -1
  116. package/dist/kill-process-tree.d.ts +43 -0
  117. package/dist/kill-process-tree.d.ts.map +1 -0
  118. package/dist/kill-process-tree.js +48 -0
  119. package/dist/kill-process-tree.js.map +1 -0
  120. package/dist/link-following.d.ts +115 -0
  121. package/dist/link-following.d.ts.map +1 -0
  122. package/dist/link-following.js +283 -0
  123. package/dist/link-following.js.map +1 -0
  124. package/dist/listing-refusal.d.ts +44 -0
  125. package/dist/listing-refusal.d.ts.map +1 -1
  126. package/dist/listing-refusal.js +79 -2
  127. package/dist/listing-refusal.js.map +1 -1
  128. package/dist/name-fold.d.ts +25 -0
  129. package/dist/name-fold.d.ts.map +1 -0
  130. package/dist/name-fold.js +40 -0
  131. package/dist/name-fold.js.map +1 -0
  132. package/dist/path-containment.d.ts +3 -1
  133. package/dist/path-containment.d.ts.map +1 -1
  134. package/dist/path-containment.js +13 -7
  135. package/dist/path-containment.js.map +1 -1
  136. package/dist/path-utils.d.ts +14 -17
  137. package/dist/path-utils.d.ts.map +1 -1
  138. package/dist/path-utils.js +37 -55
  139. package/dist/path-utils.js.map +1 -1
  140. package/dist/process.d.ts +2 -0
  141. package/dist/process.d.ts.map +1 -1
  142. package/dist/process.js +2 -0
  143. package/dist/process.js.map +1 -1
  144. package/dist/project-utils.d.ts.map +1 -1
  145. package/dist/project-utils.js +8 -9
  146. package/dist/project-utils.js.map +1 -1
  147. package/dist/safe-exec.d.ts +6 -2
  148. package/dist/safe-exec.d.ts.map +1 -1
  149. package/dist/safe-exec.js +1 -1
  150. package/dist/safe-exec.js.map +1 -1
  151. package/dist/skill-targets.d.ts.map +1 -1
  152. package/dist/skill-targets.js +3 -1
  153. package/dist/skill-targets.js.map +1 -1
  154. package/dist/skill-test/spawn-claude.d.ts +0 -15
  155. package/dist/skill-test/spawn-claude.d.ts.map +1 -1
  156. package/dist/skill-test/spawn-claude.js +11 -50
  157. package/dist/skill-test/spawn-claude.js.map +1 -1
  158. package/dist/special-file.d.ts +18 -0
  159. package/dist/special-file.d.ts.map +1 -0
  160. package/dist/special-file.js +21 -0
  161. package/dist/special-file.js.map +1 -0
  162. package/dist/terminating-signals.d.ts +129 -0
  163. package/dist/terminating-signals.d.ts.map +1 -0
  164. package/dist/terminating-signals.js +210 -0
  165. package/dist/terminating-signals.js.map +1 -0
  166. package/dist/test-helpers.d.ts +9 -5
  167. package/dist/test-helpers.d.ts.map +1 -1
  168. package/dist/test-helpers.js +18 -21
  169. package/dist/test-helpers.js.map +1 -1
  170. package/dist/test-scratch-guard.d.ts +34 -0
  171. package/dist/test-scratch-guard.d.ts.map +1 -0
  172. package/dist/test-scratch-guard.js +45 -0
  173. package/dist/test-scratch-guard.js.map +1 -0
  174. package/dist/testing/archive-fixtures.d.ts +147 -0
  175. package/dist/testing/archive-fixtures.d.ts.map +1 -0
  176. package/dist/testing/archive-fixtures.js +449 -0
  177. package/dist/testing/archive-fixtures.js.map +1 -0
  178. package/dist/testing/executables.d.ts +6 -0
  179. package/dist/testing/executables.d.ts.map +1 -1
  180. package/dist/testing/executables.js +20 -9
  181. package/dist/testing/executables.js.map +1 -1
  182. package/dist/testing/fault-fs-preload.d.ts +16 -0
  183. package/dist/testing/fault-fs-preload.d.ts.map +1 -0
  184. package/dist/testing/fault-fs-preload.js +22 -0
  185. package/dist/testing/fault-fs-preload.js.map +1 -0
  186. package/dist/testing/fault-fs.d.ts +115 -0
  187. package/dist/testing/fault-fs.d.ts.map +1 -0
  188. package/dist/testing/fault-fs.js +411 -0
  189. package/dist/testing/fault-fs.js.map +1 -0
  190. package/dist/testing/fault-spec.d.ts +83 -0
  191. package/dist/testing/fault-spec.d.ts.map +1 -0
  192. package/dist/testing/fault-spec.js +132 -0
  193. package/dist/testing/fault-spec.js.map +1 -0
  194. package/dist/testing/hostile-tree.d.ts.map +1 -1
  195. package/dist/testing/hostile-tree.js +3 -4
  196. package/dist/testing/hostile-tree.js.map +1 -1
  197. package/dist/testing/platform-gates.d.ts +8 -0
  198. package/dist/testing/platform-gates.d.ts.map +1 -1
  199. package/dist/testing/platform-gates.js +24 -0
  200. package/dist/testing/platform-gates.js.map +1 -1
  201. package/dist/testing/temp-dir.d.ts +31 -0
  202. package/dist/testing/temp-dir.d.ts.map +1 -1
  203. package/dist/testing/temp-dir.js +63 -0
  204. package/dist/testing/temp-dir.js.map +1 -1
  205. package/dist/testing/tier-timeout.d.ts +34 -0
  206. package/dist/testing/tier-timeout.d.ts.map +1 -0
  207. package/dist/testing/tier-timeout.js +45 -0
  208. package/dist/testing/tier-timeout.js.map +1 -0
  209. package/dist/testing/tree-snapshot.d.ts +71 -0
  210. package/dist/testing/tree-snapshot.d.ts.map +1 -0
  211. package/dist/testing/tree-snapshot.js +163 -0
  212. package/dist/testing/tree-snapshot.js.map +1 -0
  213. package/dist/testing.d.ts +6 -0
  214. package/dist/testing.d.ts.map +1 -1
  215. package/dist/testing.js +8 -1
  216. package/dist/testing.js.map +1 -1
  217. package/dist/text-file.d.ts +14 -1
  218. package/dist/text-file.d.ts.map +1 -1
  219. package/dist/text-file.js +41 -8
  220. package/dist/text-file.js.map +1 -1
  221. package/dist/timing-dump.d.ts.map +1 -1
  222. package/dist/timing-dump.js +2 -10
  223. package/dist/timing-dump.js.map +1 -1
  224. package/dist/tree-change/apply-decisions.d.ts +101 -0
  225. package/dist/tree-change/apply-decisions.d.ts.map +1 -0
  226. package/dist/tree-change/apply-decisions.js +139 -0
  227. package/dist/tree-change/apply-decisions.js.map +1 -0
  228. package/dist/tree-change/apply.d.ts +98 -0
  229. package/dist/tree-change/apply.d.ts.map +1 -0
  230. package/dist/tree-change/apply.js +364 -0
  231. package/dist/tree-change/apply.js.map +1 -0
  232. package/dist/tree-change/copy-decisions.d.ts +58 -0
  233. package/dist/tree-change/copy-decisions.d.ts.map +1 -0
  234. package/dist/tree-change/copy-decisions.js +66 -0
  235. package/dist/tree-change/copy-decisions.js.map +1 -0
  236. package/dist/tree-change/copy-tree.d.ts +125 -0
  237. package/dist/tree-change/copy-tree.d.ts.map +1 -0
  238. package/dist/tree-change/copy-tree.js +279 -0
  239. package/dist/tree-change/copy-tree.js.map +1 -0
  240. package/dist/tree-change/files.d.ts +167 -0
  241. package/dist/tree-change/files.d.ts.map +1 -0
  242. package/dist/tree-change/files.js +423 -0
  243. package/dist/tree-change/files.js.map +1 -0
  244. package/dist/tree-change/followed-walk.d.ts +54 -0
  245. package/dist/tree-change/followed-walk.d.ts.map +1 -0
  246. package/dist/tree-change/followed-walk.js +81 -0
  247. package/dist/tree-change/followed-walk.js.map +1 -0
  248. package/dist/tree-change/host-chain.d.ts +48 -0
  249. package/dist/tree-change/host-chain.d.ts.map +1 -0
  250. package/dist/tree-change/host-chain.js +85 -0
  251. package/dist/tree-change/host-chain.js.map +1 -0
  252. package/dist/tree-change/identity-compare.d.ts +61 -0
  253. package/dist/tree-change/identity-compare.d.ts.map +1 -0
  254. package/dist/tree-change/identity-compare.js +115 -0
  255. package/dist/tree-change/identity-compare.js.map +1 -0
  256. package/dist/tree-change/identity.d.ts +62 -0
  257. package/dist/tree-change/identity.d.ts.map +1 -0
  258. package/dist/tree-change/identity.js +152 -0
  259. package/dist/tree-change/identity.js.map +1 -0
  260. package/dist/tree-change/index.d.ts +24 -0
  261. package/dist/tree-change/index.d.ts.map +1 -0
  262. package/dist/tree-change/index.js +14 -0
  263. package/dist/tree-change/index.js.map +1 -0
  264. package/dist/tree-change/link-chain.d.ts +180 -0
  265. package/dist/tree-change/link-chain.d.ts.map +1 -0
  266. package/dist/tree-change/link-chain.js +377 -0
  267. package/dist/tree-change/link-chain.js.map +1 -0
  268. package/dist/tree-change/link-containment.d.ts +105 -0
  269. package/dist/tree-change/link-containment.d.ts.map +1 -0
  270. package/dist/tree-change/link-containment.js +196 -0
  271. package/dist/tree-change/link-containment.js.map +1 -0
  272. package/dist/tree-change/link-walk.d.ts +49 -0
  273. package/dist/tree-change/link-walk.d.ts.map +1 -0
  274. package/dist/tree-change/link-walk.js +69 -0
  275. package/dist/tree-change/link-walk.js.map +1 -0
  276. package/dist/tree-change/plan.d.ts +206 -0
  277. package/dist/tree-change/plan.d.ts.map +1 -0
  278. package/dist/tree-change/plan.js +320 -0
  279. package/dist/tree-change/plan.js.map +1 -0
  280. package/dist/tree-change/readable-tree.d.ts +44 -0
  281. package/dist/tree-change/readable-tree.d.ts.map +1 -0
  282. package/dist/tree-change/readable-tree.js +52 -0
  283. package/dist/tree-change/readable-tree.js.map +1 -0
  284. package/dist/tree-change/rollback-error.d.ts +29 -0
  285. package/dist/tree-change/rollback-error.d.ts.map +1 -0
  286. package/dist/tree-change/rollback-error.js +31 -0
  287. package/dist/tree-change/rollback-error.js.map +1 -0
  288. package/dist/tree-change/staging-names.d.ts +27 -0
  289. package/dist/tree-change/staging-names.d.ts.map +1 -0
  290. package/dist/tree-change/staging-names.js +40 -0
  291. package/dist/tree-change/staging-names.js.map +1 -0
  292. package/dist/tree-change/tree-walk.d.ts +81 -0
  293. package/dist/tree-change/tree-walk.d.ts.map +1 -0
  294. package/dist/tree-change/tree-walk.js +212 -0
  295. package/dist/tree-change/tree-walk.js.map +1 -0
  296. package/dist/win32-namespace.d.ts +24 -0
  297. package/dist/win32-namespace.d.ts.map +1 -0
  298. package/dist/win32-namespace.js +31 -0
  299. package/dist/win32-namespace.js.map +1 -0
  300. package/dist/yaml/surgical-yaml.d.ts +12 -3
  301. package/dist/yaml/surgical-yaml.d.ts.map +1 -1
  302. package/dist/yaml/surgical-yaml.js +16 -6
  303. package/dist/yaml/surgical-yaml.js.map +1 -1
  304. package/eslint/README.md +12 -4
  305. package/eslint/rules/fs-binding-scan.cjs +278 -0
  306. package/eslint/rules/no-adhoc-errno.cjs +364 -0
  307. package/eslint/rules/no-bare-symlink-in-tests.cjs +2 -3
  308. package/eslint/rules/no-blind-catch.cjs +1 -1
  309. package/eslint/rules/no-destructive-fs.cjs +359 -0
  310. package/eslint/rules/no-existssync.cjs +70 -0
  311. package/eslint/rules/no-fragile-entrypoint-guard.cjs +3 -2
  312. package/eslint/rules/no-link-following-fs.cjs +68 -0
  313. package/eslint/rules/no-literal-process-exit.cjs +3 -16
  314. package/eslint/rules/no-literal-test-timeout.cjs +214 -0
  315. package/eslint/rules/no-raw-signal-listener.cjs +224 -0
  316. package/eslint/rules/no-stdout-outside-writer.cjs +135 -0
  317. package/package.json +10 -2
  318. package/dist/errors/errno.d.ts +0 -51
  319. package/dist/errors/errno.d.ts.map +0 -1
  320. package/dist/errors/errno.js +0 -112
  321. package/dist/errors/errno.js.map +0 -1
  322. package/eslint/rules/no-fs-promises-cp.cjs +0 -43
@@ -0,0 +1,177 @@
1
+ /**
2
+ * The errno table and every single-errno question — the leaf of the fs-fault
3
+ * family.
4
+ *
5
+ * ⚠️ This module imports nothing but `win32-namespace.ts`, a leaf that itself imports nothing. `path-containment.ts`, `path-utils.ts`,
6
+ * `dirent-kind.ts` and `fs-utils.ts` ask "is there nothing at this path?", and
7
+ * `fs-fault.ts` needs `path-containment.ts` to decide a side by containment, so
8
+ * the table cannot live in `fs-fault.ts` without an import cycle
9
+ * (`fs-fault → path-containment → fs-fault`). It lives here, and `fs-fault.ts`
10
+ * builds classification on top of it.
11
+ *
12
+ * The errno sets are those of the former `FILESYSTEM_ACCESS_ERRNOS`; every
13
+ * member keeps exactly one class. The table is not the guarantee: an errno it
14
+ * does not list, on an error a system call raised, is still a fault — of the
15
+ * `device` class ({@link UNLISTED_ERRNO_CLASS}) — so a code libuv adds, or one a
16
+ * host reports that nobody wrote down, is never handed back raw. An error with
17
+ * no errno-shaped `code` is not a filesystem fault and {@link fsFaultOf} answers
18
+ * `undefined`, so a `TypeError` from a validator is never read as the
19
+ * environment's fault. The errnos a socket shares with a file on a share — the
20
+ * network ones — and every unlisted errno count only when a filesystem call
21
+ * raised them ({@link isRaisedByFilesystemCall}), so a `connect` or a fetch that
22
+ * failed is never read as one either.
23
+ */
24
+ /** What kind of thing the OS said went wrong, independent of which side of a verb it happened on. */
25
+ export type FsFaultClass = 'absent' | 'refused' | 'exhausted' | 'wrong-type' | 'occupied' | 'busy' | 'unsupported' | 'device';
26
+ /**
27
+ * The one place an errno gets a class. `EROFS` is `unsupported`: the filesystem cannot be written, no permission would change it.
28
+ *
29
+ * Frozen, lists included: the classifier's lookup is built from it once, at load, so a list a
30
+ * consumer could change afterwards would be a second table the classifier does not agree with.
31
+ */
32
+ export declare const FS_FAULT_ERRNOS_BY_CLASS: Readonly<Record<FsFaultClass, readonly string[]>>;
33
+ /**
34
+ * The class of an errno a caller already KNOWS a filesystem call raised — a listing git reported
35
+ * it could not open, say, where only the errno survives: the table's class, else
36
+ * {@link UNLISTED_ERRNO_CLASS}. Never `undefined`: the question "is this the filesystem?" was
37
+ * settled where the error was in hand.
38
+ *
39
+ * @param errno - The errno
40
+ * @returns Its class
41
+ */
42
+ export declare function filesystemErrnoClass(errno: string): FsFaultClass;
43
+ /**
44
+ * The code a path whose link chain VAT will not hand the kernel is refused with
45
+ * (`LinkChainRefusedError`, `tree-change/host-chain.ts`): a link on the way names
46
+ * a network path, or the chain never ends. Not an errno — VAT declined to ask the
47
+ * OS — but recorded where an errno is (a refused listing, a fault row), always
48
+ * of the `refused` class.
49
+ */
50
+ export declare const LINK_CHAIN_REFUSED_CODE = "LINK_CHAIN_REFUSED";
51
+ /** What `fsFaultOf` learned from the error that carried the errno. */
52
+ export interface FsFaultFacts {
53
+ readonly errno: string;
54
+ readonly faultClass: FsFaultClass;
55
+ readonly path: string | undefined;
56
+ readonly dest: string | undefined;
57
+ readonly syscall: string | undefined;
58
+ }
59
+ /**
60
+ * The classified errno on `error` or down its `cause` chain, with the path the OS
61
+ * named — or `undefined` when this is not the filesystem refusing something.
62
+ *
63
+ * Deliberately NOT `error instanceof Error`: callers degrade on a hostile tree,
64
+ * and a `TypeError` is not that. Walks `cause` because the errno is routinely
65
+ * re-wrapped on its way up (the CLI config loader turns a read failure into
66
+ * `new Error('Failed to load config: …')`); a `code`-only check answered "not a
67
+ * filesystem error" for a plain `EACCES`.
68
+ *
69
+ * A listed errno anywhere on the chain wins (a network one only from a filesystem call); failing
70
+ * that, the first errno a filesystem call raised that the table does not list is a fault of
71
+ * {@link UNLISTED_ERRNO_CLASS} — never `undefined`, so no caller hands it back raw. A link chain VAT
72
+ * would not hand the kernel ({@link LINK_CHAIN_REFUSED_CODE}, a `LinkChainRefusedError` — matched by
73
+ * its code and its `refusal`, as this module cannot import it) is a fault of the `refused` class
74
+ * too, so every catch that asks "is this the filesystem?" answers it as one, never as a bug.
75
+ */
76
+ export declare function fsFaultOf(error: unknown): FsFaultFacts | undefined;
77
+ /**
78
+ * The paths the failing syscall ACTED ON, the one to name the fault by first.
79
+ *
80
+ * Node files a two-path call's first argument under `path` and its second under `dest`, whatever
81
+ * the call does with them. For `symlink(target, link)` the first is the link's TARGET TEXT — a
82
+ * string the call never resolved, often relative — so only `dest`, the link being created, is a
83
+ * path the call acted on. `rename(from, to)` acted on both, and what it could not do is land the
84
+ * entry: `dest` first. Every other call — `link(existing, new)` and `copyfile` included, whose
85
+ * two arguments are both real paths either of which may be the one refused — is read `path` first.
86
+ *
87
+ * @param facts - The fault's facts, as {@link fsFaultOf} read them off the errno
88
+ * @returns Every path the call acted on, the one that names the fault first; empty when the errno carries none
89
+ */
90
+ export declare function pathsActedOn(facts: FsFaultFacts): readonly string[];
91
+ /**
92
+ * For a refused `rename`, the entry that was being moved — the other end of the path the fault is
93
+ * named by. `undefined` for every other call, and for a rename whose errno names one path only.
94
+ *
95
+ * @param facts - The fault's facts, as {@link fsFaultOf} read them off the errno
96
+ */
97
+ export declare function movedFromOf(facts: FsFaultFacts): string | undefined;
98
+ /**
99
+ * Whether `error` means **there is nothing at this path** — `ENOENT`, or `ENOTDIR`
100
+ * for a path whose component turned out to be a file — and nothing else. The
101
+ * narrowing a `try { stat(p) } catch { return null }` is rewritten to under
102
+ * `no-blind-catch`: only an absence may produce the sentinel; a refusal or a
103
+ * bug is rethrown.
104
+ */
105
+ export declare function isPathAbsentError(error: unknown): boolean;
106
+ /**
107
+ * `ENOENT` alone: nothing at this path, with every directory above it real. For a
108
+ * site where `ENOTDIR` — a component that is a FILE — must stay loud, because it
109
+ * means a misconfiguration rather than "not there yet" ({@link isPathAbsentError}
110
+ * folds the two together).
111
+ */
112
+ export declare function isNoSuchEntryError(error: unknown): boolean;
113
+ /**
114
+ * `ENOTDIR` alone: a component of the path is a FILE. On a write whose layout an
115
+ * input decided, that is a file in the way of a directory the layout needs — a
116
+ * layout fault, though the class table files `ENOTDIR` under `absent` (for a read
117
+ * it means "nothing there").
118
+ */
119
+ export declare function isFileInTheWayError(error: unknown): boolean;
120
+ /** `EEXIST`: the exclusive create lost to something already there. */
121
+ export declare function isAlreadyExistsError(error: unknown): boolean;
122
+ /** The `occupied` class (`EEXIST`, `ENOTEMPTY`): something is in the way — a directory `rmdir` was asked to remove still holds entries. */
123
+ export declare function isOccupiedError(error: unknown): boolean;
124
+ /**
125
+ * Whether resolving a link failed because **the link resolves to nothing** ({@link UNRESOLVABLE_LINK_ERRNOS}),
126
+ * as opposed to a fault of the OS or the operator's tree, which the caller throws for the classifier.
127
+ * The one answer to "does this link resolve?" for every site that follows one. `false` for an
128
+ * error that carries no errno.
129
+ */
130
+ export declare function isUnresolvableLinkError(error: unknown): boolean;
131
+ /**
132
+ * `EISDIR`, `ENOTSUP`, `EOPNOTSUPP` from a NATIVE realpath (`realpathSync.native`, `fs/promises.realpath`):
133
+ * the volume cannot answer a final-path query, which says nothing about the path. On Windows libuv
134
+ * maps `ERROR_INVALID_FUNCTION` — what `GetFinalPathNameByHandleW` returns on a RAM disk or a
135
+ * redirector that does not implement it — to `EISDIR` (`src/win/error.c`). The answer is the JS
136
+ * realpath (an lstat/readlink walk), which never asks that question.
137
+ */
138
+ export declare function isFinalPathUnanswerableError(error: unknown): boolean;
139
+ /** `ENAMETOOLONG`: a name (or path) longer than this host's filesystem will take. */
140
+ export declare function isNameTooLongError(error: unknown): boolean;
141
+ /** `EINVAL`: the filesystem rejected the argument (e.g. `readlink` on a non-link). */
142
+ export declare function isInvalidArgumentError(error: unknown): boolean;
143
+ /** `EFTYPE`: BSD's "inappropriate file type" — a pipe, socket or device where content was expected. */
144
+ export declare function isNotARegularFileError(error: unknown): boolean;
145
+ /** `ETIMEDOUT`: an operation (a child process given a `timeout`, a network filesystem) ran out of time. */
146
+ export declare function isTimedOutError(error: unknown): boolean;
147
+ /** `EAGAIN`: a non-blocking descriptor (stdout on a full pipe) would block. */
148
+ export declare function isWouldBlockError(error: unknown): boolean;
149
+ /**
150
+ * `ESRCH` or `EPERM` from signalling a process group we created: no such group,
151
+ * or its id was recycled to a process we may not signal. Either way every
152
+ * process of ours in it has exited — the outcome the kill was after.
153
+ */
154
+ export declare function isProcessGoneError(error: unknown): boolean;
155
+ /** This host cannot create symlinks: Windows without Developer Mode (`EPERM`), or a filesystem with none (`ENOTSUP`/`EOPNOTSUPP`). */
156
+ export declare function isSymlinkUnsupportedError(error: unknown): boolean;
157
+ /**
158
+ * A refusal a re-ask can legitimately answer differently: the `busy` class
159
+ * (`EBUSY`, `ETXTBSY`, `EAGAIN`), or this process out of descriptors (`EMFILE`,
160
+ * `ENFILE`). Disk and quota exhaustion (`ENOSPC`, `EDQUOT`) share the `exhausted`
161
+ * class but are NOT retryable: re-asking frees no space, so "re-run first" would
162
+ * be the wrong advice.
163
+ */
164
+ export declare function isRetryableShortageError(error: unknown): boolean;
165
+ /**
166
+ * The errnos Windows raises when a rename races a scanner, indexer or handle
167
+ * that has the tree open: `EPERM`, `EBUSY`, `EACCES`. Worth a bounded retry;
168
+ * anything else is final.
169
+ */
170
+ export declare function isRenameContentionError(error: unknown): boolean;
171
+ /**
172
+ * The `refused` class (`EACCES`, `EPERM`): the OS refused the caller's access. A
173
+ * removal refused this way is retried once its directories are made owner-writable:
174
+ * a read-only directory refuses the removal of its entries.
175
+ */
176
+ export declare function isAccessRefusedError(error: unknown): boolean;
177
+ //# sourceMappingURL=errno-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errno-table.d.ts","sourceRoot":"","sources":["../../src/errors/errno-table.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,343 @@
1
+ /**
2
+ * The errno table and every single-errno question — the leaf of the fs-fault
3
+ * family.
4
+ *
5
+ * ⚠️ This module imports nothing but `win32-namespace.ts`, a leaf that itself imports nothing. `path-containment.ts`, `path-utils.ts`,
6
+ * `dirent-kind.ts` and `fs-utils.ts` ask "is there nothing at this path?", and
7
+ * `fs-fault.ts` needs `path-containment.ts` to decide a side by containment, so
8
+ * the table cannot live in `fs-fault.ts` without an import cycle
9
+ * (`fs-fault → path-containment → fs-fault`). It lives here, and `fs-fault.ts`
10
+ * builds classification on top of it.
11
+ *
12
+ * The errno sets are those of the former `FILESYSTEM_ACCESS_ERRNOS`; every
13
+ * member keeps exactly one class. The table is not the guarantee: an errno it
14
+ * does not list, on an error a system call raised, is still a fault — of the
15
+ * `device` class ({@link UNLISTED_ERRNO_CLASS}) — so a code libuv adds, or one a
16
+ * host reports that nobody wrote down, is never handed back raw. An error with
17
+ * no errno-shaped `code` is not a filesystem fault and {@link fsFaultOf} answers
18
+ * `undefined`, so a `TypeError` from a validator is never read as the
19
+ * environment's fault. The errnos a socket shares with a file on a share — the
20
+ * network ones — and every unlisted errno count only when a filesystem call
21
+ * raised them ({@link isRaisedByFilesystemCall}), so a `connect` or a fetch that
22
+ * failed is never read as one either.
23
+ */
24
+ import { withoutWin32Namespace } from '../win32-namespace.js';
25
+ /**
26
+ * The one place an errno gets a class. `EROFS` is `unsupported`: the filesystem cannot be written, no permission would change it.
27
+ *
28
+ * Frozen, lists included: the classifier's lookup is built from it once, at load, so a list a
29
+ * consumer could change afterwards would be a second table the classifier does not agree with.
30
+ */
31
+ export const FS_FAULT_ERRNOS_BY_CLASS = {
32
+ absent: ['ENOENT', 'ENOTDIR'],
33
+ refused: ['EACCES', 'EPERM'],
34
+ exhausted: ['ENOSPC', 'EDQUOT', 'EMFILE', 'ENFILE'],
35
+ // EFTYPE: BSD's errno for a named pipe, socket or device where content was expected (`readDecodableBytes` raises it)
36
+ 'wrong-type': ['EISDIR', 'EFTYPE', 'ELOOP', 'ENAMETOOLONG'],
37
+ occupied: ['EEXIST', 'ENOTEMPTY'],
38
+ busy: ['EBUSY', 'ETXTBSY', 'EAGAIN'],
39
+ unsupported: ['ENOTSUP', 'EOPNOTSUPP', 'EXDEV', 'EINVAL', 'EROFS'],
40
+ // The network errnos a file call on a share raises — libuv v1.x `src/win/error.c` maps
41
+ // `ERROR_NETWORK_UNREACHABLE` to ENETUNREACH (:131), `ERROR_HOST_UNREACHABLE` to EHOSTUNREACH
42
+ // (:100), `ERROR_NETNAME_DELETED` (the share went away mid-call) to ECONNRESET (:94) and
43
+ // `ERROR_NOT_CONNECTED` to ENOTCONN (:152).
44
+ //
45
+ // UNKNOWN: what `uv_translate_sys_error` answers for a Win32 error it has NO case for (`default:
46
+ // return UV_UNKNOWN;`, :172) — and only that; every Win32 error with a case is its mapped errno,
47
+ // the network ones above included. Among the unmapped: a share that is not there
48
+ // (`ERROR_BAD_NETPATH`, `ERROR_BAD_NET_NAME`), credentials or an ACL the share refused
49
+ // (`ERROR_LOGON_FAILURE`, `ERROR_NETWORK_ACCESS_DENIED`), a drive that is not ready or not there
50
+ // (`ERROR_NOT_READY`, `ERROR_DEV_NOT_EXIST`). The Win32 cause is lost, so UNKNOWN is ambiguous: a
51
+ // fault, never "resolves to nothing".
52
+ device: ['EIO', 'ESTALE', 'ETIMEDOUT', 'EHOSTDOWN', 'ENETDOWN', 'ENETUNREACH', 'EHOSTUNREACH', 'ECONNRESET', 'ENOTCONN', 'UNKNOWN'],
53
+ };
54
+ for (const errnos of Object.values(FS_FAULT_ERRNOS_BY_CLASS))
55
+ Object.freeze(errnos);
56
+ Object.freeze(FS_FAULT_ERRNOS_BY_CLASS);
57
+ const CLASS_BY_ERRNO = new Map(Object.entries(FS_FAULT_ERRNOS_BY_CLASS)
58
+ .flatMap(([faultClass, errnos]) => errnos.map((errno) => [errno, faultClass])));
59
+ /**
60
+ * The class of an errno the table does not list, raised by a system call (`EFAULT`, `ECHARSET`,
61
+ * whatever a later libuv or another host adds). `device`: the OS could not complete the call for a
62
+ * reason VAT has no name for — a fault on the side it happened, with the "check the device" remedy,
63
+ * never "nothing there" and never an internal error.
64
+ */
65
+ const UNLISTED_ERRNO_CLASS = 'device';
66
+ /** An errno-shaped code: libuv's `E…` names and its `UNKNOWN`. Node's own `ERR_…` codes are not errnos. */
67
+ const ERRNO_SHAPE = /^(E[A-Z0-9]+|UNKNOWN)$/;
68
+ /**
69
+ * The listed errnos a socket raises as readily as a file call on a share does. Listed (a share
70
+ * reports them), but a fault only when a filesystem call raised them ({@link isRaisedByFilesystemCall}).
71
+ */
72
+ const NETWORK_ERRNOS = new Set(['ENETUNREACH', 'EHOSTUNREACH', 'ECONNRESET', 'ENOTCONN']);
73
+ /**
74
+ * The filesystem calls that act on a descriptor and so name no path. `read`, `write` and `close`
75
+ * are not here: a socket raises them too (a fetch's `ECONNRESET` is `syscall: 'read'`), and nothing
76
+ * on the error tells the two apart.
77
+ */
78
+ const FILESYSTEM_FD_SYSCALLS = new Set(['fstat', 'ftruncate', 'fsync', 'fdatasync', 'futime', 'fchmod', 'fchown']);
79
+ /**
80
+ * The ONE test of "a filesystem call raised this": the error names the path it acted on (`path`
81
+ * or `dest` — every path-taking fs call reports one, and no socket call does: a socket names an
82
+ * `address`), or its syscall is a descriptor-only filesystem call ({@link FILESYSTEM_FD_SYSCALLS}).
83
+ * Both the network errnos and the unlisted fallback ask it, so they cannot disagree.
84
+ */
85
+ function isRaisedByFilesystemCall(node) {
86
+ if (stringField(node, 'path') !== undefined || stringField(node, 'dest') !== undefined)
87
+ return true;
88
+ const syscall = stringField(node, 'syscall');
89
+ return syscall !== undefined && FILESYSTEM_FD_SYSCALLS.has(syscall);
90
+ }
91
+ /** Whether the error that carries `code` holds a listed errno that is a fault here. */
92
+ function isListedFault(code, node) {
93
+ return CLASS_BY_ERRNO.has(code) && (!NETWORK_ERRNOS.has(code) || isRaisedByFilesystemCall(node));
94
+ }
95
+ /** Whether the error that carries `code` is a refused link chain (`LinkChainRefusedError`, by shape). */
96
+ function isRefusedLinkChain(code, node) {
97
+ return code === LINK_CHAIN_REFUSED_CODE && 'refusal' in node;
98
+ }
99
+ /** Whether the error that carries `code` is a filesystem call's errno the table does not list. */
100
+ function isUnlistedFilesystemErrno(code, node) {
101
+ return ERRNO_SHAPE.test(code) && !CLASS_BY_ERRNO.has(code) && isRaisedByFilesystemCall(node);
102
+ }
103
+ /**
104
+ * The class of an errno a caller already KNOWS a filesystem call raised — a listing git reported
105
+ * it could not open, say, where only the errno survives: the table's class, else
106
+ * {@link UNLISTED_ERRNO_CLASS}. Never `undefined`: the question "is this the filesystem?" was
107
+ * settled where the error was in hand.
108
+ *
109
+ * @param errno - The errno
110
+ * @returns Its class
111
+ */
112
+ export function filesystemErrnoClass(errno) {
113
+ if (errno === LINK_CHAIN_REFUSED_CODE)
114
+ return 'refused';
115
+ return CLASS_BY_ERRNO.get(errno) ?? UNLISTED_ERRNO_CLASS;
116
+ }
117
+ /**
118
+ * The code a path whose link chain VAT will not hand the kernel is refused with
119
+ * (`LinkChainRefusedError`, `tree-change/host-chain.ts`): a link on the way names
120
+ * a network path, or the chain never ends. Not an errno — VAT declined to ask the
121
+ * OS — but recorded where an errno is (a refused listing, a fault row), always
122
+ * of the `refused` class.
123
+ */
124
+ export const LINK_CHAIN_REFUSED_CODE = 'LINK_CHAIN_REFUSED';
125
+ const MAX_CAUSE_DEPTH = 10;
126
+ /** A path field of an errno, without the win32 namespace prefix Node may report it with — read once, here, for every consumer. */
127
+ function reportedPath(source, key) {
128
+ const reported = stringField(source, key);
129
+ return reported === undefined ? undefined : withoutWin32Namespace(reported);
130
+ }
131
+ function stringField(source, key) {
132
+ const value = source[key];
133
+ return typeof value === 'string' ? value : undefined;
134
+ }
135
+ /**
136
+ * The first error on `error`'s `cause` chain whose string `code` satisfies
137
+ * `accept`. Bounded: a malformed chain must not become an infinite loop inside
138
+ * an error path, which is the worst place to hang.
139
+ */
140
+ function findCoded(error, accept) {
141
+ let current = error;
142
+ for (let depth = 0; depth < MAX_CAUSE_DEPTH; depth++) {
143
+ if (typeof current !== 'object' || current === null)
144
+ return undefined;
145
+ const code = stringField(current, 'code');
146
+ if (code !== undefined && accept(code, current))
147
+ return { node: current, code };
148
+ if (!('cause' in current))
149
+ return undefined;
150
+ current = current.cause;
151
+ }
152
+ return undefined;
153
+ }
154
+ /**
155
+ * The classified errno on `error` or down its `cause` chain, with the path the OS
156
+ * named — or `undefined` when this is not the filesystem refusing something.
157
+ *
158
+ * Deliberately NOT `error instanceof Error`: callers degrade on a hostile tree,
159
+ * and a `TypeError` is not that. Walks `cause` because the errno is routinely
160
+ * re-wrapped on its way up (the CLI config loader turns a read failure into
161
+ * `new Error('Failed to load config: …')`); a `code`-only check answered "not a
162
+ * filesystem error" for a plain `EACCES`.
163
+ *
164
+ * A listed errno anywhere on the chain wins (a network one only from a filesystem call); failing
165
+ * that, the first errno a filesystem call raised that the table does not list is a fault of
166
+ * {@link UNLISTED_ERRNO_CLASS} — never `undefined`, so no caller hands it back raw. A link chain VAT
167
+ * would not hand the kernel ({@link LINK_CHAIN_REFUSED_CODE}, a `LinkChainRefusedError` — matched by
168
+ * its code and its `refusal`, as this module cannot import it) is a fault of the `refused` class
169
+ * too, so every catch that asks "is this the filesystem?" answers it as one, never as a bug.
170
+ */
171
+ export function fsFaultOf(error) {
172
+ const found = findCoded(error, isListedFault) ?? findCoded(error, isUnlistedFilesystemErrno) ?? findCoded(error, isRefusedLinkChain);
173
+ if (found === undefined)
174
+ return undefined;
175
+ return {
176
+ errno: found.code,
177
+ faultClass: filesystemErrnoClass(found.code),
178
+ path: reportedPath(found.node, 'path'),
179
+ dest: reportedPath(found.node, 'dest'),
180
+ syscall: stringField(found.node, 'syscall'),
181
+ };
182
+ }
183
+ /**
184
+ * The paths the failing syscall ACTED ON, the one to name the fault by first.
185
+ *
186
+ * Node files a two-path call's first argument under `path` and its second under `dest`, whatever
187
+ * the call does with them. For `symlink(target, link)` the first is the link's TARGET TEXT — a
188
+ * string the call never resolved, often relative — so only `dest`, the link being created, is a
189
+ * path the call acted on. `rename(from, to)` acted on both, and what it could not do is land the
190
+ * entry: `dest` first. Every other call — `link(existing, new)` and `copyfile` included, whose
191
+ * two arguments are both real paths either of which may be the one refused — is read `path` first.
192
+ *
193
+ * @param facts - The fault's facts, as {@link fsFaultOf} read them off the errno
194
+ * @returns Every path the call acted on, the one that names the fault first; empty when the errno carries none
195
+ */
196
+ export function pathsActedOn(facts) {
197
+ const { path, dest, syscall } = facts;
198
+ let ordered = [path, dest];
199
+ if (syscall === 'symlink')
200
+ ordered = [dest];
201
+ else if (syscall === 'rename')
202
+ ordered = [dest, path];
203
+ return ordered.filter((each) => each !== undefined);
204
+ }
205
+ /**
206
+ * For a refused `rename`, the entry that was being moved — the other end of the path the fault is
207
+ * named by. `undefined` for every other call, and for a rename whose errno names one path only.
208
+ *
209
+ * @param facts - The fault's facts, as {@link fsFaultOf} read them off the errno
210
+ */
211
+ export function movedFromOf(facts) {
212
+ return facts.syscall === 'rename' && facts.dest !== undefined ? facts.path : undefined;
213
+ }
214
+ function hasAnyErrno(error, errnos) {
215
+ return findCoded(error, (code) => errnos.includes(code)) !== undefined;
216
+ }
217
+ /**
218
+ * Whether `error` means **there is nothing at this path** — `ENOENT`, or `ENOTDIR`
219
+ * for a path whose component turned out to be a file — and nothing else. The
220
+ * narrowing a `try { stat(p) } catch { return null }` is rewritten to under
221
+ * `no-blind-catch`: only an absence may produce the sentinel; a refusal or a
222
+ * bug is rethrown.
223
+ */
224
+ export function isPathAbsentError(error) {
225
+ return hasAnyErrno(error, FS_FAULT_ERRNOS_BY_CLASS.absent);
226
+ }
227
+ /**
228
+ * `ENOENT` alone: nothing at this path, with every directory above it real. For a
229
+ * site where `ENOTDIR` — a component that is a FILE — must stay loud, because it
230
+ * means a misconfiguration rather than "not there yet" ({@link isPathAbsentError}
231
+ * folds the two together).
232
+ */
233
+ export function isNoSuchEntryError(error) {
234
+ return hasAnyErrno(error, ['ENOENT']);
235
+ }
236
+ /**
237
+ * `ENOTDIR` alone: a component of the path is a FILE. On a write whose layout an
238
+ * input decided, that is a file in the way of a directory the layout needs — a
239
+ * layout fault, though the class table files `ENOTDIR` under `absent` (for a read
240
+ * it means "nothing there").
241
+ */
242
+ export function isFileInTheWayError(error) {
243
+ return hasAnyErrno(error, ['ENOTDIR']);
244
+ }
245
+ /** `EEXIST`: the exclusive create lost to something already there. */
246
+ export function isAlreadyExistsError(error) {
247
+ return hasAnyErrno(error, ['EEXIST']);
248
+ }
249
+ /** The `occupied` class (`EEXIST`, `ENOTEMPTY`): something is in the way — a directory `rmdir` was asked to remove still holds entries. */
250
+ export function isOccupiedError(error) {
251
+ return hasAnyErrno(error, FS_FAULT_ERRNOS_BY_CLASS.occupied);
252
+ }
253
+ /**
254
+ * The errnos with which the OS LOOKED and found nothing a link resolves to: the `absent` class
255
+ * (`ENOENT`, `ENOTDIR` — it dangles) and `ELOOP` (a cycle; on Windows
256
+ * `ERROR_CANT_RESOLVE_FILENAME`). On Windows a dangling link or junction is `ENOENT`. Every other
257
+ * errno says nothing about the link — the OS declining (`EACCES`, `EPERM`), running short
258
+ * (`EMFILE`, `ENOSPC`), being held (`EBUSY`), failing to look (`EIO`, `ESTALE`, `ETIMEDOUT`, the
259
+ * network errnos) — and so does an AMBIGUOUS one: libuv v1.x `src/win/error.c` reports
260
+ * `ERROR_INVALID_PARAMETER`, `ERROR_INVALID_DATA`, `ERROR_INSUFFICIENT_BUFFER` and
261
+ * `ERROR_SYMLINK_NOT_SUPPORTED` all as `EINVAL` (:102-105), `ERROR_BUFFER_OVERFLOW` as
262
+ * `ENAMETOOLONG` (:129), and every Win32 error it has no case for as `UNKNOWN` (:172) — a missing
263
+ * share AND refused credentials. A cause that cannot be told apart is a fault, never "nothing there".
264
+ */
265
+ const UNRESOLVABLE_LINK_ERRNOS = Object.freeze([...FS_FAULT_ERRNOS_BY_CLASS.absent, 'ELOOP']);
266
+ /**
267
+ * Whether resolving a link failed because **the link resolves to nothing** ({@link UNRESOLVABLE_LINK_ERRNOS}),
268
+ * as opposed to a fault of the OS or the operator's tree, which the caller throws for the classifier.
269
+ * The one answer to "does this link resolve?" for every site that follows one. `false` for an
270
+ * error that carries no errno.
271
+ */
272
+ export function isUnresolvableLinkError(error) {
273
+ return hasAnyErrno(error, UNRESOLVABLE_LINK_ERRNOS);
274
+ }
275
+ /**
276
+ * `EISDIR`, `ENOTSUP`, `EOPNOTSUPP` from a NATIVE realpath (`realpathSync.native`, `fs/promises.realpath`):
277
+ * the volume cannot answer a final-path query, which says nothing about the path. On Windows libuv
278
+ * maps `ERROR_INVALID_FUNCTION` — what `GetFinalPathNameByHandleW` returns on a RAM disk or a
279
+ * redirector that does not implement it — to `EISDIR` (`src/win/error.c`). The answer is the JS
280
+ * realpath (an lstat/readlink walk), which never asks that question.
281
+ */
282
+ export function isFinalPathUnanswerableError(error) {
283
+ return hasAnyErrno(error, ['EISDIR', 'ENOTSUP', 'EOPNOTSUPP']);
284
+ }
285
+ /** `ENAMETOOLONG`: a name (or path) longer than this host's filesystem will take. */
286
+ export function isNameTooLongError(error) {
287
+ return hasAnyErrno(error, ['ENAMETOOLONG']);
288
+ }
289
+ /** `EINVAL`: the filesystem rejected the argument (e.g. `readlink` on a non-link). */
290
+ export function isInvalidArgumentError(error) {
291
+ return hasAnyErrno(error, ['EINVAL']);
292
+ }
293
+ /** `EFTYPE`: BSD's "inappropriate file type" — a pipe, socket or device where content was expected. */
294
+ export function isNotARegularFileError(error) {
295
+ return hasAnyErrno(error, ['EFTYPE']);
296
+ }
297
+ /** `ETIMEDOUT`: an operation (a child process given a `timeout`, a network filesystem) ran out of time. */
298
+ export function isTimedOutError(error) {
299
+ return hasAnyErrno(error, ['ETIMEDOUT']);
300
+ }
301
+ /** `EAGAIN`: a non-blocking descriptor (stdout on a full pipe) would block. */
302
+ export function isWouldBlockError(error) {
303
+ return hasAnyErrno(error, ['EAGAIN']);
304
+ }
305
+ /**
306
+ * `ESRCH` or `EPERM` from signalling a process group we created: no such group,
307
+ * or its id was recycled to a process we may not signal. Either way every
308
+ * process of ours in it has exited — the outcome the kill was after.
309
+ */
310
+ export function isProcessGoneError(error) {
311
+ return hasAnyErrno(error, ['ESRCH', 'EPERM']);
312
+ }
313
+ /** This host cannot create symlinks: Windows without Developer Mode (`EPERM`), or a filesystem with none (`ENOTSUP`/`EOPNOTSUPP`). */
314
+ export function isSymlinkUnsupportedError(error) {
315
+ return hasAnyErrno(error, ['EPERM', 'ENOTSUP', 'EOPNOTSUPP']);
316
+ }
317
+ /**
318
+ * A refusal a re-ask can legitimately answer differently: the `busy` class
319
+ * (`EBUSY`, `ETXTBSY`, `EAGAIN`), or this process out of descriptors (`EMFILE`,
320
+ * `ENFILE`). Disk and quota exhaustion (`ENOSPC`, `EDQUOT`) share the `exhausted`
321
+ * class but are NOT retryable: re-asking frees no space, so "re-run first" would
322
+ * be the wrong advice.
323
+ */
324
+ export function isRetryableShortageError(error) {
325
+ return hasAnyErrno(error, [...FS_FAULT_ERRNOS_BY_CLASS.busy, 'EMFILE', 'ENFILE']);
326
+ }
327
+ /**
328
+ * The errnos Windows raises when a rename races a scanner, indexer or handle
329
+ * that has the tree open: `EPERM`, `EBUSY`, `EACCES`. Worth a bounded retry;
330
+ * anything else is final.
331
+ */
332
+ export function isRenameContentionError(error) {
333
+ return hasAnyErrno(error, ['EPERM', 'EBUSY', 'EACCES']);
334
+ }
335
+ /**
336
+ * The `refused` class (`EACCES`, `EPERM`): the OS refused the caller's access. A
337
+ * removal refused this way is retried once its directories are made owner-writable:
338
+ * a read-only directory refuses the removal of its entries.
339
+ */
340
+ export function isAccessRefusedError(error) {
341
+ return hasAnyErrno(error, FS_FAULT_ERRNOS_BY_CLASS.refused);
342
+ }
343
+ //# sourceMappingURL=errno-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errno-table.js","sourceRoot":"","sources":["../../src/errors/errno-table.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `fsBoundary`: decide a fault's side from the path the OS named, against the
3
+ * roots each side owns. Built on the classifier (`fs-fault.ts`) and on
4
+ * `path-containment.ts`; it lives apart from the classifier so that the path
5
+ * helpers `path-containment.ts` itself imports can classify without a cycle.
6
+ */
7
+ import { type FsSide, type SourceOrigin } from './fs-fault.js';
8
+ /** The directories each side owns for one verb. */
9
+ export interface FsRoots {
10
+ readonly source?: readonly string[];
11
+ readonly destination?: readonly string[];
12
+ readonly environment?: readonly string[];
13
+ }
14
+ /** Decides the side of a fault from the path the OS named. */
15
+ export interface FsBoundary {
16
+ /** The side owning `path` (the most specific root wins), or `undefined` when it is under no root. */
17
+ sideOf(path: string): FsSide | undefined;
18
+ /** Classify an error already caught: by the path it names, else on `fallback`; a non-fs error comes back untouched. */
19
+ classify(error: unknown, action: string, fallback: FsSide): unknown;
20
+ run<T>(action: string, fallback: FsSide, work: () => Promise<T>): Promise<T>;
21
+ runSync<T>(action: string, fallback: FsSide, work: () => T): T;
22
+ }
23
+ /**
24
+ * Role by PATH, not by wrapper. A wrapper names the side its author had in mind;
25
+ * the path the failing call acted on ({@link pathsActedOn} — never a symlink's target
26
+ * text, and a rename's landing place first) is what actually failed, and one call routinely touches
27
+ * both an input and an output (a `copyFile` whose source is unreadable fails
28
+ * under the SOURCE root even though the wrapper says "write"). Falls back to the
29
+ * call's declared side only when the error names no path or the path is under no
30
+ * root.
31
+ */
32
+ export declare function fsBoundary(roots: FsRoots, options?: {
33
+ origin?: SourceOrigin;
34
+ shapeFromSource?: boolean;
35
+ }): FsBoundary;
36
+ //# sourceMappingURL=fs-boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-boundary.d.ts","sourceRoot":"","sources":["../../src/errors/fs-boundary.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,EAA6B,KAAK,MAAM,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1F,mDAAmD;AACnD,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,8DAA8D;AAC9D,MAAM,WAAW,UAAU;IACzB,qGAAqG;IACrG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACzC,uHAAuH;IACvH,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACpE,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7E,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;CAChE;AA0CD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,YAAY,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,UAAU,CA0DzH"}