@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
@@ -1 +1 @@
1
- {"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAmB,EACnB,QAA2C,EAC3C,GAAG,OAAiB;IAEpB,iDAAiD;IACjD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC;IAEzC,iEAAiE;IACjE,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAEpD,kFAAkF;IAClF,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CACjC,WAAW,EACX,UAAU,EACV,WAAW,EACX,cAAc,EACd,QAAQ,EACR,KAAK,EACL,GAAG,OAAO,CACX,CAAC;IAEF,wDAAwD;IAExD,OAAO,aAAa,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACnD,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,OAAO,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAc;IAOnD,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,OAAO;QACL,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,QAAQ,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,GAAG,MAAM,SAAS,CAAC,CAAC,CAAC;QACrF,CAAC;QACD,QAAQ,EAAE,KAAK,IAAI,EAAE;YACnB,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QACD,UAAU,EAAE,KAAK,IAAI,EAAE;YACrB,WAAW,EAAE,CAAC;YACd,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,WAAW,EAAE,CAAC,CAAC;YACzD,8FAA8F;YAC9F,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,4CAA4C;QAC9C,CAAC;QACD,UAAU,EAAE,GAAG,EAAE,CAAC,OAAO;KAC1B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAOlD,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,OAAO;QACL,SAAS,EAAE,GAAG,EAAE;YACd,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,GAAG,MAAM,SAAS,CAAC,CAAC,CAAC;QAChF,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE;YACb,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QACD,UAAU,EAAE,GAAG,EAAE;YACf,WAAW,EAAE,CAAC;YACd,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,WAAW,EAAE,CAAC,CAAC;YACzD,aAAa,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,4CAA4C;QAC9C,CAAC;QACD,UAAU,EAAE,GAAG,EAAE,CAAC,OAAO;KAC1B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Absolute paths for the executables test fixtures spawn.
3
+ *
4
+ * A test that spawns `'git'` or `'node'` by bare name asks the OS to search
5
+ * `PATH`, and a writable directory on `PATH` turns that into a place to plant
6
+ * a binary (the class SonarCloud's S4036 flags). Fixtures resolve the binary
7
+ * ONCE, here, to an absolute path and spawn that: `node` is the process that
8
+ * is running the test (`process.execPath`, the only node whose version the
9
+ * test can vouch for), and `git` is found by walking `PATH`.
10
+ *
11
+ * Why a second `PATH` walk beside `safe-exec.ts`'s `which`: `which` resolves
12
+ * in-process too, but it is a third-party package, and the `./testing` subpath
13
+ * is pinned dependency-free (`subpath-purity.test.ts`) — an adopter's test
14
+ * suite pulls nothing in. This walk answers the same question under that
15
+ * constraint: the first REGULAR FILE on `PATH` named `name` (with a `PATHEXT`
16
+ * extension on Windows) that the process may execute.
17
+ */
18
+ /** The `node` running this test, absolute. */
19
+ export declare const NODE_EXECUTABLE: string;
20
+ /** The names to try in one `PATH` directory: `PATHEXT` variants on Windows, the bare name elsewhere. */
21
+ export declare function executableCandidates(name: string, platform: NodeJS.Platform, pathext: string | undefined): string[];
22
+ /**
23
+ * The first executable named `name` on `PATH`, absolute.
24
+ *
25
+ * @throws {Error} when nothing on `PATH` is executable under that name — a
26
+ * fixture that needs `git` and has none should fail at the first spawn with
27
+ * the reason, not with the OS's `ENOENT` for a bare word.
28
+ */
29
+ export declare function resolveExecutable(name: string): string;
30
+ /** `git`, absolute, resolved on first use and cached for the process. */
31
+ export declare function gitExecutable(): string;
32
+ //# sourceMappingURL=executables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executables.d.ts","sourceRoot":"","sources":["../../src/testing/executables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,8CAA8C;AAC9C,eAAO,MAAM,eAAe,EAAE,MAAyB,CAAC;AAExD,wGAAwG;AACxG,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAInH;AAcD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUtD;AAID,yEAAyE;AACzE,wBAAgB,aAAa,IAAI,MAAM,CAGtC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Absolute paths for the executables test fixtures spawn.
3
+ *
4
+ * A test that spawns `'git'` or `'node'` by bare name asks the OS to search
5
+ * `PATH`, and a writable directory on `PATH` turns that into a place to plant
6
+ * a binary (the class SonarCloud's S4036 flags). Fixtures resolve the binary
7
+ * ONCE, here, to an absolute path and spawn that: `node` is the process that
8
+ * is running the test (`process.execPath`, the only node whose version the
9
+ * test can vouch for), and `git` is found by walking `PATH`.
10
+ *
11
+ * Why a second `PATH` walk beside `safe-exec.ts`'s `which`: `which` resolves
12
+ * in-process too, but it is a third-party package, and the `./testing` subpath
13
+ * is pinned dependency-free (`subpath-purity.test.ts`) — an adopter's test
14
+ * suite pulls nothing in. This walk answers the same question under that
15
+ * constraint: the first REGULAR FILE on `PATH` named `name` (with a `PATHEXT`
16
+ * extension on Windows) that the process may execute.
17
+ */
18
+ import { accessSync, constants, statSync } from 'node:fs';
19
+ import { delimiter } from 'node:path';
20
+ import { isFilesystemAccessError } from '../errors/errno.js';
21
+ import { safePath } from '../path-core.js';
22
+ /** The `node` running this test, absolute. */
23
+ export const NODE_EXECUTABLE = process.execPath;
24
+ /** The names to try in one `PATH` directory: `PATHEXT` variants on Windows, the bare name elsewhere. */
25
+ export function executableCandidates(name, platform, pathext) {
26
+ if (platform !== 'win32')
27
+ return [name];
28
+ const extensions = (pathext ?? '.EXE;.CMD;.BAT;.COM').split(';').filter((ext) => ext !== '');
29
+ return [...extensions.map((ext) => `${name}${ext}`), name];
30
+ }
31
+ /** Is `full` a regular file the process may execute? A directory named `git` passes `X_OK` (search permission) and is not one. */
32
+ function isExecutableFile(full) {
33
+ try {
34
+ accessSync(full, constants.X_OK);
35
+ return statSync(full).isFile();
36
+ }
37
+ catch (error) {
38
+ // Absent or not executable here: the next directory on PATH may have it.
39
+ if (isFilesystemAccessError(error))
40
+ return false;
41
+ throw error;
42
+ }
43
+ }
44
+ /**
45
+ * The first executable named `name` on `PATH`, absolute.
46
+ *
47
+ * @throws {Error} when nothing on `PATH` is executable under that name — a
48
+ * fixture that needs `git` and has none should fail at the first spawn with
49
+ * the reason, not with the OS's `ENOENT` for a bare word.
50
+ */
51
+ export function resolveExecutable(name) {
52
+ const candidates = executableCandidates(name, process.platform, process.env['PATHEXT']);
53
+ for (const dir of (process.env['PATH'] ?? '').split(delimiter)) {
54
+ if (dir === '')
55
+ continue;
56
+ for (const candidate of candidates) {
57
+ const full = safePath.join(dir, candidate);
58
+ if (isExecutableFile(full))
59
+ return full;
60
+ }
61
+ }
62
+ throw new Error(`No executable named "${name}" on PATH (${process.env['PATH'] ?? '<unset>'})`);
63
+ }
64
+ let resolvedGit;
65
+ /** `git`, absolute, resolved on first use and cached for the process. */
66
+ export function gitExecutable() {
67
+ resolvedGit ??= resolveExecutable('git');
68
+ return resolvedGit;
69
+ }
70
+ //# sourceMappingURL=executables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executables.js","sourceRoot":"","sources":["../../src/testing/executables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,8CAA8C;AAC9C,MAAM,CAAC,MAAM,eAAe,GAAW,OAAO,CAAC,QAAQ,CAAC;AAExD,wGAAwG;AACxG,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,QAAyB,EAAE,OAA2B;IACvG,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,CAAC,OAAO,IAAI,qBAAqB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC;IAC7F,OAAO,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;AAC7D,CAAC;AAED,kIAAkI;AAClI,SAAS,gBAAgB,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,yEAAyE;QACzE,IAAI,uBAAuB,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACjD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,UAAU,GAAG,oBAAoB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IACxF,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/D,IAAI,GAAG,KAAK,EAAE;YAAE,SAAS;QACzB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAC3C,IAAI,gBAAgB,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,cAAc,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC;AACjG,CAAC;AAED,IAAI,WAA+B,CAAC;AAEpC,yEAAyE;AACzE,MAAM,UAAU,aAAa;IAC3B,WAAW,KAAK,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACzC,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * One hostile fixture tree, built the same way for every sink.
3
+ *
4
+ * A correctness sweep found a delete, a copy and an uninstall that
5
+ * each walked out of their root, and found them by hand-building the same
6
+ * shapes — a symlink pointing out, a symlink pointing back at the root, a
7
+ * `..`-named entry, an unreadable directory, a traversal name — one throwaway
8
+ * fixture per probe. This module
9
+ * is that fixture, once, so a sink's test says `buildHostileTree(base)` and
10
+ * `it.each(HOSTILE_NAMES)` and is refusing the shapes the next sink's test is
11
+ * refusing too. A shape added here reaches every sink that uses it.
12
+ *
13
+ * ⛔ Framework-free, like everything under `testing/`: no `vitest` import, so
14
+ * the `./testing` subpath keeps the empty third-party set its purity pin
15
+ * asserts. Fields that the host cannot build are `null` — route those through
16
+ * the suite's own `skip()` so the skip is visible in the report.
17
+ */
18
+ /** The names a sink must refuse when they arrive as "the entry to act on". */
19
+ export declare const HOSTILE_NAMES: readonly string[];
20
+ /** The tree {@link buildHostileTree} plants, every path absolute and forward-slashed. */
21
+ export interface HostileTree {
22
+ /** The trusted root — the directory a sink must stay inside. */
23
+ readonly root: string;
24
+ /** A regular directory under the root; `root/member`. */
25
+ readonly member: string;
26
+ /** A member whose NAME begins with two dots; `root/..cache`. Legitimate. */
27
+ readonly dotdotNamed: string;
28
+ /** A sibling of the root, outside it. */
29
+ readonly outside: string;
30
+ /** `outside/victim` — holds `secret.txt`; a traversal that succeeds deletes or copies this. */
31
+ readonly victim: string;
32
+ /** `root/link-out` → `outside/victim`, or `null` where the host cannot symlink. */
33
+ readonly linkOut: string | null;
34
+ /** `root/link-in` → `root/member`, or `null` where the host cannot symlink. */
35
+ readonly linkIn: string | null;
36
+ /** `root/dangling` → a path that does not exist, or `null` where the host cannot symlink. */
37
+ readonly dangling: string | null;
38
+ /** `root/loop` → `root` itself — a walk that follows it never ends — or `null` where the host cannot symlink. */
39
+ readonly linkLoop: string | null;
40
+ /** A link OUTSIDE the tree that points AT the root, or `null` where the host cannot symlink. */
41
+ readonly rootAlias: string | null;
42
+ /** `root/unreadable`, mode 000, or `null` where the host cannot deny reads. */
43
+ readonly unreadable: string | null;
44
+ /** A directory whose own name is 200 characters, under the root; `null` where the OS refused it. */
45
+ readonly longPath: string | null;
46
+ /** Restore modes and remove everything this call created. Idempotent. */
47
+ cleanup(): void;
48
+ }
49
+ /**
50
+ * Plant the hostile tree under `base`, which must exist and be empty enough
51
+ * to take `root`, `outside` and `root-alias` as direct children.
52
+ *
53
+ * @param base - A scratch directory the caller owns (a per-test temp dir)
54
+ * @returns The tree, with `null` for every shape this host cannot build
55
+ */
56
+ export declare function buildHostileTree(base: string): HostileTree;
57
+ /** A hostile tree replanted per test, driven from the suite's own hooks. */
58
+ export interface HostileTreePerTest {
59
+ /** Mint a scratch root and plant a fresh tree in it. Drive from `beforeEach`. */
60
+ plant: () => void;
61
+ /** Tear the tree down and remove the scratch root. Drive from `afterEach`. */
62
+ clear: () => void;
63
+ /** The tree planted by the most recent {@link HostileTreePerTest.plant}. */
64
+ tree: () => HostileTree;
65
+ }
66
+ /**
67
+ * Hold a per-test hostile tree, so a suite's wiring is three lines:
68
+ * `const hostile = hostileTreePerTest('x'); beforeEach(hostile.plant); afterEach(hostile.clear);`.
69
+ *
70
+ * Same shape and same reasons as `replantableCorpus`: the tree comes back
71
+ * through a GETTER because it is reminted per test, `plant` clears any tree
72
+ * still standing so nested `describe`s do not leak one, and `tree()` before
73
+ * `plant()` throws by name rather than surfacing as an undefined read.
74
+ *
75
+ * @param prefix - `mkdtemp` prefix for the scratch root, so a leak names its suite
76
+ * @returns Plant/clear/tree, to be driven from the caller's own hooks
77
+ */
78
+ export declare function hostileTreePerTest(prefix: string): HostileTreePerTest;
79
+ //# sourceMappingURL=hostile-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostile-tree.d.ts","sourceRoot":"","sources":["../../src/testing/hostile-tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAYH,8EAA8E;AAC9E,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAW1C,CAAC;AAEF,yFAAyF;AACzF,MAAM,WAAW,WAAW;IAC1B,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+FAA+F;IAC/F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,6FAA6F;IAC7F,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iHAAiH;IACjH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gGAAgG;IAChG,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,oGAAoG;IACpG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,yEAAyE;IACzE,OAAO,IAAI,IAAI,CAAC;CACjB;AAuBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CA8D1D;AAED,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IACjC,iFAAiF;IACjF,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,4EAA4E;IAC5E,IAAI,EAAE,MAAM,WAAW,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAuBrE"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * One hostile fixture tree, built the same way for every sink.
3
+ *
4
+ * A correctness sweep found a delete, a copy and an uninstall that
5
+ * each walked out of their root, and found them by hand-building the same
6
+ * shapes — a symlink pointing out, a symlink pointing back at the root, a
7
+ * `..`-named entry, an unreadable directory, a traversal name — one throwaway
8
+ * fixture per probe. This module
9
+ * is that fixture, once, so a sink's test says `buildHostileTree(base)` and
10
+ * `it.each(HOSTILE_NAMES)` and is refusing the shapes the next sink's test is
11
+ * refusing too. A shape added here reaches every sink that uses it.
12
+ *
13
+ * ⛔ Framework-free, like everything under `testing/`: no `vitest` import, so
14
+ * the `./testing` subpath keeps the empty third-party set its purity pin
15
+ * asserts. Fields that the host cannot build are `null` — route those through
16
+ * the suite's own `skip()` so the skip is visible in the report.
17
+ */
18
+ import { chmodSync, rmSync, writeFileSync } from 'node:fs';
19
+ import { isFilesystemAccessError } from '../errors/errno.js';
20
+ import { mkdirSyncReal, safePath } from '../path-utils.js';
21
+ import { createSymlink, symlinkCapability } from '../test-helpers.js';
22
+ import { CANNOT_DENY_READS } from './platform-gates.js';
23
+ import { createTempDir, removeTempDir } from './temp-dir.js';
24
+ /** The names a sink must refuse when they arrive as "the entry to act on". */
25
+ export const HOSTILE_NAMES = [
26
+ '..',
27
+ '../victim',
28
+ '../../victim',
29
+ 'a/../../victim',
30
+ String.raw `..\victim`,
31
+ '.',
32
+ '',
33
+ '/victim',
34
+ String.raw `C:\victim`,
35
+ `nul${String.fromCodePoint(0)}byte`,
36
+ ];
37
+ /** A link, or `null` when this host cannot make one (the capability probe said so). */
38
+ function tryLink(cap, target, link, type) {
39
+ if (cap === null)
40
+ return null;
41
+ createSymlink(cap, target, link, type);
42
+ return link;
43
+ }
44
+ function tryMkdir(dir) {
45
+ try {
46
+ mkdirSyncReal(dir);
47
+ return dir;
48
+ }
49
+ catch (error) {
50
+ // Only a name the OS will not take is "cannot build" — `ENAMETOOLONG` on
51
+ // a host with a shorter limit. Anything else is a broken fixture.
52
+ if (error instanceof Error && 'code' in error && error.code === 'ENAMETOOLONG') {
53
+ return null;
54
+ }
55
+ throw error;
56
+ }
57
+ }
58
+ /**
59
+ * Plant the hostile tree under `base`, which must exist and be empty enough
60
+ * to take `root`, `outside` and `root-alias` as direct children.
61
+ *
62
+ * @param base - A scratch directory the caller owns (a per-test temp dir)
63
+ * @returns The tree, with `null` for every shape this host cannot build
64
+ */
65
+ export function buildHostileTree(base) {
66
+ const root = safePath.join(base, 'root');
67
+ const member = safePath.join(root, 'member');
68
+ const dotdotNamed = safePath.join(root, '..cache');
69
+ const outside = safePath.join(base, 'outside');
70
+ const victim = safePath.join(outside, 'victim');
71
+ mkdirSyncReal(member, { recursive: true });
72
+ mkdirSyncReal(safePath.join(root, 'nested', 'deep'), { recursive: true });
73
+ mkdirSyncReal(dotdotNamed);
74
+ mkdirSyncReal(victim, { recursive: true });
75
+ writeFileSync(safePath.join(victim, 'secret.txt'), 'TOKEN=abc\n');
76
+ writeFileSync(safePath.join(member, 'file.txt'), 'member\n');
77
+ const cap = symlinkCapability();
78
+ const linkOut = tryLink(cap, victim, safePath.join(root, 'link-out'), 'dir');
79
+ const linkIn = tryLink(cap, member, safePath.join(root, 'link-in'), 'dir');
80
+ const dangling = tryLink(cap, safePath.join(root, 'does-not-exist'), safePath.join(root, 'dangling'), 'file');
81
+ const linkLoop = tryLink(cap, root, safePath.join(root, 'loop'), 'dir');
82
+ const rootAlias = tryLink(cap, root, safePath.join(base, 'root-alias'), 'dir');
83
+ let unreadable = null;
84
+ if (!CANNOT_DENY_READS) {
85
+ unreadable = safePath.join(root, 'unreadable');
86
+ mkdirSyncReal(unreadable);
87
+ writeFileSync(safePath.join(unreadable, 'hidden.txt'), 'x');
88
+ chmodSync(unreadable, 0o000);
89
+ }
90
+ const longPath = tryMkdir(safePath.join(root, 'L'.repeat(200)));
91
+ let cleaned = false;
92
+ return {
93
+ root,
94
+ member,
95
+ dotdotNamed,
96
+ outside,
97
+ victim,
98
+ linkOut,
99
+ linkIn,
100
+ dangling,
101
+ linkLoop,
102
+ rootAlias,
103
+ unreadable,
104
+ longPath,
105
+ cleanup: () => {
106
+ if (cleaned)
107
+ return;
108
+ cleaned = true;
109
+ if (unreadable !== null) {
110
+ try {
111
+ chmodSync(unreadable, 0o700);
112
+ }
113
+ catch (error) {
114
+ // Already removed by the subject under test, which a delete sink is
115
+ // entitled to do; a refusal to restore anything else stays loud.
116
+ if (!isFilesystemAccessError(error))
117
+ throw error;
118
+ }
119
+ }
120
+ for (const dir of [root, outside, rootAlias]) {
121
+ if (dir !== null)
122
+ rmSync(dir, { recursive: true, force: true });
123
+ }
124
+ },
125
+ };
126
+ }
127
+ /**
128
+ * Hold a per-test hostile tree, so a suite's wiring is three lines:
129
+ * `const hostile = hostileTreePerTest('x'); beforeEach(hostile.plant); afterEach(hostile.clear);`.
130
+ *
131
+ * Same shape and same reasons as `replantableCorpus`: the tree comes back
132
+ * through a GETTER because it is reminted per test, `plant` clears any tree
133
+ * still standing so nested `describe`s do not leak one, and `tree()` before
134
+ * `plant()` throws by name rather than surfacing as an undefined read.
135
+ *
136
+ * @param prefix - `mkdtemp` prefix for the scratch root, so a leak names its suite
137
+ * @returns Plant/clear/tree, to be driven from the caller's own hooks
138
+ */
139
+ export function hostileTreePerTest(prefix) {
140
+ let scratch;
141
+ let planted;
142
+ const clear = () => {
143
+ planted?.cleanup();
144
+ planted = undefined;
145
+ if (scratch !== undefined)
146
+ removeTempDir(scratch);
147
+ scratch = undefined;
148
+ };
149
+ return {
150
+ plant: () => {
151
+ clear();
152
+ scratch = createTempDir(prefix);
153
+ planted = buildHostileTree(scratch);
154
+ },
155
+ clear,
156
+ tree: () => {
157
+ if (planted === undefined) {
158
+ throw new Error(`hostileTreePerTest('${prefix}'): tree() before plant() — the suite is missing its beforeEach`);
159
+ }
160
+ return planted;
161
+ },
162
+ };
163
+ }
164
+ //# sourceMappingURL=hostile-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostile-tree.js","sourceRoot":"","sources":["../../src/testing/hostile-tree.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The host facts a fixture has to ask before it can build a refusal.
3
+ *
4
+ * ⛔ Framework-free, like everything under `testing/`: no `vitest` import, so
5
+ * the `./testing` subpath keeps the empty third-party set its purity pin
6
+ * asserts. Route a `true` here through the suite's own `skip()` so the skip is
7
+ * visible in the report — a fixture that silently no-ops is a passing test for
8
+ * a property nobody exercised.
9
+ */
10
+ /**
11
+ * Whether a `chmod 000` on this host denies anything.
12
+ *
13
+ * Two hosts read every mode as readable: Windows, where POSIX mode bits do not
14
+ * bind at all, and a POSIX process running as root, which bypasses them. On
15
+ * either, a fixture directory made unreadable is still readable, so a test of
16
+ * "the walker refuses what it cannot list" would pass by listing it.
17
+ *
18
+ * ⚠️ Evaluated ONCE at module load, as a constant rather than a function, on
19
+ * purpose: the answer is a property of the process's identity and platform,
20
+ * neither of which changes mid-run, and a constant is what `it.skipIf(...)`
21
+ * takes. This one line used to be spelled in 28 test files under three names
22
+ * (`CANNOT_DENY_READS`, `PERMISSIONS_ENFORCED`, inline), which is 28 places
23
+ * for the `getuid` guard to drift.
24
+ */
25
+ export declare const CANNOT_DENY_READS: boolean;
26
+ /**
27
+ * The positive spelling, for the suites that phrase the gate as "only run
28
+ * where modes bind". Same fact, no second evaluation.
29
+ */
30
+ export declare const PERMISSIONS_ENFORCED: boolean;
31
+ //# sourceMappingURL=platform-gates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-gates.d.ts","sourceRoot":"","sources":["../../src/testing/platform-gates.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,EAAE,OACkE,CAAC;AAEnG;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,OAA4B,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The host facts a fixture has to ask before it can build a refusal.
3
+ *
4
+ * ⛔ Framework-free, like everything under `testing/`: no `vitest` import, so
5
+ * the `./testing` subpath keeps the empty third-party set its purity pin
6
+ * asserts. Route a `true` here through the suite's own `skip()` so the skip is
7
+ * visible in the report — a fixture that silently no-ops is a passing test for
8
+ * a property nobody exercised.
9
+ */
10
+ /**
11
+ * Whether a `chmod 000` on this host denies anything.
12
+ *
13
+ * Two hosts read every mode as readable: Windows, where POSIX mode bits do not
14
+ * bind at all, and a POSIX process running as root, which bypasses them. On
15
+ * either, a fixture directory made unreadable is still readable, so a test of
16
+ * "the walker refuses what it cannot list" would pass by listing it.
17
+ *
18
+ * ⚠️ Evaluated ONCE at module load, as a constant rather than a function, on
19
+ * purpose: the answer is a property of the process's identity and platform,
20
+ * neither of which changes mid-run, and a constant is what `it.skipIf(...)`
21
+ * takes. This one line used to be spelled in 28 test files under three names
22
+ * (`CANNOT_DENY_READS`, `PERMISSIONS_ENFORCED`, inline), which is 28 places
23
+ * for the `getuid` guard to drift.
24
+ */
25
+ export const CANNOT_DENY_READS = process.platform === 'win32' || (typeof process.getuid === 'function' && process.getuid() === 0);
26
+ /**
27
+ * The positive spelling, for the suites that phrase the gate as "only run
28
+ * where modes bind". Same fact, no second evaluation.
29
+ */
30
+ export const PERMISSIONS_ENFORCED = !CANNOT_DENY_READS;
31
+ //# sourceMappingURL=platform-gates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-gates.js","sourceRoot":"","sources":["../../src/testing/platform-gates.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAC5B,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,OAAO,OAAO,CAAC,MAAM,KAAK,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AAEnG;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAY,CAAC,iBAAiB,CAAC"}