@vibe-agent-toolkit/utils 0.1.42 → 0.2.0-rc.10

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 (279) hide show
  1. package/README.md +81 -19
  2. package/dist/asset-reference.js +3 -11
  3. package/dist/asset-reference.js.map +1 -1
  4. package/dist/compare-code-units.d.ts +28 -0
  5. package/dist/compare-code-units.d.ts.map +1 -0
  6. package/dist/compare-code-units.js +33 -0
  7. package/dist/compare-code-units.js.map +1 -0
  8. package/dist/crawl-timing.d.ts +657 -0
  9. package/dist/crawl-timing.d.ts.map +1 -0
  10. package/dist/crawl-timing.js +765 -0
  11. package/dist/crawl-timing.js.map +1 -0
  12. package/dist/crawl.d.ts +2 -4
  13. package/dist/crawl.d.ts.map +1 -1
  14. package/dist/crawl.js +2 -4
  15. package/dist/crawl.js.map +1 -1
  16. package/dist/dirent-kind.d.ts +83 -0
  17. package/dist/dirent-kind.d.ts.map +1 -0
  18. package/dist/dirent-kind.js +129 -0
  19. package/dist/dirent-kind.js.map +1 -0
  20. package/dist/entrypoint.d.ts +54 -0
  21. package/dist/entrypoint.d.ts.map +1 -0
  22. package/dist/entrypoint.js +71 -0
  23. package/dist/entrypoint.js.map +1 -0
  24. package/dist/env-flag.d.ts +51 -0
  25. package/dist/env-flag.d.ts.map +1 -0
  26. package/dist/env-flag.js +62 -0
  27. package/dist/env-flag.js.map +1 -0
  28. package/dist/errors/errno.d.ts +51 -0
  29. package/dist/errors/errno.d.ts.map +1 -0
  30. package/dist/errors/errno.js +112 -0
  31. package/dist/errors/errno.js.map +1 -0
  32. package/dist/errors/vat-error.d.ts +60 -0
  33. package/dist/errors/vat-error.d.ts.map +1 -0
  34. package/dist/errors/vat-error.js +86 -0
  35. package/dist/errors/vat-error.js.map +1 -0
  36. package/dist/file-crawler.d.ts +60 -0
  37. package/dist/file-crawler.d.ts.map +1 -1
  38. package/dist/file-crawler.js +214 -24
  39. package/dist/file-crawler.js.map +1 -1
  40. package/dist/fs/file-hash.d.ts.map +1 -1
  41. package/dist/fs/file-hash.js +0 -1
  42. package/dist/fs/file-hash.js.map +1 -1
  43. package/dist/fs-utils.d.ts +628 -38
  44. package/dist/fs-utils.d.ts.map +1 -1
  45. package/dist/fs-utils.js +770 -71
  46. package/dist/fs-utils.js.map +1 -1
  47. package/dist/fs.d.ts +5 -1
  48. package/dist/fs.d.ts.map +1 -1
  49. package/dist/fs.js +9 -1
  50. package/dist/fs.js.map +1 -1
  51. package/dist/git-root-cache.d.ts +44 -0
  52. package/dist/git-root-cache.d.ts.map +1 -0
  53. package/dist/git-root-cache.js +68 -0
  54. package/dist/git-root-cache.js.map +1 -0
  55. package/dist/git-run.d.ts +167 -0
  56. package/dist/git-run.d.ts.map +1 -0
  57. package/dist/git-run.js +154 -0
  58. package/dist/git-run.js.map +1 -0
  59. package/dist/git-snapshot.d.ts +199 -0
  60. package/dist/git-snapshot.d.ts.map +1 -0
  61. package/dist/git-snapshot.js +250 -0
  62. package/dist/git-snapshot.js.map +1 -0
  63. package/dist/git-tracker.d.ts +166 -3
  64. package/dist/git-tracker.d.ts.map +1 -1
  65. package/dist/git-tracker.js +250 -22
  66. package/dist/git-tracker.js.map +1 -1
  67. package/dist/git-utils.d.ts +95 -1
  68. package/dist/git-utils.d.ts.map +1 -1
  69. package/dist/git-utils.js +227 -81
  70. package/dist/git-utils.js.map +1 -1
  71. package/dist/git.d.ts +13 -4
  72. package/dist/git.d.ts.map +1 -1
  73. package/dist/git.js +12 -4
  74. package/dist/git.js.map +1 -1
  75. package/dist/gitignore-checker.d.ts.map +1 -1
  76. package/dist/gitignore-checker.js +15 -6
  77. package/dist/gitignore-checker.js.map +1 -1
  78. package/dist/glob/glob-pattern.js +5 -5
  79. package/dist/glob/glob-pattern.js.map +1 -1
  80. package/dist/index.d.ts +33 -19
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +113 -33
  83. package/dist/index.js.map +1 -1
  84. package/dist/listing-refusal.d.ts +112 -0
  85. package/dist/listing-refusal.d.ts.map +1 -0
  86. package/dist/listing-refusal.js +105 -0
  87. package/dist/listing-refusal.js.map +1 -0
  88. package/dist/numeric-args.d.ts +24 -0
  89. package/dist/numeric-args.d.ts.map +1 -0
  90. package/dist/numeric-args.js +37 -0
  91. package/dist/numeric-args.js.map +1 -0
  92. package/dist/path-containment.d.ts +64 -0
  93. package/dist/path-containment.d.ts.map +1 -0
  94. package/dist/path-containment.js +111 -0
  95. package/dist/path-containment.js.map +1 -0
  96. package/dist/path-core.d.ts +143 -18
  97. package/dist/path-core.d.ts.map +1 -1
  98. package/dist/path-core.js +171 -23
  99. package/dist/path-core.js.map +1 -1
  100. package/dist/path-utils.d.ts.map +1 -1
  101. package/dist/path-utils.js +42 -47
  102. package/dist/path-utils.js.map +1 -1
  103. package/dist/path.d.ts +1 -1
  104. package/dist/path.d.ts.map +1 -1
  105. package/dist/path.js +1 -1
  106. package/dist/path.js.map +1 -1
  107. package/dist/process.d.ts +7 -0
  108. package/dist/process.d.ts.map +1 -1
  109. package/dist/process.js +7 -0
  110. package/dist/process.js.map +1 -1
  111. package/dist/project-utils.d.ts +7 -1
  112. package/dist/project-utils.d.ts.map +1 -1
  113. package/dist/project-utils.js +24 -10
  114. package/dist/project-utils.js.map +1 -1
  115. package/dist/project.d.ts +7 -5
  116. package/dist/project.d.ts.map +1 -1
  117. package/dist/project.js +7 -5
  118. package/dist/project.js.map +1 -1
  119. package/dist/safe-exec.d.ts +40 -11
  120. package/dist/safe-exec.d.ts.map +1 -1
  121. package/dist/safe-exec.js +111 -25
  122. package/dist/safe-exec.js.map +1 -1
  123. package/dist/skill-targets.d.ts +2 -2
  124. package/dist/skill-targets.js +2 -2
  125. package/dist/skill-test/auth-resolver.d.ts +10 -2
  126. package/dist/skill-test/auth-resolver.d.ts.map +1 -1
  127. package/dist/skill-test/auth-resolver.js +26 -11
  128. package/dist/skill-test/auth-resolver.js.map +1 -1
  129. package/dist/skill-test/index.d.ts +1 -1
  130. package/dist/skill-test/index.d.ts.map +1 -1
  131. package/dist/skill-test/index.js +1 -1
  132. package/dist/skill-test/index.js.map +1 -1
  133. package/dist/skill-test/spawn-claude.d.ts +30 -1
  134. package/dist/skill-test/spawn-claude.d.ts.map +1 -1
  135. package/dist/skill-test/spawn-claude.js +71 -5
  136. package/dist/skill-test/spawn-claude.js.map +1 -1
  137. package/dist/skill-test/transcript.d.ts +41 -2
  138. package/dist/skill-test/transcript.d.ts.map +1 -1
  139. package/dist/skill-test/transcript.js +55 -10
  140. package/dist/skill-test/transcript.js.map +1 -1
  141. package/dist/spawn-hardened.js +0 -1
  142. package/dist/spawn-hardened.js.map +1 -1
  143. package/dist/stdio-blocking.js +13 -14
  144. package/dist/stdio-blocking.js.map +1 -1
  145. package/dist/test-helpers.d.ts +130 -79
  146. package/dist/test-helpers.d.ts.map +1 -1
  147. package/dist/test-helpers.js +229 -124
  148. package/dist/test-helpers.js.map +1 -1
  149. package/dist/testing/executables.d.ts +32 -0
  150. package/dist/testing/executables.d.ts.map +1 -0
  151. package/dist/testing/executables.js +70 -0
  152. package/dist/testing/executables.js.map +1 -0
  153. package/dist/testing/hostile-tree.d.ts +79 -0
  154. package/dist/testing/hostile-tree.d.ts.map +1 -0
  155. package/dist/testing/hostile-tree.js +164 -0
  156. package/dist/testing/hostile-tree.js.map +1 -0
  157. package/dist/testing/platform-gates.d.ts +31 -0
  158. package/dist/testing/platform-gates.d.ts.map +1 -0
  159. package/dist/testing/platform-gates.js +31 -0
  160. package/dist/testing/platform-gates.js.map +1 -0
  161. package/dist/testing/temp-dir.d.ts +255 -0
  162. package/dist/testing/temp-dir.d.ts.map +1 -0
  163. package/dist/testing/temp-dir.js +363 -0
  164. package/dist/testing/temp-dir.js.map +1 -0
  165. package/dist/testing.d.ts +94 -3
  166. package/dist/testing.d.ts.map +1 -1
  167. package/dist/testing.js +119 -3
  168. package/dist/testing.js.map +1 -1
  169. package/dist/text-content.d.ts +197 -0
  170. package/dist/text-content.d.ts.map +1 -0
  171. package/dist/text-content.js +354 -0
  172. package/dist/text-content.js.map +1 -0
  173. package/dist/text-file.d.ts +45 -0
  174. package/dist/text-file.d.ts.map +1 -0
  175. package/dist/text-file.js +51 -0
  176. package/dist/text-file.js.map +1 -0
  177. package/dist/text.d.ts +16 -0
  178. package/dist/text.d.ts.map +1 -0
  179. package/dist/text.js +16 -0
  180. package/dist/text.js.map +1 -0
  181. package/dist/timing-dump.d.ts +136 -0
  182. package/dist/timing-dump.d.ts.map +1 -0
  183. package/dist/timing-dump.js +229 -0
  184. package/dist/timing-dump.js.map +1 -0
  185. package/dist/windows-shell.d.ts +0 -1
  186. package/dist/windows-shell.d.ts.map +1 -1
  187. package/dist/windows-shell.js +0 -1
  188. package/dist/windows-shell.js.map +1 -1
  189. package/dist/zod-introspection.js +2 -2
  190. package/dist/zod-introspection.js.map +1 -1
  191. package/eslint/README.md +224 -50
  192. package/eslint/index.cjs +111 -97
  193. package/eslint/index.d.cts +16 -6
  194. package/eslint/rules/callee-name.cjs +23 -0
  195. package/eslint/rules/commands-import-boundary.cjs +148 -0
  196. package/eslint/rules/dead-import.cjs +62 -12
  197. package/eslint/rules/dirent-type-needs-symlink-check.cjs +282 -0
  198. package/eslint/rules/eslint-rule-factory.cjs +21 -3
  199. package/eslint/rules/exempt-path-matcher.cjs +2 -1
  200. package/eslint/rules/explicit-zod-strictness.cjs +120 -0
  201. package/eslint/rules/no-bare-dynamic-import-path.cjs +5 -1
  202. package/eslint/rules/no-bare-executable-spawn.cjs +70 -0
  203. package/eslint/rules/no-bare-symlink-in-tests.cjs +213 -0
  204. package/eslint/rules/no-blind-catch.cjs +171 -0
  205. package/eslint/rules/no-child-process-execSync.cjs +8 -0
  206. package/eslint/rules/no-decaying-referent.cjs +217 -0
  207. package/eslint/rules/no-dotdot-containment.cjs +160 -0
  208. package/eslint/rules/no-file-url-string-concat.cjs +4 -1
  209. package/eslint/rules/no-fragile-entrypoint-guard.cjs +228 -0
  210. package/eslint/rules/no-fs-mkdirSync.cjs +8 -0
  211. package/eslint/rules/no-fs-promises-cp.cjs +7 -0
  212. package/eslint/rules/no-fs-realpathSync.cjs +8 -0
  213. package/eslint/rules/no-hardcoded-path-split.cjs +29 -18
  214. package/eslint/rules/no-io-in-unit-tier.cjs +129 -0
  215. package/eslint/rules/no-literal-process-exit.cjs +129 -0
  216. package/eslint/rules/no-manual-path-normalize.cjs +146 -96
  217. package/eslint/rules/no-os-tmpdir.cjs +8 -0
  218. package/eslint/rules/no-path-operations-in-comparisons.cjs +7 -2
  219. package/eslint/rules/no-path-sep-in-strings.cjs +7 -2
  220. package/eslint/rules/no-path-startswith.cjs +7 -2
  221. package/eslint/rules/no-process-exit-in-phase.cjs +127 -0
  222. package/eslint/rules/no-raw-node-path.cjs +563 -0
  223. package/eslint/rules/no-raw-text-decode.cjs +305 -0
  224. package/eslint/rules/no-registry-count-pin.cjs +255 -0
  225. package/eslint/rules/no-self-package-import.cjs +168 -0
  226. package/eslint/rules/no-test-scoped-functions.cjs +10 -3
  227. package/eslint/rules/no-unix-shell-commands.cjs +6 -2
  228. package/eslint/rules/no-unsafe-root-join.cjs +23 -2
  229. package/eslint/rules/no-url-pathname-for-fs.cjs +5 -1
  230. package/eslint/rules/no-version-literal.cjs +151 -0
  231. package/eslint/rules/prefer-startswith-over-regex.cjs +33 -1
  232. package/eslint/rules/require-justified-skip.cjs +8 -2
  233. package/eslint/rules/safe-import.cjs +1 -1
  234. package/package.json +16 -16
  235. package/dist/link-auth/build-headers.d.ts +0 -34
  236. package/dist/link-auth/build-headers.d.ts.map +0 -1
  237. package/dist/link-auth/build-headers.js +0 -58
  238. package/dist/link-auth/build-headers.js.map +0 -1
  239. package/dist/link-auth/expand-macro.d.ts +0 -38
  240. package/dist/link-auth/expand-macro.d.ts.map +0 -1
  241. package/dist/link-auth/expand-macro.js +0 -133
  242. package/dist/link-auth/expand-macro.js.map +0 -1
  243. package/dist/link-auth/macros.yaml +0 -50
  244. package/dist/link-auth/resolve-token.d.ts +0 -83
  245. package/dist/link-auth/resolve-token.d.ts.map +0 -1
  246. package/dist/link-auth/resolve-token.js +0 -101
  247. package/dist/link-auth/resolve-token.js.map +0 -1
  248. package/dist/link-auth/resolve.d.ts +0 -102
  249. package/dist/link-auth/resolve.d.ts.map +0 -1
  250. package/dist/link-auth/resolve.js +0 -66
  251. package/dist/link-auth/resolve.js.map +0 -1
  252. package/dist/link-auth/rewrite.d.ts +0 -52
  253. package/dist/link-auth/rewrite.d.ts.map +0 -1
  254. package/dist/link-auth/rewrite.js +0 -102
  255. package/dist/link-auth/rewrite.js.map +0 -1
  256. package/dist/link-auth/select-provider.d.ts +0 -30
  257. package/dist/link-auth/select-provider.d.ts.map +0 -1
  258. package/dist/link-auth/select-provider.js +0 -55
  259. package/dist/link-auth/select-provider.js.map +0 -1
  260. package/dist/link-auth/template.d.ts +0 -40
  261. package/dist/link-auth/template.d.ts.map +0 -1
  262. package/dist/link-auth/template.js +0 -89
  263. package/dist/link-auth/template.js.map +0 -1
  264. package/dist/link-auth/transforms.d.ts +0 -46
  265. package/dist/link-auth/transforms.d.ts.map +0 -1
  266. package/dist/link-auth/transforms.js +0 -52
  267. package/dist/link-auth/transforms.js.map +0 -1
  268. package/dist/template-entry.d.ts +0 -10
  269. package/dist/template-entry.d.ts.map +0 -1
  270. package/dist/template-entry.js +0 -10
  271. package/dist/template-entry.js.map +0 -1
  272. package/dist/template.d.ts +0 -7
  273. package/dist/template.d.ts.map +0 -1
  274. package/dist/template.js +0 -18
  275. package/dist/template.js.map +0 -1
  276. package/eslint/rules/no-path-join.cjs +0 -14
  277. package/eslint/rules/no-path-relative.cjs +0 -14
  278. package/eslint/rules/no-path-resolve.cjs +0 -14
  279. package/eslint/rules/path-function-rule-factory.cjs +0 -417
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawl-timing.js","sourceRoot":"","sources":["../src/crawl-timing.ts"],"names":[],"mappings":"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"}
package/dist/crawl.d.ts CHANGED
@@ -6,10 +6,8 @@
6
6
  * and shells out to `git` for the gitignore-aware fast path.
7
7
  *
8
8
  * This is the only *subpath* entry that reaches `picomatch` — `./crawl` is
9
- * therefore the narrow entry that makes `picomatch` a required install. It is
10
- * not the package's only consumer of it: `link-auth/select-provider.ts` uses
11
- * `picomatch.isMatch` for host-pattern matching, and that is reachable from the
12
- * `.` barrel.
9
+ * therefore the narrow entry that makes `picomatch` a required install. The `.`
10
+ * barrel reaches it too, through this same `file-crawler` route.
13
11
  *
14
12
  * Deliberately NOT folded into `./glob`. `./glob` is guarded as portable —
15
13
  * `node:path` and no third-party dependency (see `test/subpath-purity.test.ts`)
@@ -1 +1 @@
1
- {"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,mBAAmB,CAAC"}
package/dist/crawl.js CHANGED
@@ -6,10 +6,8 @@
6
6
  * and shells out to `git` for the gitignore-aware fast path.
7
7
  *
8
8
  * This is the only *subpath* entry that reaches `picomatch` — `./crawl` is
9
- * therefore the narrow entry that makes `picomatch` a required install. It is
10
- * not the package's only consumer of it: `link-auth/select-provider.ts` uses
11
- * `picomatch.isMatch` for host-pattern matching, and that is reachable from the
12
- * `.` barrel.
9
+ * therefore the narrow entry that makes `picomatch` a required install. The `.`
10
+ * barrel reaches it too, through this same `file-crawler` route.
13
11
  *
14
12
  * Deliberately NOT folded into `./glob`. `./glob` is guarded as portable —
15
13
  * `node:path` and no third-party dependency (see `test/subpath-purity.test.ts`)
package/dist/crawl.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"crawl.js","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"crawl.js","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * What a directory entry IS — with the symlink question asked first.
3
+ *
4
+ * A `Dirent` from `readdir(…, { withFileTypes: true })` describes the entry
5
+ * itself, so for a symlink BOTH `isFile()` and `isDirectory()` are false. A
6
+ * walk written `if (e.isDirectory()) recurse(); else if (e.isFile()) read();`
7
+ * therefore neither refuses a link nor follows it: it drops the entry on the
8
+ * floor without a word. The sweep found staged skill trees, size accounting
9
+ * and packaging walks with exactly that shape, every one reporting a tree
10
+ * with a symlink in it as clean. `local/dirent-type-needs-symlink-check`
11
+ * refuses that shape; these two helpers are what a walk says instead, and
12
+ * each makes the caller pick a policy by name.
13
+ *
14
+ * - {@link direntKind} — lstat semantics. A link is `'symlink'`, never what it
15
+ * points at. For a walk that must NOT follow (a delete, a size count of
16
+ * what `rm -rf` will remove, a bundle that travels as a tarball).
17
+ * - {@link direntKindFollowing} — stat semantics. A link is answered by its
18
+ * target: `'file'`, `'directory'`, or `'dangling'`. For a walk over a tree
19
+ * the caller trusts (its own build output, a dev-mode install, a fixture),
20
+ * where a link is simply how the entry got there.
21
+ *
22
+ * Neither helper decides for the caller. A `'symlink'` or `'dangling'` that
23
+ * the caller ignores is still ignored — but it is ignored in a `case` the
24
+ * reader can see, which is the whole difference.
25
+ */
26
+ import type { Dirent } from 'node:fs';
27
+ import { VatError } from './errors/vat-error.js';
28
+ /** What the entry itself is. A link is a link. */
29
+ export type DirentKind = 'file' | 'directory' | 'symlink' | 'other';
30
+ /** What the entry resolves to. A link is answered by its target, or is `dangling`. */
31
+ export type FollowedKind = 'file' | 'directory' | 'dangling' | 'other';
32
+ /**
33
+ * Classify an entry WITHOUT following it.
34
+ *
35
+ * @param entry - A `Dirent` from a `withFileTypes` listing
36
+ * @returns `'symlink'` for any link, else the entry's own type
37
+ */
38
+ export declare function direntKind(entry: Dirent): DirentKind;
39
+ /**
40
+ * Classify an entry by what it resolves to, following a link with one `stat`.
41
+ *
42
+ * A non-link entry costs no syscall. A link whose target is absent is
43
+ * `'dangling'`; a link the OS refuses to resolve (`ELOOP`, `EACCES`) is a
44
+ * refusal, not an absence, and stays loud.
45
+ *
46
+ * @param dir - The directory `entry` was listed from
47
+ * @param entry - A `Dirent` from a `withFileTypes` listing of `dir`
48
+ * @returns The target's kind, or `'dangling'`
49
+ */
50
+ export declare function direntKindFollowingSync(dir: string, entry: Dirent): FollowedKind;
51
+ /** The async counterpart of {@link direntKindFollowingSync}. */
52
+ export declare function direntKindFollowing(dir: string, entry: Dirent): Promise<FollowedKind>;
53
+ /** Thrown when a following walk is led back into a directory it has already entered. */
54
+ export declare class DirectoryWalkRevisitedError extends VatError {
55
+ constructor(dir: string, enteredAs: string);
56
+ }
57
+ /**
58
+ * The directories a FOLLOWING walk has entered, by realpath, so a link that
59
+ * leads back into the walk is refused instead of recursed until
60
+ * `ENAMETOOLONG`.
61
+ *
62
+ * A walk that follows links (`direntKindFollowing`) has no cycle guard by
63
+ * construction: `scripts/loop -> .` makes a copy create `dest/loop/loop/…`,
64
+ * writing every file at every level first, and a hashing walk do the same in
65
+ * memory. Every following walk holds one of these and calls {@link enter}
66
+ * on every directory it recurses into — the root included. A REVISIT is
67
+ * refused, not just a cycle: two links to one directory make the walk's
68
+ * output ambiguous (which spelling is the file's path?), and a refusal that
69
+ * names both spellings is the answer the author can act on.
70
+ */
71
+ export declare class FollowedWalk {
72
+ #private;
73
+ /**
74
+ * Record that the walk is entering `dir`. Synchronous on purpose — one
75
+ * realpath per directory entered is nothing beside the listing itself, and
76
+ * the sync and async walkers then share one guard.
77
+ *
78
+ * @param dir - A directory the walk is about to list, in any spelling
79
+ * @throws {DirectoryWalkRevisitedError} When its realpath was entered before
80
+ */
81
+ enter(dir: string): void;
82
+ }
83
+ //# sourceMappingURL=dirent-kind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dirent-kind.d.ts","sourceRoot":"","sources":["../src/dirent-kind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAKtC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAIjD,kDAAkD;AAClD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpE,sFAAsF;AACtF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC;AAEvE;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAKpD;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAQhF;AAED,gEAAgE;AAChE,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAQ3F;AAED,wFAAwF;AACxF,qBAAa,2BAA4B,SAAQ,QAAQ;gBAC3C,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAM3C;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,YAAY;;IAGvB;;;;;;;OAOG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAMzB"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * What a directory entry IS — with the symlink question asked first.
3
+ *
4
+ * A `Dirent` from `readdir(…, { withFileTypes: true })` describes the entry
5
+ * itself, so for a symlink BOTH `isFile()` and `isDirectory()` are false. A
6
+ * walk written `if (e.isDirectory()) recurse(); else if (e.isFile()) read();`
7
+ * therefore neither refuses a link nor follows it: it drops the entry on the
8
+ * floor without a word. The sweep found staged skill trees, size accounting
9
+ * and packaging walks with exactly that shape, every one reporting a tree
10
+ * with a symlink in it as clean. `local/dirent-type-needs-symlink-check`
11
+ * refuses that shape; these two helpers are what a walk says instead, and
12
+ * each makes the caller pick a policy by name.
13
+ *
14
+ * - {@link direntKind} — lstat semantics. A link is `'symlink'`, never what it
15
+ * points at. For a walk that must NOT follow (a delete, a size count of
16
+ * what `rm -rf` will remove, a bundle that travels as a tarball).
17
+ * - {@link direntKindFollowing} — stat semantics. A link is answered by its
18
+ * target: `'file'`, `'directory'`, or `'dangling'`. For a walk over a tree
19
+ * the caller trusts (its own build output, a dev-mode install, a fixture),
20
+ * where a link is simply how the entry got there.
21
+ *
22
+ * Neither helper decides for the caller. A `'symlink'` or `'dangling'` that
23
+ * the caller ignores is still ignored — but it is ignored in a `case` the
24
+ * reader can see, which is the whole difference.
25
+ */
26
+ import { statSync } from 'node:fs';
27
+ import fs from 'node:fs/promises';
28
+ import { isPathAbsentError } from './errors/errno.js';
29
+ import { VatError } from './errors/vat-error.js';
30
+ import { toForwardSlash } from './path-core.js';
31
+ import { normalizePath, safePath } from './path-utils.js';
32
+ /**
33
+ * Classify an entry WITHOUT following it.
34
+ *
35
+ * @param entry - A `Dirent` from a `withFileTypes` listing
36
+ * @returns `'symlink'` for any link, else the entry's own type
37
+ */
38
+ export function direntKind(entry) {
39
+ if (entry.isSymbolicLink())
40
+ return 'symlink';
41
+ if (entry.isDirectory())
42
+ return 'directory';
43
+ if (entry.isFile())
44
+ return 'file';
45
+ return 'other';
46
+ }
47
+ /** The kind a `stat` result reports. */
48
+ function kindOfStats(stats) {
49
+ if (stats.isDirectory())
50
+ return 'directory';
51
+ if (stats.isFile())
52
+ return 'file';
53
+ return 'other';
54
+ }
55
+ /**
56
+ * Classify an entry by what it resolves to, following a link with one `stat`.
57
+ *
58
+ * A non-link entry costs no syscall. A link whose target is absent is
59
+ * `'dangling'`; a link the OS refuses to resolve (`ELOOP`, `EACCES`) is a
60
+ * refusal, not an absence, and stays loud.
61
+ *
62
+ * @param dir - The directory `entry` was listed from
63
+ * @param entry - A `Dirent` from a `withFileTypes` listing of `dir`
64
+ * @returns The target's kind, or `'dangling'`
65
+ */
66
+ export function direntKindFollowingSync(dir, entry) {
67
+ if (!entry.isSymbolicLink())
68
+ return kindOfStats(entry);
69
+ try {
70
+ return kindOfStats(statSync(safePath.join(dir, entry.name)));
71
+ }
72
+ catch (error) {
73
+ if (isPathAbsentError(error))
74
+ return 'dangling';
75
+ throw error;
76
+ }
77
+ }
78
+ /** The async counterpart of {@link direntKindFollowingSync}. */
79
+ export async function direntKindFollowing(dir, entry) {
80
+ if (!entry.isSymbolicLink())
81
+ return kindOfStats(entry);
82
+ try {
83
+ return kindOfStats(await fs.stat(safePath.join(dir, entry.name)));
84
+ }
85
+ catch (error) {
86
+ if (isPathAbsentError(error))
87
+ return 'dangling';
88
+ throw error;
89
+ }
90
+ }
91
+ /** Thrown when a following walk is led back into a directory it has already entered. */
92
+ export class DirectoryWalkRevisitedError extends VatError {
93
+ constructor(dir, enteredAs) {
94
+ super('DIRECTORY_WALK_REVISITED', `Refusing to enter ${dir}: it is the directory already walked as ${enteredAs} — a symlink leads the walk back into itself.`);
95
+ }
96
+ }
97
+ /**
98
+ * The directories a FOLLOWING walk has entered, by realpath, so a link that
99
+ * leads back into the walk is refused instead of recursed until
100
+ * `ENAMETOOLONG`.
101
+ *
102
+ * A walk that follows links (`direntKindFollowing`) has no cycle guard by
103
+ * construction: `scripts/loop -> .` makes a copy create `dest/loop/loop/…`,
104
+ * writing every file at every level first, and a hashing walk do the same in
105
+ * memory. Every following walk holds one of these and calls {@link enter}
106
+ * on every directory it recurses into — the root included. A REVISIT is
107
+ * refused, not just a cycle: two links to one directory make the walk's
108
+ * output ambiguous (which spelling is the file's path?), and a refusal that
109
+ * names both spellings is the answer the author can act on.
110
+ */
111
+ export class FollowedWalk {
112
+ #entered = new Map();
113
+ /**
114
+ * Record that the walk is entering `dir`. Synchronous on purpose — one
115
+ * realpath per directory entered is nothing beside the listing itself, and
116
+ * the sync and async walkers then share one guard.
117
+ *
118
+ * @param dir - A directory the walk is about to list, in any spelling
119
+ * @throws {DirectoryWalkRevisitedError} When its realpath was entered before
120
+ */
121
+ enter(dir) {
122
+ const real = toForwardSlash(normalizePath(dir));
123
+ const before = this.#entered.get(real);
124
+ if (before !== undefined)
125
+ throw new DirectoryWalkRevisitedError(dir, before);
126
+ this.#entered.set(real, dir);
127
+ }
128
+ }
129
+ //# sourceMappingURL=dirent-kind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dirent-kind.js","sourceRoot":"","sources":["../src/dirent-kind.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The one answer to "am I the script Node was asked to run?"
3
+ *
4
+ * Lives here, in the package every other one already depends on, because there
5
+ * has to be exactly one: the question was previously answered three different
6
+ * ways across this monorepo (`import.meta.main`, a raw `pathToFileURL` string
7
+ * compare, and this function), and two of those three answer `false` for the
8
+ * script they guard — which makes the process exit 0 having run nothing.
9
+ */
10
+ /**
11
+ * Was this module invoked as the process entrypoint, rather than imported?
12
+ *
13
+ * ⛔ **Do not reach for `import.meta.main` here.** It shipped in Node 24.2 and
14
+ * 22.18; this repo declares a floor of `>=22.13.0`, and on a real 22.13.0 the
15
+ * property is `undefined`:
16
+ *
17
+ * ```
18
+ * $ node-v22.13.0 --input-type=module -e "console.log(import.meta.main)" -> undefined
19
+ * ```
20
+ *
21
+ * That is not a cosmetic gap. Every `if (import.meta.main)` guard in the
22
+ * dev-tools package was silently dead on the declared floor — running
23
+ * `validate-repo-structure.ts` under 22.13.0 printed nothing and exited 0, so a
24
+ * contributor sitting exactly on the supported Node got a green pre-commit
25
+ * structure gate that had run no rule at all. Raising the floor to 22.18 would
26
+ * have hidden the defect behind the number instead of fixing it.
27
+ *
28
+ * ⛔ **Nor the raw string compare it replaced**, which was the other seven
29
+ * guards in this repo:
30
+ *
31
+ * ```ts
32
+ * import.meta.url === pathToFileURL(process.argv[1]).href // ❌
33
+ * ```
34
+ *
35
+ * A `node_modules/.bin` entry is a SYMLINK to the real script, so `argv[1]` is
36
+ * the link and `import.meta.url` is the resolved target. The two strings differ
37
+ * and the guard is false — measured false through a `.bin`-style symlink on both
38
+ * Node 22.14.0 and 24.13.1, where this function is true.
39
+ *
40
+ * `process.argv[1]` is defined on every Node this repo supports, so the
41
+ * comparison below is the portable form of the same question. The realpath pass
42
+ * covers the case where the script is reached through a symlink on one side of
43
+ * the comparison but not the other.
44
+ *
45
+ * `local/no-fragile-entrypoint-guard` (shipped on this package's `./eslint`
46
+ * subpath) is what keeps either of the two banned spellings from coming back —
47
+ * the prose comments that used to stand in for it did not.
48
+ *
49
+ * @param importMetaUrl - The calling module's `import.meta.url`
50
+ * @param entryPath - The invoked script path; defaults to `process.argv[1]`
51
+ * @returns `true` only when this module is the script Node was asked to run
52
+ */
53
+ export declare function isEntrypoint(importMetaUrl: string, entryPath?: string | undefined): boolean;
54
+ //# sourceMappingURL=entrypoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,YAAY,CAC1B,aAAa,EAAE,MAAM,EACrB,SAAS,GAAE,MAAM,GAAG,SAA2B,GAC9C,OAAO,CAcT"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The one answer to "am I the script Node was asked to run?"
3
+ *
4
+ * Lives here, in the package every other one already depends on, because there
5
+ * has to be exactly one: the question was previously answered three different
6
+ * ways across this monorepo (`import.meta.main`, a raw `pathToFileURL` string
7
+ * compare, and this function), and two of those three answer `false` for the
8
+ * script they guard — which makes the process exit 0 having run nothing.
9
+ */
10
+ import { fileURLToPath } from 'node:url';
11
+ import { safePath, toForwardSlash } from './path-core.js';
12
+ import { normalizePath } from './path-utils.js';
13
+ /**
14
+ * Was this module invoked as the process entrypoint, rather than imported?
15
+ *
16
+ * ⛔ **Do not reach for `import.meta.main` here.** It shipped in Node 24.2 and
17
+ * 22.18; this repo declares a floor of `>=22.13.0`, and on a real 22.13.0 the
18
+ * property is `undefined`:
19
+ *
20
+ * ```
21
+ * $ node-v22.13.0 --input-type=module -e "console.log(import.meta.main)" -> undefined
22
+ * ```
23
+ *
24
+ * That is not a cosmetic gap. Every `if (import.meta.main)` guard in the
25
+ * dev-tools package was silently dead on the declared floor — running
26
+ * `validate-repo-structure.ts` under 22.13.0 printed nothing and exited 0, so a
27
+ * contributor sitting exactly on the supported Node got a green pre-commit
28
+ * structure gate that had run no rule at all. Raising the floor to 22.18 would
29
+ * have hidden the defect behind the number instead of fixing it.
30
+ *
31
+ * ⛔ **Nor the raw string compare it replaced**, which was the other seven
32
+ * guards in this repo:
33
+ *
34
+ * ```ts
35
+ * import.meta.url === pathToFileURL(process.argv[1]).href // ❌
36
+ * ```
37
+ *
38
+ * A `node_modules/.bin` entry is a SYMLINK to the real script, so `argv[1]` is
39
+ * the link and `import.meta.url` is the resolved target. The two strings differ
40
+ * and the guard is false — measured false through a `.bin`-style symlink on both
41
+ * Node 22.14.0 and 24.13.1, where this function is true.
42
+ *
43
+ * `process.argv[1]` is defined on every Node this repo supports, so the
44
+ * comparison below is the portable form of the same question. The realpath pass
45
+ * covers the case where the script is reached through a symlink on one side of
46
+ * the comparison but not the other.
47
+ *
48
+ * `local/no-fragile-entrypoint-guard` (shipped on this package's `./eslint`
49
+ * subpath) is what keeps either of the two banned spellings from coming back —
50
+ * the prose comments that used to stand in for it did not.
51
+ *
52
+ * @param importMetaUrl - The calling module's `import.meta.url`
53
+ * @param entryPath - The invoked script path; defaults to `process.argv[1]`
54
+ * @returns `true` only when this module is the script Node was asked to run
55
+ */
56
+ export function isEntrypoint(importMetaUrl, entryPath = process.argv[1]) {
57
+ // An empty argv[1] would resolve to the cwd and could then match a module by
58
+ // accident; `undefined` happens under `node -e`. Neither is an entrypoint.
59
+ if (entryPath === undefined || entryPath === '')
60
+ return false;
61
+ const modulePath = safePath.resolve(fileURLToPath(importMetaUrl));
62
+ const invokedPath = safePath.resolve(entryPath);
63
+ if (modulePath === invokedPath)
64
+ return true;
65
+ // `normalizePath` resolves symlinks and Windows 8.3 short names, and returns
66
+ // the path unchanged when it cannot — which is the right answer here, since
67
+ // the string comparison above has already decided the two differ and an
68
+ // unresolvable path carries no symlink information to compare.
69
+ return toForwardSlash(normalizePath(modulePath)) === toForwardSlash(normalizePath(invokedPath));
70
+ }
71
+ //# sourceMappingURL=entrypoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypoint.js","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,UAAU,YAAY,CAC1B,aAAqB,EACrB,YAAgC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAE/C,6EAA6E;IAC7E,2EAA2E;IAC3E,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAE9D,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;IAClE,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChD,IAAI,UAAU,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAE5C,6EAA6E;IAC7E,4EAA4E;IAC5E,wEAAwE;IACxE,+DAA+D;IAC/D,OAAO,cAAc,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,KAAK,cAAc,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC;AAClG,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Read an environment variable as a boolean.
3
+ *
4
+ * 🔑 **Returns `undefined` for anything it does not recognise, and never
5
+ * guesses.** That is the whole point: the caller — not this function — decides
6
+ * what an unreadable value means, because only the caller knows which way is
7
+ * safe. A token-fetching kill switch wants "deny"; a cache toggle wants
8
+ * "leave the cache on". A parser that folded the unknown case into `false`
9
+ * would have made that choice for both of them.
10
+ *
11
+ * 🚨 **Why this exists at all.** Three switches were each a comparison against
12
+ * the literal string `'0'`, so `=false` turned none of them off — measured for
13
+ * `VAT_LINKAUTH_ALLOW_COMMAND`, which *still spawned subprocesses*. Every
14
+ * spelling a human reaches for (`false`, `no`, `off`, `FALSE`, a value with a
15
+ * stray space) failed open. A switch whose off position is one exact string is
16
+ * not a switch.
17
+ *
18
+ * 📍 **Why it lives in `utils`.** It was written next to its first consumer in
19
+ * `resources`, on the rule that utils takes a utility when a SECOND package
20
+ * needs it rather than speculatively. That second package arrived:
21
+ * `packages/cli`'s `projectionStoreSelected()` reads the same `VAT_CACHE` the
22
+ * `resources` parse cache does, and two independent readings of one variable is
23
+ * the defect, not the fix. The four consumers today:
24
+ *
25
+ * | Caller | Variable | Reads `undefined` as | Why |
26
+ * |---|---|---|---|
27
+ * | `link-auth/resolve-token.ts` | `VAT_LINKAUTH_ALLOW_COMMAND` | **deny** | gates a capability — fail closed |
28
+ * | `resources/parse-cache.ts` | `VAT_CACHE` | cache stays on | gates a cache — an unreadable value must not silently change behaviour |
29
+ * | `cli/utils/projection-store.ts` | `VAT_CACHE` | not a veto | same variable, same reading, one implementation |
30
+ * | `cli/utils/projection-store.ts` | `VAT_PROJECTION_STORE` | not a veto | the projection store is ON by default; only an explicit off spelling (or an empty value, which that call site handles before asking) turns it off |
31
+ *
32
+ * Same parser, different safe sides, each chosen at its own call site. That is
33
+ * the contract; do not move a default in here.
34
+ *
35
+ * 🔑 The last two rows are the interesting pair: one variable defaults OFF and
36
+ * the other defaults ON, and both are still read through this one function,
37
+ * because what it answers is not "is this on" but "did the operator say no".
38
+ */
39
+ /**
40
+ * Parse an env value as a boolean.
41
+ *
42
+ * Case-insensitive and surrounding whitespace is trimmed, because a value that
43
+ * arrived through a shell, a CI YAML block, or a `.env` file routinely carries
44
+ * both. Everything else — including the empty string, which is what an unset
45
+ * shell variable expands to — returns `undefined`.
46
+ *
47
+ * @param raw - The raw env value, or `undefined` when the variable is unset
48
+ * @returns `true` / `false` for a recognised spelling; `undefined` otherwise
49
+ */
50
+ export declare function parseEnvBoolean(raw: string | undefined): boolean | undefined;
51
+ //# sourceMappingURL=env-flag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-flag.d.ts","sourceRoot":"","sources":["../src/env-flag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAKH;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAM5E"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Read an environment variable as a boolean.
3
+ *
4
+ * 🔑 **Returns `undefined` for anything it does not recognise, and never
5
+ * guesses.** That is the whole point: the caller — not this function — decides
6
+ * what an unreadable value means, because only the caller knows which way is
7
+ * safe. A token-fetching kill switch wants "deny"; a cache toggle wants
8
+ * "leave the cache on". A parser that folded the unknown case into `false`
9
+ * would have made that choice for both of them.
10
+ *
11
+ * 🚨 **Why this exists at all.** Three switches were each a comparison against
12
+ * the literal string `'0'`, so `=false` turned none of them off — measured for
13
+ * `VAT_LINKAUTH_ALLOW_COMMAND`, which *still spawned subprocesses*. Every
14
+ * spelling a human reaches for (`false`, `no`, `off`, `FALSE`, a value with a
15
+ * stray space) failed open. A switch whose off position is one exact string is
16
+ * not a switch.
17
+ *
18
+ * 📍 **Why it lives in `utils`.** It was written next to its first consumer in
19
+ * `resources`, on the rule that utils takes a utility when a SECOND package
20
+ * needs it rather than speculatively. That second package arrived:
21
+ * `packages/cli`'s `projectionStoreSelected()` reads the same `VAT_CACHE` the
22
+ * `resources` parse cache does, and two independent readings of one variable is
23
+ * the defect, not the fix. The four consumers today:
24
+ *
25
+ * | Caller | Variable | Reads `undefined` as | Why |
26
+ * |---|---|---|---|
27
+ * | `link-auth/resolve-token.ts` | `VAT_LINKAUTH_ALLOW_COMMAND` | **deny** | gates a capability — fail closed |
28
+ * | `resources/parse-cache.ts` | `VAT_CACHE` | cache stays on | gates a cache — an unreadable value must not silently change behaviour |
29
+ * | `cli/utils/projection-store.ts` | `VAT_CACHE` | not a veto | same variable, same reading, one implementation |
30
+ * | `cli/utils/projection-store.ts` | `VAT_PROJECTION_STORE` | not a veto | the projection store is ON by default; only an explicit off spelling (or an empty value, which that call site handles before asking) turns it off |
31
+ *
32
+ * Same parser, different safe sides, each chosen at its own call site. That is
33
+ * the contract; do not move a default in here.
34
+ *
35
+ * 🔑 The last two rows are the interesting pair: one variable defaults OFF and
36
+ * the other defaults ON, and both are still read through this one function,
37
+ * because what it answers is not "is this on" but "did the operator say no".
38
+ */
39
+ const TRUE_SPELLINGS = new Set(['1', 'true', 'yes', 'y', 'on']);
40
+ const FALSE_SPELLINGS = new Set(['0', 'false', 'no', 'n', 'off']);
41
+ /**
42
+ * Parse an env value as a boolean.
43
+ *
44
+ * Case-insensitive and surrounding whitespace is trimmed, because a value that
45
+ * arrived through a shell, a CI YAML block, or a `.env` file routinely carries
46
+ * both. Everything else — including the empty string, which is what an unset
47
+ * shell variable expands to — returns `undefined`.
48
+ *
49
+ * @param raw - The raw env value, or `undefined` when the variable is unset
50
+ * @returns `true` / `false` for a recognised spelling; `undefined` otherwise
51
+ */
52
+ export function parseEnvBoolean(raw) {
53
+ if (raw === undefined)
54
+ return undefined;
55
+ const normalized = raw.trim().toLowerCase();
56
+ if (TRUE_SPELLINGS.has(normalized))
57
+ return true;
58
+ if (FALSE_SPELLINGS.has(normalized))
59
+ return false;
60
+ return undefined;
61
+ }
62
+ //# sourceMappingURL=env-flag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-flag.js","sourceRoot":"","sources":["../src/env-flag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AACrF,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AAEvF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,GAAuB;IACrD,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,IAAI,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IAClD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Errno predicates — the two questions every catch site asks of an OS error,
3
+ * answered by the `code` on the error or down its `cause` chain.
4
+ *
5
+ * ⚠️ This module imports NOTHING. It is the leaf that `fs-utils.ts`,
6
+ * `path-utils.ts`, `dirent-kind.ts`, `path-containment.ts` and the rest of the
7
+ * package share; it lived in `fs-utils.ts` until that put three of them in an
8
+ * import cycle (`fs-utils → path-utils → fs-utils` and two more), and a leaf
9
+ * is the one place a shared predicate cannot re-open one. (The cycle was once
10
+ * blamed for a platform-dependent knip verdict on these two names; breaking it
11
+ * changed nothing there — the cause was a missing knip entry, see
12
+ * `docs/contributing/traps.md`, "A subpath module's re-exports flap by platform".)
13
+ */
14
+ /**
15
+ * Whether `error` is the filesystem refusing a path rather than a bug.
16
+ *
17
+ * Deliberately NOT `error instanceof Error`: the point of every caller is to
18
+ * degrade on a hostile tree, and a `TypeError` from a validator is not that.
19
+ * Treating one as environmental turns a real defect into a warning about
20
+ * whichever file it happened on — which makes a tool quietest exactly when it is
21
+ * most wrong.
22
+ *
23
+ * Walks `cause`, because the errno is routinely re-wrapped on its way up. The CLI
24
+ * config loader turns a read failure into `new Error('Failed to load config: …')`;
25
+ * without following the chain the predicate answered "not a filesystem error" for
26
+ * a plain `EACCES`, and an unreadable config aborted a whole `vat audit` run. Any
27
+ * layer that adds context to an OS error defeats a `code`-only check, so the check
28
+ * cannot be `code`-only.
29
+ */
30
+ export declare function isFilesystemAccessError(error: unknown): boolean;
31
+ /**
32
+ * Whether `error` means **there is nothing at this path** — `ENOENT`, or
33
+ * `ENOTDIR` for a path whose component turned out to be a file — and nothing
34
+ * else.
35
+ *
36
+ * This is the narrowing a `try { stat(p) } catch { return null }` is rewritten
37
+ * to under the `no-blind-catch` lint rule: the sentinel stands for *absent*,
38
+ * so only an absence may produce it; a refusal (`EACCES`, `EPERM`, `ELOOP`) or
39
+ * a bug (`TypeError`) is rethrown and stays loud.
40
+ *
41
+ * ⚠️ Deliberately NOT {@link isFilesystemAccessError}. That predicate answers
42
+ * "is this the environment's fault?" and to answer it groups `ENOENT` with
43
+ * `EACCES` — the exact conflation that once turned an unreadable directory
44
+ * into an empty one. The two questions have two predicates on purpose; see
45
+ * also {@link listingFailure}, which makes the same split for `readdir`.
46
+ *
47
+ * Walks `cause` for the same reason its sibling does: the errno is routinely
48
+ * re-wrapped on its way up.
49
+ */
50
+ export declare function isPathAbsentError(error: unknown): boolean;
51
+ //# sourceMappingURL=errno.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errno.d.ts","sourceRoot":"","sources":["../../src/errors/errno.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAwCH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE/D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEzD"}