@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 @@
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/archive/archive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * What an archive holds, and the ONE policy for which archives VAT extracts — decided from the
3
+ * entry list alone, before anything is written. Pure: nothing here reads or writes.
4
+ */
5
+ import { VatError } from '../errors/vat-error.js';
6
+ /** The archive formats VAT reads: a ZIP, or a tar stream (gzipped or plain). */
7
+ export type ArchiveFormat = 'zip' | 'tar';
8
+ /** What one entry of an archive is. `other` is a device, a FIFO, a socket or a type VAT does not know. */
9
+ export type ArchiveEntryKind = 'file' | 'directory' | 'link' | 'hardlink' | 'other';
10
+ /** One entry of an archive, as the archive spells it. */
11
+ export interface ArchiveEntry {
12
+ /** The entry's name as the archive spells it, every backslash read as `/` ({@link entryNameOf}). */
13
+ readonly name: string;
14
+ readonly kind: ArchiveEntryKind;
15
+ /** The uncompressed size the entry's header declares, in bytes; `0` for anything but a file. */
16
+ readonly size: number;
17
+ }
18
+ /** How much an archive may hold. Every reader is given one: there is no default, because an omitted bound is the failure. */
19
+ export interface ArchiveLimits {
20
+ /** The most entries — files, directories and everything else — the archive may list. */
21
+ readonly maxEntries: number;
22
+ /** The most bytes its files may expand to, summed. */
23
+ readonly maxBytes: number;
24
+ }
25
+ /** The code of every {@link ArchiveRefusedError}. */
26
+ export declare const ARCHIVE_REFUSED_CODE = "ARCHIVE_REFUSED";
27
+ /**
28
+ * Why an archive was refused:
29
+ * - `unreadable`: its bytes are no archive of the format;
30
+ * - `unsupported`: it IS an archive, and one VAT will not take — a ZIP64 ZIP, an end record or
31
+ * directory two readers would read differently, or a tarball cut short inside an entry
32
+ * (`entry` names it). Never passed on by any lane, where `unreadable` bytes may be. One entry
33
+ * that does not inflate or hold what it declares, asked for after the archive opened, is
34
+ * {@link ArchiveEntryReadError} instead;
35
+ * - `link`, `hardlink`, `special`: it holds an entry that is not a file or a directory;
36
+ * - `unsafe-name`: an entry is named outside the directory it is extracted into;
37
+ * - `name-clash`: two entries are one name, or one is a file with another at or under it;
38
+ * - `too-many-entries`, `too-large`: it is past an {@link ArchiveLimits} bound.
39
+ */
40
+ export type ArchiveRefusalReason = 'unreadable' | 'unsupported' | 'link' | 'hardlink' | 'special' | 'unsafe-name' | 'name-clash' | 'too-many-entries' | 'too-large';
41
+ /** An archive VAT will not read, extract or pass on: the input's refusal, never the run's. */
42
+ export declare class ArchiveRefusedError extends VatError {
43
+ readonly reason: ArchiveRefusalReason;
44
+ /**
45
+ * The entry the refusal is about, as the archive spells it: the first offending one for a
46
+ * `link`, `hardlink`, `special`, `unsafe-name` or `name-clash`, and the cut-short entry of an
47
+ * `unsupported` tarball — the archive is refused as a whole all the same. None when no one entry
48
+ * is to blame (`unreadable`, a limit, a ZIP structure two readers would read differently).
49
+ */
50
+ readonly entry: string | undefined;
51
+ /**
52
+ * @param archive - What the operator named: the archive's path or URL
53
+ * @param refusal - Why, and the entry it is about
54
+ */
55
+ constructor(archive: string, refusal: {
56
+ readonly reason: ArchiveRefusalReason;
57
+ readonly entry?: string;
58
+ readonly why: string;
59
+ }, options?: ErrorOptions);
60
+ }
61
+ /** The code of every {@link ArchiveEntryReadError}. */
62
+ export declare const ARCHIVE_ENTRY_UNREADABLE_CODE = "ARCHIVE_ENTRY_UNREADABLE";
63
+ /**
64
+ * The refusal of ONE entry an opened archive was asked to read: it does not inflate, or does not
65
+ * hold what it declares. Its own code ({@link ARCHIVE_ENTRY_UNREADABLE_CODE}), so a lane that may
66
+ * skip one member tells it from every refusal of the whole archive by
67
+ * {@link isArchiveEntryReadRefusal} — the brand and the code, never the prototype chain and never
68
+ * whether an `entry` happens to be set (a clash, a link and a cut-short tarball name one too).
69
+ */
70
+ export declare class ArchiveEntryReadError extends VatError {
71
+ readonly entry: string;
72
+ /**
73
+ * @param archive - What the operator named: the archive's path or URL
74
+ * @param entry - The entry, as the archive spells it
75
+ * @param what - What is wrong with it, completing "its entry `x` …"
76
+ */
77
+ constructor(archive: string, entry: string, what: string, options?: ErrorOptions);
78
+ }
79
+ /**
80
+ * Whether `error` is the archive module refusing one entry's read ({@link ArchiveEntryReadError}):
81
+ * by the brand and {@link ARCHIVE_ENTRY_UNREADABLE_CODE}, so a `dist` copy of the class answers as a
82
+ * `src` one does.
83
+ */
84
+ export declare function isArchiveEntryReadRefusal(error: unknown): error is ArchiveEntryReadError;
85
+ /** A refusal before it names its archive: what {@link archiveEntryRefusal} answers. */
86
+ export interface EntryRefusal {
87
+ readonly reason: ArchiveRefusalReason;
88
+ readonly entry: string;
89
+ readonly why: string;
90
+ }
91
+ /**
92
+ * An entry's name as both readers hand it on, on every host: the archive's spelling with every
93
+ * backslash read as `/` — the separator VAT reads it as everywhere, in a tarball as in a ZIP. The
94
+ * tar library already does this on win32, and only there; doing it here for both formats on every
95
+ * host keeps one listing, so a refusal names an entry the same way wherever VAT runs.
96
+ *
97
+ * @param spelled - The name as the format's library decoded it
98
+ * @returns The name with forward slashes
99
+ */
100
+ export declare function entryNameOf(spelled: string): string;
101
+ /**
102
+ * Where an entry lands under the directory it is extracted into: its segments, a backslash read
103
+ * as a separator on every host (as a ZIP written on Windows spells one), empty and `.` segments
104
+ * dropped. Only for a name {@link unsafeNameReason} accepts.
105
+ */
106
+ export declare function placeOf(name: string): string[];
107
+ /**
108
+ * The first reason `entries` cannot be extracted, or `undefined` when every entry may be. An
109
+ * archive is extracted whole or not at all, so one offending entry refuses it:
110
+ *
111
+ * - an entry that is not a regular file or a directory — a symbolic link, a hard link, a device,
112
+ * a FIFO (`npm pack` and a skill ZIP hold none);
113
+ * - a name that is absolute, begins with a drive letter, is a UNC path, holds a `..` segment or a
114
+ * NUL (a backslash is read as a separator on every host); or one with a segment Windows cannot
115
+ * hold as spelled — a `:`, one of `<` `>` `"` `|` `?` `*`, a control character (code points
116
+ * 1–31), a trailing `.` or space, a device name (`CON`, `com1.txt`) — on every host;
117
+ * - two entries that are one name — exactly, or once folded as a case-insensitive or
118
+ * normalising volume folds them ({@link foldedSegment}) — or a file with another entry under it.
119
+ *
120
+ * @param entries - Every entry of the archive, in archive order
121
+ * @returns The refusal of the first offending entry, in archive order
122
+ */
123
+ export declare function archiveEntryRefusal(entries: readonly ArchiveEntry[]): EntryRefusal | undefined;
124
+ /**
125
+ * Refuse `archive` when its entries cannot all be extracted ({@link archiveEntryRefusal}).
126
+ *
127
+ * @param archive - What the operator named, for the message
128
+ * @param entries - Every entry of the archive, in archive order
129
+ * @throws ArchiveRefusedError naming the first offending entry
130
+ */
131
+ export declare function assertArchiveExtractable(archive: string, entries: readonly ArchiveEntry[]): void;
132
+ //# sourceMappingURL=entries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entries.d.ts","sourceRoot":"","sources":["../../src/archive/entries.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAc,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAI9D,gFAAgF;AAChF,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,KAAK,CAAC;AAE1C,0GAA0G;AAC1G,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAEpF,yDAAyD;AACzD,MAAM,WAAW,YAAY;IAC3B,oGAAoG;IACpG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,gGAAgG;IAChG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,6HAA6H;AAC7H,MAAM,WAAW,aAAa;IAC5B,wFAAwF;IACxF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AAEtD;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,YAAY,GAAG,kBAAkB,GAAG,WAAW,CAAC;AAOpK,8FAA8F;AAC9F,qBAAa,mBAAoB,SAAQ,QAAQ;IAC/C,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnC;;;OAGG;gBACS,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,CAAC,EAAE,YAAY;CAKvJ;AAED,uDAAuD;AACvD,eAAO,MAAM,6BAA6B,6BAA6B,CAAC;AAExE;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,QAAQ;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;gBACS,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIjF;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qBAAqB,CAExF;AAED,uFAAuF;AACvF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAKD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE9C;AA0GD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,YAAY,GAAG,SAAS,CAO9F;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAGhG"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * What an archive holds, and the ONE policy for which archives VAT extracts — decided from the
3
+ * entry list alone, before anything is written. Pure: nothing here reads or writes.
4
+ */
5
+ import { isVatError, VatError } from '../errors/vat-error.js';
6
+ import { foldedSegment } from '../name-fold.js';
7
+ import { hasParentTraversalSegment, toForwardSlashAnyPlatform } from '../path-core.js';
8
+ /** The code of every {@link ArchiveRefusedError}. */
9
+ export const ARCHIVE_REFUSED_CODE = 'ARCHIVE_REFUSED';
10
+ /** The sentence every archive refusal is: the archive named, then why. */
11
+ function refusalMessage(archive, why) {
12
+ return `${archive} is not an archive VAT accepts, nothing was changed: ${why}`;
13
+ }
14
+ /** An archive VAT will not read, extract or pass on: the input's refusal, never the run's. */
15
+ export class ArchiveRefusedError extends VatError {
16
+ reason;
17
+ /**
18
+ * The entry the refusal is about, as the archive spells it: the first offending one for a
19
+ * `link`, `hardlink`, `special`, `unsafe-name` or `name-clash`, and the cut-short entry of an
20
+ * `unsupported` tarball — the archive is refused as a whole all the same. None when no one entry
21
+ * is to blame (`unreadable`, a limit, a ZIP structure two readers would read differently).
22
+ */
23
+ entry;
24
+ /**
25
+ * @param archive - What the operator named: the archive's path or URL
26
+ * @param refusal - Why, and the entry it is about
27
+ */
28
+ constructor(archive, refusal, options) {
29
+ super(ARCHIVE_REFUSED_CODE, refusalMessage(archive, refusal.why), options);
30
+ this.reason = refusal.reason;
31
+ this.entry = refusal.entry;
32
+ }
33
+ }
34
+ /** The code of every {@link ArchiveEntryReadError}. */
35
+ export const ARCHIVE_ENTRY_UNREADABLE_CODE = 'ARCHIVE_ENTRY_UNREADABLE';
36
+ /**
37
+ * The refusal of ONE entry an opened archive was asked to read: it does not inflate, or does not
38
+ * hold what it declares. Its own code ({@link ARCHIVE_ENTRY_UNREADABLE_CODE}), so a lane that may
39
+ * skip one member tells it from every refusal of the whole archive by
40
+ * {@link isArchiveEntryReadRefusal} — the brand and the code, never the prototype chain and never
41
+ * whether an `entry` happens to be set (a clash, a link and a cut-short tarball name one too).
42
+ */
43
+ export class ArchiveEntryReadError extends VatError {
44
+ entry;
45
+ /**
46
+ * @param archive - What the operator named: the archive's path or URL
47
+ * @param entry - The entry, as the archive spells it
48
+ * @param what - What is wrong with it, completing "its entry `x` …"
49
+ */
50
+ constructor(archive, entry, what, options) {
51
+ super(ARCHIVE_ENTRY_UNREADABLE_CODE, refusalMessage(archive, `its entry \`${entry}\` ${what}`), options);
52
+ this.entry = entry;
53
+ }
54
+ }
55
+ /**
56
+ * Whether `error` is the archive module refusing one entry's read ({@link ArchiveEntryReadError}):
57
+ * by the brand and {@link ARCHIVE_ENTRY_UNREADABLE_CODE}, so a `dist` copy of the class answers as a
58
+ * `src` one does.
59
+ */
60
+ export function isArchiveEntryReadRefusal(error) {
61
+ return isVatError(error, ARCHIVE_ENTRY_UNREADABLE_CODE);
62
+ }
63
+ /**
64
+ * An entry's name as both readers hand it on, on every host: the archive's spelling with every
65
+ * backslash read as `/` — the separator VAT reads it as everywhere, in a tarball as in a ZIP. The
66
+ * tar library already does this on win32, and only there; doing it here for both formats on every
67
+ * host keeps one listing, so a refusal names an entry the same way wherever VAT runs.
68
+ *
69
+ * @param spelled - The name as the format's library decoded it
70
+ * @returns The name with forward slashes
71
+ */
72
+ export function entryNameOf(spelled) {
73
+ return toForwardSlashAnyPlatform(spelled);
74
+ }
75
+ /** A Windows drive prefix (`C:`), which makes a name absolute or drive-relative there. */
76
+ const DRIVE_PREFIX = /^[A-Za-z]:/;
77
+ /**
78
+ * Where an entry lands under the directory it is extracted into: its segments, a backslash read
79
+ * as a separator on every host (as a ZIP written on Windows spells one), empty and `.` segments
80
+ * dropped. Only for a name {@link unsafeNameReason} accepts.
81
+ */
82
+ export function placeOf(name) {
83
+ return toForwardSlashAnyPlatform(name).split('/').filter((segment) => segment !== '' && segment !== '.');
84
+ }
85
+ /**
86
+ * A Windows device name, whatever follows it after a `.` and whatever its case: `CON`, `prn.txt`,
87
+ * `Aux.tar.gz` (Microsoft: "NUL.txt and NUL.tar.gz are both equivalent to NUL"), `COM1`…`COM9`,
88
+ * `LPT1`…`LPT9`, and the superscript-digit forms `COM¹` `LPT³`, which Windows reads as digits. A
89
+ * space before the `.` is over-refused on purpose: Win32 drops it, so `con .md` may be `CON`.
90
+ *
91
+ * @vendor-claim reviewed=2026-10-26 verify=Re-read https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file — "File and Directory Names", the reserved-names list (item 9) and the trailing space or period rule (item 10)
92
+ */
93
+ const WINDOWS_DEVICE_NAME = /^(?:con|prn|aux|nul|com[1-9¹²³]|lpt[1-9¹²³]) *(?:\.|$)/i;
94
+ /**
95
+ * The other characters Windows reserves in a name (item 1 of the same page): `<` `>` `"` `|` `?`
96
+ * `*`, and the code points 1–31. (NUL, code point 0, has its own refusal; `/` and `\` are
97
+ * separators; `:` has its own reason.)
98
+ */
99
+ const WINDOWS_RESERVED_CHARACTERS = new Set(['<', '>', '"', '|', '?', '*', ...Array.from({ length: 31 }, (_unused, index) => String.fromCodePoint(index + 1))]);
100
+ /**
101
+ * Why one segment of a name is one Windows cannot hold as spelled, or `undefined`. Refused on EVERY
102
+ * host, so one archive has one verdict wherever VAT runs: on NTFS a `:` names a stream of the file
103
+ * before it (`notes:v2.md` writes into `notes`), a reserved character cannot be written at all, a
104
+ * device name opens the device, and a trailing `.` or space is dropped from the name a Win32 tool sees.
105
+ */
106
+ function windowsSegmentReason(segment) {
107
+ if (segment.includes(':'))
108
+ return 'holds a `:`, which on NTFS names a stream of the file before it';
109
+ if ([...segment].some((character) => WINDOWS_RESERVED_CHARACTERS.has(character)))
110
+ return 'holds a character Windows does not allow in a name (`<` `>` `"` `|` `?` `*`, or a control character)';
111
+ if (segment.endsWith('.') || segment.endsWith(' '))
112
+ return 'ends in a `.` or a space, which Windows drops from a name';
113
+ return WINDOWS_DEVICE_NAME.test(segment) ? 'is a Windows device name' : undefined;
114
+ }
115
+ /** Why `name` would land outside the extraction directory, or somewhere other than it says, on some host; or `undefined`. */
116
+ function unsafeNameReason(name) {
117
+ if (name.includes('\0'))
118
+ return 'holds a NUL character';
119
+ const spelled = toForwardSlashAnyPlatform(name);
120
+ if (spelled.startsWith('/'))
121
+ return 'is an absolute path';
122
+ if (DRIVE_PREFIX.test(spelled))
123
+ return 'begins with a drive letter';
124
+ if (hasParentTraversalSegment(name))
125
+ return 'holds a `..` segment';
126
+ for (const segment of placeOf(name)) {
127
+ const reason = windowsSegmentReason(segment);
128
+ if (reason !== undefined)
129
+ return reason;
130
+ }
131
+ return undefined;
132
+ }
133
+ /** What each entry kind that is not extracted is called, and its reason. */
134
+ const UNEXTRACTED = {
135
+ link: { reason: 'link', what: 'a symbolic link' },
136
+ hardlink: { reason: 'hardlink', what: 'a hard link' },
137
+ other: { reason: 'special', what: 'a device, a named pipe or another special file' },
138
+ };
139
+ /** The refusal of an entry for what it is or how it is named, or `undefined`. */
140
+ function entryRefusal(entry) {
141
+ if (entry.kind !== 'file' && entry.kind !== 'directory') {
142
+ const { reason, what } = UNEXTRACTED[entry.kind];
143
+ return { reason, entry: entry.name, why: `its entry \`${entry.name}\` is ${what}, and an archive may hold only files and directories` };
144
+ }
145
+ const unsafe = unsafeNameReason(entry.name);
146
+ if (unsafe !== undefined)
147
+ return { reason: 'unsafe-name', entry: entry.name, why: `its entry \`${entry.name}\` ${unsafe}, so it names no place inside the archive that every host can write` };
148
+ if (entry.kind === 'file' && placeOf(entry.name).length === 0) {
149
+ return { reason: 'unsafe-name', entry: entry.name, why: `its entry \`${entry.name}\` is a file that names no place inside the archive` };
150
+ }
151
+ return undefined;
152
+ }
153
+ /**
154
+ * Claim every place `entry` needs — each directory above it, and its own — refusing the first one
155
+ * an earlier entry holds differently: under another spelling of one folded name, or as a file
156
+ * where this entry needs a directory (or the reverse), or as the very same file.
157
+ */
158
+ function claimPlaces(entry, claims) {
159
+ const place = placeOf(entry.name);
160
+ for (let depth = 1; depth <= place.length; depth += 1) {
161
+ const segments = place.slice(0, depth);
162
+ const kind = depth === place.length && entry.kind === 'file' ? 'file' : 'directory';
163
+ const key = segments.map((segment) => foldedSegment(segment)).join('/');
164
+ const spelled = segments.join('/');
165
+ const held = claims.get(key);
166
+ if (held === undefined) {
167
+ claims.set(key, { spelled, kind, entry: entry.name });
168
+ }
169
+ else if (held.spelled !== spelled) {
170
+ // A `:` and a trailing dot or space were refused with the name, so only the case and Unicode folds are left.
171
+ return {
172
+ reason: 'name-clash',
173
+ entry: entry.name,
174
+ why: `its entries \`${held.entry}\` and \`${entry.name}\` are one name where a volume folds letter case or Unicode form (\`${held.spelled}\` and \`${spelled}\`), so one would overwrite the other`,
175
+ };
176
+ }
177
+ else if (held.kind === 'file' || kind === 'file') {
178
+ const why = held.kind === kind
179
+ ? `it lists \`${entry.name}\` twice`
180
+ : `it holds both \`${held.entry}\` and \`${entry.name}\`, and \`${spelled}\` is a file in one and a directory in the other, so no directory can hold the two`;
181
+ return { reason: 'name-clash', entry: entry.name, why };
182
+ }
183
+ }
184
+ return undefined;
185
+ }
186
+ /**
187
+ * The first reason `entries` cannot be extracted, or `undefined` when every entry may be. An
188
+ * archive is extracted whole or not at all, so one offending entry refuses it:
189
+ *
190
+ * - an entry that is not a regular file or a directory — a symbolic link, a hard link, a device,
191
+ * a FIFO (`npm pack` and a skill ZIP hold none);
192
+ * - a name that is absolute, begins with a drive letter, is a UNC path, holds a `..` segment or a
193
+ * NUL (a backslash is read as a separator on every host); or one with a segment Windows cannot
194
+ * hold as spelled — a `:`, one of `<` `>` `"` `|` `?` `*`, a control character (code points
195
+ * 1–31), a trailing `.` or space, a device name (`CON`, `com1.txt`) — on every host;
196
+ * - two entries that are one name — exactly, or once folded as a case-insensitive or
197
+ * normalising volume folds them ({@link foldedSegment}) — or a file with another entry under it.
198
+ *
199
+ * @param entries - Every entry of the archive, in archive order
200
+ * @returns The refusal of the first offending entry, in archive order
201
+ */
202
+ export function archiveEntryRefusal(entries) {
203
+ const claims = new Map();
204
+ for (const entry of entries) {
205
+ const refusal = entryRefusal(entry) ?? claimPlaces(entry, claims);
206
+ if (refusal !== undefined)
207
+ return refusal;
208
+ }
209
+ return undefined;
210
+ }
211
+ /**
212
+ * Refuse `archive` when its entries cannot all be extracted ({@link archiveEntryRefusal}).
213
+ *
214
+ * @param archive - What the operator named, for the message
215
+ * @param entries - Every entry of the archive, in archive order
216
+ * @throws ArchiveRefusedError naming the first offending entry
217
+ */
218
+ export function assertArchiveExtractable(archive, entries) {
219
+ const refusal = archiveEntryRefusal(entries);
220
+ if (refusal !== undefined)
221
+ throw new ArchiveRefusedError(archive, refusal);
222
+ }
223
+ //# sourceMappingURL=entries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entries.js","sourceRoot":"","sources":["../../src/archive/entries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The bounds on what an archive may hold, and the refusals for one past them. An archive past a
3
+ * bound is the INPUT's refusal: a tarball that would fill the disk is refused for what it is,
4
+ * before a byte of it is written, never reported as VAT's staging running out.
5
+ */
6
+ import { ArchiveRefusedError, type ArchiveLimits } from './entries.js';
7
+ /**
8
+ * What an archive VAT installs from — an npm package tarball, a skill ZIP — may hold. Two orders
9
+ * of magnitude above any real skill package, and small enough to read in memory.
10
+ */
11
+ export declare const ARCHIVE_LIMITS: ArchiveLimits;
12
+ /** The most bytes VAT downloads for an archive it is given a URL for. */
13
+ export declare const ARCHIVE_DOWNLOAD_MAX_BYTES: number;
14
+ /**
15
+ * The most bytes an archive within `limits` can be, read whole — as a file, or as a tar stream
16
+ * once inflated: its files' bytes and its own structure.
17
+ */
18
+ export declare function archiveBytesCap(limits: ArchiveLimits): number;
19
+ /** The refusal of an archive listing more entries than `limits` allows. */
20
+ export declare function tooManyEntries(archive: string, limits: ArchiveLimits): ArchiveRefusedError;
21
+ /** The refusal of an archive that expands past `limits`. */
22
+ export declare function tooLarge(archive: string, limits: ArchiveLimits, cause?: unknown): ArchiveRefusedError;
23
+ /** The refusal of bytes that are no archive of the format: the one reason a lane may pass bytes on. */
24
+ export declare function unreadableArchive(archive: string, why: string, cause?: unknown): ArchiveRefusedError;
25
+ /**
26
+ * The refusal of an archive that parsed, as it is opened, for an entry that does not hold what it
27
+ * declares: `unsupported`, naming it. Refused as a whole — a read of one entry that fails is
28
+ * an `ArchiveEntryReadError` instead.
29
+ */
30
+ export declare function unsupportedEntry(archive: string, entry: string, what: string): ArchiveRefusedError;
31
+ /**
32
+ * Hold an entry list to `limits`: its count, and the sum of the sizes its files declare.
33
+ *
34
+ * @throws ArchiveRefusedError `too-many-entries` or `too-large`
35
+ */
36
+ export declare function assertWithinLimits(archive: string, entries: ReadonlyArray<{
37
+ readonly size: number;
38
+ }>, limits: ArchiveLimits): void;
39
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/archive/limits.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAIvE;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,aAA2D,CAAC;AAEzF,yEAAyE;AACzE,eAAO,MAAM,0BAA0B,QAAY,CAAC;AAKpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAE7D;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,mBAAmB,CAE1F;AAED,4DAA4D;AAC5D,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAErG;AAED,uGAAuG;AACvG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAEpG;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAElG;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAOlI"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The bounds on what an archive may hold, and the refusals for one past them. An archive past a
3
+ * bound is the INPUT's refusal: a tarball that would fill the disk is refused for what it is,
4
+ * before a byte of it is written, never reported as VAT's staging running out.
5
+ */
6
+ import { ArchiveRefusedError } from './entries.js';
7
+ const MIB = 1024 * 1024;
8
+ /**
9
+ * What an archive VAT installs from — an npm package tarball, a skill ZIP — may hold. Two orders
10
+ * of magnitude above any real skill package, and small enough to read in memory.
11
+ */
12
+ export const ARCHIVE_LIMITS = { maxEntries: 50_000, maxBytes: 256 * MIB };
13
+ /** The most bytes VAT downloads for an archive it is given a URL for. */
14
+ export const ARCHIVE_DOWNLOAD_MAX_BYTES = 100 * MIB;
15
+ /** What an archive's own structure may add per entry (headers, padding, a long-name record) on top of its files' bytes. */
16
+ const OVERHEAD_PER_ENTRY = 2048;
17
+ /**
18
+ * The most bytes an archive within `limits` can be, read whole — as a file, or as a tar stream
19
+ * once inflated: its files' bytes and its own structure.
20
+ */
21
+ export function archiveBytesCap(limits) {
22
+ return limits.maxBytes + limits.maxEntries * OVERHEAD_PER_ENTRY + MIB;
23
+ }
24
+ /** The refusal of an archive listing more entries than `limits` allows. */
25
+ export function tooManyEntries(archive, limits) {
26
+ return new ArchiveRefusedError(archive, { reason: 'too-many-entries', why: `it holds more than ${limits.maxEntries} entries, the most VAT reads from one archive` });
27
+ }
28
+ /** The refusal of an archive that expands past `limits`. */
29
+ export function tooLarge(archive, limits, cause) {
30
+ return new ArchiveRefusedError(archive, { reason: 'too-large', why: `it expands to more than ${limits.maxBytes} bytes, the most VAT reads from one archive` }, { cause });
31
+ }
32
+ /** The refusal of bytes that are no archive of the format: the one reason a lane may pass bytes on. */
33
+ export function unreadableArchive(archive, why, cause) {
34
+ return new ArchiveRefusedError(archive, { reason: 'unreadable', why }, { cause });
35
+ }
36
+ /**
37
+ * The refusal of an archive that parsed, as it is opened, for an entry that does not hold what it
38
+ * declares: `unsupported`, naming it. Refused as a whole — a read of one entry that fails is
39
+ * an `ArchiveEntryReadError` instead.
40
+ */
41
+ export function unsupportedEntry(archive, entry, what) {
42
+ return new ArchiveRefusedError(archive, { reason: 'unsupported', entry, why: `its entry \`${entry}\` ${what}` });
43
+ }
44
+ /**
45
+ * Hold an entry list to `limits`: its count, and the sum of the sizes its files declare.
46
+ *
47
+ * @throws ArchiveRefusedError `too-many-entries` or `too-large`
48
+ */
49
+ export function assertWithinLimits(archive, entries, limits) {
50
+ if (entries.length > limits.maxEntries)
51
+ throw tooManyEntries(archive, limits);
52
+ let total = 0;
53
+ for (const entry of entries) {
54
+ total += entry.size;
55
+ if (total > limits.maxBytes)
56
+ throw tooLarge(archive, limits);
57
+ }
58
+ }
59
+ //# sourceMappingURL=limits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/archive/limits.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAsB,MAAM,cAAc,CAAC;AAEvE,MAAM,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAExB;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAkB,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AAEzF,yEAAyE;AACzE,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,GAAG,GAAG,CAAC;AAEpD,2HAA2H;AAC3H,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAqB;IACnD,OAAO,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,UAAU,GAAG,kBAAkB,GAAG,GAAG,CAAC;AACxE,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,MAAqB;IACnE,OAAO,IAAI,mBAAmB,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,EAAE,sBAAsB,MAAM,CAAC,UAAU,+CAA+C,EAAE,CAAC,CAAC;AACvK,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,MAAqB,EAAE,KAAe;IAC9E,OAAO,IAAI,mBAAmB,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,2BAA2B,MAAM,CAAC,QAAQ,6CAA6C,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AAC5K,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,GAAW,EAAE,KAAe;IAC7E,OAAO,IAAI,mBAAmB,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AACpF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,KAAa,EAAE,IAAY;IAC3E,OAAO,IAAI,mBAAmB,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,KAAK,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;AACnH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAAE,OAAiD,EAAE,MAAqB;IAC1H,IAAI,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,UAAU;QAAE,MAAM,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9E,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC;QACpB,IAAI,KAAK,GAAG,MAAM,CAAC,QAAQ;YAAE,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ /** What the two format readers hand the archive module: an entry, and how to get at its bytes. */
2
+ import type { ArchiveEntry } from './entries.js';
3
+ /** One entry as a reader parsed it. */
4
+ export interface ArchiveRecord extends ArchiveEntry {
5
+ /** Whether the archive marks the file executable — the only permission bit an extraction carries over. */
6
+ readonly executable: boolean;
7
+ /**
8
+ * A file's bytes. A reader that inflates lazily does so here.
9
+ *
10
+ * @throws Whatever the format's reader throws for an entry that does not inflate
11
+ */
12
+ readonly read: () => Buffer;
13
+ }
14
+ //# sourceMappingURL=records.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../src/archive/records.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAElG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,uCAAuC;AACvC,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,0GAA0G;IAC1G,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,MAAM,CAAC;CAC7B"}
@@ -0,0 +1,3 @@
1
+ /** What the two format readers hand the archive module: an entry, and how to get at its bytes. */
2
+ export {};
3
+ //# sourceMappingURL=records.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/archive/records.ts"],"names":[],"mappings":"AAAA,kGAAkG"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The tar reader: every entry of a tar stream (gzipped or plain), parsed in memory and bounded
3
+ * while it is parsed. One of the two files in VAT that import an archive library.
4
+ */
5
+ import { type ArchiveLimits } from './entries.js';
6
+ import type { ArchiveRecord } from './records.js';
7
+ /**
8
+ * Every entry of the tar archive `bytes`, in archive order, each as the archive spells it ({@link entryNameOf}) — links,
9
+ * devices and unsafe names included: listing judges nothing. Synchronous and in memory.
10
+ *
11
+ * @param bytes - The archive, gzipped or plain
12
+ * @param archive - What the operator named, for a refusal's message
13
+ * @param limits - The bounds the archive is held to as it is parsed
14
+ * @throws ArchiveRefusedError `unreadable` for bytes that are no tar archive; `unsupported`, naming
15
+ * the entry, for one whose entry is cut short; `too-many-entries` or `too-large` for one past `limits`
16
+ */
17
+ export declare function readTar(bytes: Buffer, archive: string, limits: ArchiveLimits): ArchiveRecord[];
18
+ //# sourceMappingURL=tar-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tar-reader.d.ts","sourceRoot":"","sources":["../../src/archive/tar-reader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,EAA+C,KAAK,aAAa,EAAe,MAAM,cAAc,CAAC;AAE5G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA+HlD;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,aAAa,EAAE,CA4B9F"}