payload 4.0.0-internal.cd69eef → 4.0.0-internal.d1cc1d3

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/dist/admin/RichText.d.ts +1 -1
  2. package/dist/admin/RichText.d.ts.map +1 -1
  3. package/dist/admin/RichText.js.map +1 -1
  4. package/dist/admin/functions/index.d.ts +10 -8
  5. package/dist/admin/functions/index.d.ts.map +1 -1
  6. package/dist/admin/functions/index.js.map +1 -1
  7. package/dist/admin/types.d.ts +2 -2
  8. package/dist/admin/types.d.ts.map +1 -1
  9. package/dist/admin/types.js.map +1 -1
  10. package/dist/auth/endpoints/login.d.ts.map +1 -1
  11. package/dist/auth/endpoints/login.js +2 -11
  12. package/dist/auth/endpoints/login.js.map +1 -1
  13. package/dist/auth/loginWithCookie.d.ts +33 -0
  14. package/dist/auth/loginWithCookie.d.ts.map +1 -0
  15. package/dist/auth/loginWithCookie.js +34 -0
  16. package/dist/auth/loginWithCookie.js.map +1 -0
  17. package/dist/auth/serverFunctions/cookies.d.ts +47 -0
  18. package/dist/auth/serverFunctions/cookies.d.ts.map +1 -0
  19. package/dist/auth/serverFunctions/cookies.js +52 -0
  20. package/dist/auth/serverFunctions/cookies.js.map +1 -0
  21. package/dist/auth/serverFunctions/login.d.ts +29 -0
  22. package/dist/auth/serverFunctions/login.d.ts.map +1 -0
  23. package/dist/auth/serverFunctions/login.js +63 -0
  24. package/dist/auth/serverFunctions/login.js.map +1 -0
  25. package/dist/auth/serverFunctions/logout.d.ts +17 -0
  26. package/dist/auth/serverFunctions/logout.d.ts.map +1 -0
  27. package/dist/auth/serverFunctions/logout.js +58 -0
  28. package/dist/auth/serverFunctions/logout.js.map +1 -0
  29. package/dist/auth/serverFunctions/refresh.d.ts +17 -0
  30. package/dist/auth/serverFunctions/refresh.d.ts.map +1 -0
  31. package/dist/auth/serverFunctions/refresh.js +61 -0
  32. package/dist/auth/serverFunctions/refresh.js.map +1 -0
  33. package/dist/collections/config/client.d.ts +2 -3
  34. package/dist/collections/config/client.d.ts.map +1 -1
  35. package/dist/collections/config/client.js +5 -7
  36. package/dist/collections/config/client.js.map +1 -1
  37. package/dist/collections/config/defaults.d.ts.map +1 -1
  38. package/dist/collections/config/defaults.js +1 -0
  39. package/dist/collections/config/defaults.js.map +1 -1
  40. package/dist/collections/config/sanitize.d.ts +3 -8
  41. package/dist/collections/config/sanitize.d.ts.map +1 -1
  42. package/dist/collections/config/sanitize.js +2 -6
  43. package/dist/collections/config/sanitize.js.map +1 -1
  44. package/dist/collections/config/types.d.ts +1 -1
  45. package/dist/collections/config/types.d.ts.map +1 -1
  46. package/dist/collections/config/types.js.map +1 -1
  47. package/dist/collections/config/useAsTitle.spec.js +27 -27
  48. package/dist/collections/config/useAsTitle.spec.js.map +1 -1
  49. package/dist/collections/operations/create.d.ts.map +1 -1
  50. package/dist/collections/operations/create.js +10 -0
  51. package/dist/collections/operations/create.js.map +1 -1
  52. package/dist/collections/operations/restoreVersion.d.ts.map +1 -1
  53. package/dist/collections/operations/restoreVersion.js +7 -4
  54. package/dist/collections/operations/restoreVersion.js.map +1 -1
  55. package/dist/collections/operations/updateByID.js +1 -0
  56. package/dist/collections/operations/updateByID.js.map +1 -1
  57. package/dist/config/build.js +1 -1
  58. package/dist/config/build.js.map +1 -1
  59. package/dist/config/defaults.d.ts.map +1 -1
  60. package/dist/config/defaults.js +5 -2
  61. package/dist/config/defaults.js.map +1 -1
  62. package/dist/config/orderable/index.d.ts +1 -1
  63. package/dist/config/orderable/index.d.ts.map +1 -1
  64. package/dist/config/orderable/index.js +2 -2
  65. package/dist/config/orderable/index.js.map +1 -1
  66. package/dist/config/sanitize.d.ts +1 -1
  67. package/dist/config/sanitize.d.ts.map +1 -1
  68. package/dist/config/sanitize.js +33 -40
  69. package/dist/config/sanitize.js.map +1 -1
  70. package/dist/config/types.d.ts +1 -1
  71. package/dist/config/types.js.map +1 -1
  72. package/dist/database/createDatabaseAdapter.d.ts +1 -1
  73. package/dist/database/createDatabaseAdapter.d.ts.map +1 -1
  74. package/dist/database/createDatabaseAdapter.js +0 -2
  75. package/dist/database/createDatabaseAdapter.js.map +1 -1
  76. package/dist/database/types.d.ts +6 -0
  77. package/dist/database/types.d.ts.map +1 -1
  78. package/dist/database/types.js.map +1 -1
  79. package/dist/exports/auth.d.ts +5 -0
  80. package/dist/exports/auth.d.ts.map +1 -0
  81. package/dist/exports/auth.js +6 -0
  82. package/dist/exports/auth.js.map +1 -0
  83. package/dist/exports/internal.d.ts +2 -0
  84. package/dist/exports/internal.d.ts.map +1 -1
  85. package/dist/exports/internal.js +3 -1
  86. package/dist/exports/internal.js.map +1 -1
  87. package/dist/fields/baseFields/slug/duplicateContext.d.ts +11 -0
  88. package/dist/fields/baseFields/slug/duplicateContext.d.ts.map +1 -0
  89. package/dist/fields/baseFields/slug/duplicateContext.js +21 -0
  90. package/dist/fields/baseFields/slug/duplicateContext.js.map +1 -0
  91. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.d.ts +22 -0
  92. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.d.ts.map +1 -0
  93. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.js +63 -0
  94. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.js.map +1 -0
  95. package/dist/fields/baseFields/slug/generateSlug.d.ts +13 -8
  96. package/dist/fields/baseFields/slug/generateSlug.d.ts.map +1 -1
  97. package/dist/fields/baseFields/slug/generateSlug.js +98 -45
  98. package/dist/fields/baseFields/slug/generateSlug.js.map +1 -1
  99. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.d.ts +18 -0
  100. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.d.ts.map +1 -0
  101. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.js +20 -0
  102. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.js.map +1 -0
  103. package/dist/fields/baseFields/slug/getSlugFallbackValue.d.ts +22 -0
  104. package/dist/fields/baseFields/slug/getSlugFallbackValue.d.ts.map +1 -0
  105. package/dist/fields/baseFields/slug/getSlugFallbackValue.js +23 -0
  106. package/dist/fields/baseFields/slug/getSlugFallbackValue.js.map +1 -0
  107. package/dist/fields/baseFields/slug/hasValue.d.ts +3 -0
  108. package/dist/fields/baseFields/slug/hasValue.d.ts.map +1 -0
  109. package/dist/fields/baseFields/slug/hasValue.js +3 -0
  110. package/dist/fields/baseFields/slug/hasValue.js.map +1 -0
  111. package/dist/fields/config/reservedFieldNames.spec.js +18 -18
  112. package/dist/fields/config/reservedFieldNames.spec.js.map +1 -1
  113. package/dist/fields/config/sanitize.d.ts +3 -9
  114. package/dist/fields/config/sanitize.d.ts.map +1 -1
  115. package/dist/fields/config/sanitize.js +33 -34
  116. package/dist/fields/config/sanitize.js.map +1 -1
  117. package/dist/fields/config/sanitize.spec.js +128 -105
  118. package/dist/fields/config/sanitize.spec.js.map +1 -1
  119. package/dist/fields/config/types.d.ts +4 -3
  120. package/dist/fields/config/types.d.ts.map +1 -1
  121. package/dist/fields/config/types.js.map +1 -1
  122. package/dist/fields/hooks/beforeValidate/promise.d.ts.map +1 -1
  123. package/dist/fields/hooks/beforeValidate/promise.js +5 -3
  124. package/dist/fields/hooks/beforeValidate/promise.js.map +1 -1
  125. package/dist/fields/hooks/beforeValidate/stripNullRows.d.ts +10 -0
  126. package/dist/fields/hooks/beforeValidate/stripNullRows.d.ts.map +1 -0
  127. package/dist/fields/hooks/beforeValidate/stripNullRows.js +18 -0
  128. package/dist/fields/hooks/beforeValidate/stripNullRows.js.map +1 -0
  129. package/dist/fields/validations.d.ts.map +1 -1
  130. package/dist/fields/validations.js +7 -8
  131. package/dist/fields/validations.js.map +1 -1
  132. package/dist/fields/validations.spec.js +61 -37
  133. package/dist/fields/validations.spec.js.map +1 -1
  134. package/dist/globals/config/sanitize.d.ts +2 -7
  135. package/dist/globals/config/sanitize.d.ts.map +1 -1
  136. package/dist/globals/config/sanitize.js +2 -6
  137. package/dist/globals/config/sanitize.js.map +1 -1
  138. package/dist/globals/config/sanitize.spec.js +6 -6
  139. package/dist/globals/config/sanitize.spec.js.map +1 -1
  140. package/dist/globals/operations/countGlobalVersions.d.ts.map +1 -1
  141. package/dist/globals/operations/countGlobalVersions.js +1 -0
  142. package/dist/globals/operations/countGlobalVersions.js.map +1 -1
  143. package/dist/index.bundled.d.ts +247 -178
  144. package/dist/index.d.ts +49 -17
  145. package/dist/index.d.ts.map +1 -1
  146. package/dist/index.js +3 -0
  147. package/dist/index.js.map +1 -1
  148. package/dist/query-presets/constraints.js +1 -1
  149. package/dist/query-presets/constraints.js.map +1 -1
  150. package/dist/queues/config/collection.d.ts.map +1 -1
  151. package/dist/queues/config/collection.js +37 -43
  152. package/dist/queues/config/collection.js.map +1 -1
  153. package/dist/queues/config/global.d.ts +5 -6
  154. package/dist/queues/config/global.d.ts.map +1 -1
  155. package/dist/queues/config/global.js +1 -1
  156. package/dist/queues/config/global.js.map +1 -1
  157. package/dist/queues/config/types/index.d.ts +29 -24
  158. package/dist/queues/config/types/index.d.ts.map +1 -1
  159. package/dist/queues/config/types/index.js.map +1 -1
  160. package/dist/queues/config/types/taskTypes.d.ts +4 -7
  161. package/dist/queues/config/types/taskTypes.d.ts.map +1 -1
  162. package/dist/queues/config/types/taskTypes.js.map +1 -1
  163. package/dist/queues/config/types/workflowJSONTypes.d.ts +10 -9
  164. package/dist/queues/config/types/workflowJSONTypes.d.ts.map +1 -1
  165. package/dist/queues/config/types/workflowJSONTypes.js.map +1 -1
  166. package/dist/queues/config/types/workflowTypes.d.ts +11 -58
  167. package/dist/queues/config/types/workflowTypes.d.ts.map +1 -1
  168. package/dist/queues/config/types/workflowTypes.js.map +1 -1
  169. package/dist/queues/endpoints/handleSchedules.js +1 -1
  170. package/dist/queues/endpoints/handleSchedules.js.map +1 -1
  171. package/dist/queues/errors/handleTaskError.js +4 -4
  172. package/dist/queues/errors/handleTaskError.js.map +1 -1
  173. package/dist/queues/errors/handleWorkflowError.js +1 -1
  174. package/dist/queues/errors/handleWorkflowError.js.map +1 -1
  175. package/dist/queues/errors/index.d.ts +6 -0
  176. package/dist/queues/errors/index.d.ts.map +1 -1
  177. package/dist/queues/errors/index.js +5 -0
  178. package/dist/queues/errors/index.js.map +1 -1
  179. package/dist/queues/localAPI.d.ts +4 -4
  180. package/dist/queues/localAPI.d.ts.map +1 -1
  181. package/dist/queues/localAPI.js +63 -66
  182. package/dist/queues/localAPI.js.map +1 -1
  183. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.d.ts +4 -4
  184. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.d.ts.map +1 -1
  185. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.js.map +1 -1
  186. package/dist/queues/operations/handleSchedules/index.d.ts +1 -1
  187. package/dist/queues/operations/handleSchedules/index.d.ts.map +1 -1
  188. package/dist/queues/operations/handleSchedules/index.js +1 -1
  189. package/dist/queues/operations/handleSchedules/index.js.map +1 -1
  190. package/dist/queues/operations/runJobs/heartbeat.d.ts +13 -0
  191. package/dist/queues/operations/runJobs/heartbeat.d.ts.map +1 -0
  192. package/dist/queues/operations/runJobs/heartbeat.js +66 -0
  193. package/dist/queues/operations/runJobs/heartbeat.js.map +1 -0
  194. package/dist/queues/operations/runJobs/index.d.ts.map +1 -1
  195. package/dist/queues/operations/runJobs/index.js +133 -84
  196. package/dist/queues/operations/runJobs/index.js.map +1 -1
  197. package/dist/queues/operations/runJobs/runJSONJob/index.d.ts.map +1 -1
  198. package/dist/queues/operations/runJobs/runJSONJob/index.js +6 -3
  199. package/dist/queues/operations/runJobs/runJSONJob/index.js.map +1 -1
  200. package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js +5 -5
  201. package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js.map +1 -1
  202. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.d.ts +2 -1
  203. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.d.ts.map +1 -1
  204. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js +39 -8
  205. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js.map +1 -1
  206. package/dist/queues/operations/runJobs/runJob/importHandlerPath.js.map +1 -1
  207. package/dist/queues/operations/runJobs/runJob/index.d.ts.map +1 -1
  208. package/dist/queues/operations/runJobs/runJob/index.js +4 -4
  209. package/dist/queues/operations/runJobs/runJob/index.js.map +1 -1
  210. package/dist/queues/utilities/updateJob.d.ts.map +1 -1
  211. package/dist/queues/utilities/updateJob.js +3 -0
  212. package/dist/queues/utilities/updateJob.js.map +1 -1
  213. package/dist/types/index.d.ts +2 -2
  214. package/dist/types/index.d.ts.map +1 -1
  215. package/dist/types/index.js.map +1 -1
  216. package/dist/uploads/checkFileRestrictions.d.ts +1 -1
  217. package/dist/uploads/checkFileRestrictions.d.ts.map +1 -1
  218. package/dist/uploads/checkFileRestrictions.js +15 -1
  219. package/dist/uploads/checkFileRestrictions.js.map +1 -1
  220. package/dist/uploads/endpoints/uploadInstructions.d.ts +12 -0
  221. package/dist/uploads/endpoints/uploadInstructions.d.ts.map +1 -1
  222. package/dist/uploads/endpoints/uploadInstructions.js +66 -20
  223. package/dist/uploads/endpoints/uploadInstructions.js.map +1 -1
  224. package/dist/uploads/generateFileData.js +4 -1
  225. package/dist/uploads/generateFileData.js.map +1 -1
  226. package/dist/uploads/getFileFromUploadInstructions.d.ts +8 -0
  227. package/dist/uploads/getFileFromUploadInstructions.d.ts.map +1 -0
  228. package/dist/uploads/getFileFromUploadInstructions.js +62 -0
  229. package/dist/uploads/getFileFromUploadInstructions.js.map +1 -0
  230. package/dist/uploads/getImageSize.d.ts +12 -1
  231. package/dist/uploads/getImageSize.d.ts.map +1 -1
  232. package/dist/uploads/getImageSize.js +20 -18
  233. package/dist/uploads/getImageSize.js.map +1 -1
  234. package/dist/uploads/getImageSize.spec.js +298 -0
  235. package/dist/uploads/getImageSize.spec.js.map +1 -0
  236. package/dist/uploads/probeImageSize.d.ts +39 -0
  237. package/dist/uploads/probeImageSize.d.ts.map +1 -0
  238. package/dist/uploads/probeImageSize.js +374 -0
  239. package/dist/uploads/probeImageSize.js.map +1 -0
  240. package/dist/uploads/probeImageSize.spec.js +366 -0
  241. package/dist/uploads/probeImageSize.spec.js.map +1 -0
  242. package/dist/uploads/stagedUpload.d.ts +27 -0
  243. package/dist/uploads/stagedUpload.d.ts.map +1 -0
  244. package/dist/uploads/stagedUpload.js +197 -0
  245. package/dist/uploads/stagedUpload.js.map +1 -0
  246. package/dist/uploads/types.d.ts +41 -13
  247. package/dist/uploads/types.d.ts.map +1 -1
  248. package/dist/uploads/types.js.map +1 -1
  249. package/dist/utilities/addDataAndFileToRequest.d.ts.map +1 -1
  250. package/dist/utilities/addDataAndFileToRequest.js +12 -46
  251. package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
  252. package/dist/utilities/configToJSONSchema.spec.js +33 -33
  253. package/dist/utilities/configToJSONSchema.spec.js.map +1 -1
  254. package/dist/utilities/fieldValueExists.d.ts +29 -0
  255. package/dist/utilities/fieldValueExists.d.ts.map +1 -0
  256. package/dist/utilities/fieldValueExists.js +27 -0
  257. package/dist/utilities/fieldValueExists.js.map +1 -0
  258. package/dist/utilities/getUniqueFieldValue.d.ts +27 -0
  259. package/dist/utilities/getUniqueFieldValue.d.ts.map +1 -0
  260. package/dist/utilities/getUniqueFieldValue.js +26 -0
  261. package/dist/utilities/getUniqueFieldValue.js.map +1 -0
  262. package/dist/versions/deleteScheduledPublishJobs.js +2 -2
  263. package/dist/versions/deleteScheduledPublishJobs.js.map +1 -1
  264. package/dist/versions/payloadPackageList.d.ts.map +1 -1
  265. package/dist/versions/payloadPackageList.js +0 -1
  266. package/dist/versions/payloadPackageList.js.map +1 -1
  267. package/package.json +8 -3
  268. package/dist/database/defaultUpdateJobs.d.ts +0 -3
  269. package/dist/database/defaultUpdateJobs.d.ts.map +0 -1
  270. package/dist/database/defaultUpdateJobs.js +0 -41
  271. package/dist/database/defaultUpdateJobs.js.map +0 -1
  272. package/dist/fields/baseFields/slug/countVersions.d.ts +0 -13
  273. package/dist/fields/baseFields/slug/countVersions.d.ts.map +0 -1
  274. package/dist/fields/baseFields/slug/countVersions.js +0 -27
  275. package/dist/fields/baseFields/slug/countVersions.js.map +0 -1
  276. package/dist/uploads/tempFile.d.ts +0 -7
  277. package/dist/uploads/tempFile.d.ts.map +0 -1
  278. package/dist/uploads/tempFile.js +0 -39
  279. package/dist/uploads/tempFile.js.map +0 -1
@@ -0,0 +1,374 @@
1
+ import { createReadStream } from 'fs';
2
+ import fs from 'fs/promises';
3
+ import { imageDimensionsFromData, imageDimensionsFromStream } from 'image-dimensions';
4
+ /**
5
+ * Image dimension probe used as a fallback when `sharp` is not configured.
6
+ * Reads only the header bytes needed to determine width and height.
7
+ *
8
+ * PNG, JPEG, GIF, WebP, AVIF and HEIF/HEIC are delegated to `image-dimensions`
9
+ * (actively maintained, zero dependencies). BMP, ICO/CUR, SVG, TIFF and JPEG
10
+ * XL have no such maintained equivalent, so they're read here directly; each
11
+ * of those parsers advances by a fixed amount or is bounded by an explicit
12
+ * guard, so malformed input can never block the event loop.
13
+ *
14
+ * Replaces the archived `image-size` package, whose ICNS/HEIF parsers shipped
15
+ * unpatched denial-of-service vulnerabilities (CVE-2025-71330, CVE-2025-71319).
16
+ *
17
+ * Two edge cases changed behavior compared to the previous hand-rolled parser:
18
+ * - JPEG files using arithmetic coding or hierarchical encoding (SOF markers
19
+ * 5-7, 9-11, 13-15) are no longer read; `image-dimensions` only recognizes
20
+ * baseline and progressive JPEG (SOF0-3). These encodings are not produced
21
+ * by browsers or cameras, so this is not expected to affect real uploads.
22
+ * - AVIF/HEIF detection now checks the container's brand list instead of
23
+ * accepting any ISO base media file with a `ftyp` box, so non-image formats
24
+ * that share the same container (for example MP4/MOV) are correctly no
25
+ * longer misidentified as images.
26
+ *
27
+ * @throws if the buffer is not a recognized/parseable image format
28
+ */ export function probeImageSize(data) {
29
+ const modernDimensions = imageDimensionsFromData(data);
30
+ const dimensions = modernDimensions ? {
31
+ height: modernDimensions.height,
32
+ width: modernDimensions.width
33
+ } : probeLegacyFormat(data);
34
+ if (!dimensions || !dimensions.width || !dimensions.height) {
35
+ throw new Error('Unsupported image type: unable to determine dimensions');
36
+ }
37
+ return dimensions;
38
+ }
39
+ /**
40
+ * Bytes read from the start of the file to detect a legacy/JXL format from
41
+ * its header; comfortably covers every signature `detectLegacyType` checks.
42
+ */ const HEADER_SNIFF_LENGTH = 4096;
43
+ /**
44
+ * Probe used when the file lives on disk via `tempFilePath`. PNG, JPEG, GIF,
45
+ * WebP, AVIF and HEIF/HEIC are read through `imageDimensionsFromStream`,
46
+ * which reads only as many bytes as are needed to find the header, so a
47
+ * large file's data is never pulled into memory. BMP, ICO/CUR, SVG, TIFF and
48
+ * JPEG XL are detected from a small header sniff and, only then, read in
49
+ * full for `probeImageSize` to parse.
50
+ *
51
+ * @throws if the file is not a recognized/parseable image format
52
+ */ export async function probeImageSizeFromPath(tempFilePath) {
53
+ const headerSniff = await readHeaderSniff(tempFilePath);
54
+ if (detectLegacyType(headerSniff)) {
55
+ return probeImageSize(await fs.readFile(tempFilePath));
56
+ }
57
+ const modernDimensions = await imageDimensionsFromStream(ReadableStream.from(createReadStream(tempFilePath)));
58
+ if (modernDimensions) {
59
+ return {
60
+ height: modernDimensions.height,
61
+ width: modernDimensions.width
62
+ };
63
+ }
64
+ return probeImageSize(await fs.readFile(tempFilePath));
65
+ }
66
+ async function readHeaderSniff(tempFilePath) {
67
+ const handle = await fs.open(tempFilePath, 'r');
68
+ try {
69
+ const buffer = Buffer.alloc(HEADER_SNIFF_LENGTH);
70
+ const { bytesRead } = await handle.read(buffer, 0, HEADER_SNIFF_LENGTH, 0);
71
+ return buffer.subarray(0, bytesRead);
72
+ } finally{
73
+ await handle.close();
74
+ }
75
+ }
76
+ function probeLegacyFormat(data) {
77
+ const type = detectLegacyType(data);
78
+ return type ? legacyParsers[type](data) : null;
79
+ }
80
+ function detectLegacyType(data) {
81
+ if (data.length < 2) {
82
+ return null;
83
+ }
84
+ if (data[0] === 0x42 && data[1] === 0x4d) {
85
+ return 'bmp';
86
+ }
87
+ if (data.length >= 8 && (data[0] === 0x49 && data[1] === 0x49 && data[2] === 0x2a || data[0] === 0x4d && data[1] === 0x4d && data[3] === 0x2a)) {
88
+ return 'tiff';
89
+ }
90
+ if (data.length >= 6 && data[0] === 0 && data[1] === 0 && (data[2] === 1 || data[2] === 2) && data[3] === 0) {
91
+ return 'ico';
92
+ }
93
+ if (data[0] === 0xff && data[1] === 0x0a || isJXLContainerSignature(data)) {
94
+ return 'jxl';
95
+ }
96
+ const head = data.toString('utf8', 0, Math.min(data.length, 1000));
97
+ if (/<svg[\s>]/i.test(head) || head.trimStart().startsWith('<?xml') && /<svg/i.test(head)) {
98
+ return 'svg';
99
+ }
100
+ return null;
101
+ }
102
+ const legacyParsers = {
103
+ bmp: (data)=>({
104
+ height: Math.abs(data.readInt32LE(22)),
105
+ width: data.readInt32LE(18)
106
+ }),
107
+ ico: (data)=>{
108
+ const count = data.readUInt16LE(4);
109
+ let best = {
110
+ height: 0,
111
+ width: 0
112
+ };
113
+ for(let i = 0; i < count && i < 1000; i++){
114
+ const entry = 6 + i * 16;
115
+ if (entry + 2 > data.length) {
116
+ break;
117
+ }
118
+ // A zero byte means 256 px in the ICO format
119
+ const width = data[entry] === 0 ? 256 : data[entry];
120
+ const height = data[entry + 1] === 0 ? 256 : data[entry + 1];
121
+ if (width * height > best.width * best.height) {
122
+ best = {
123
+ height,
124
+ width
125
+ };
126
+ }
127
+ }
128
+ return best.width ? best : null;
129
+ },
130
+ jxl: (data)=>parseJXL(data),
131
+ svg: (data)=>parseSVG(data),
132
+ tiff: (data)=>{
133
+ const isLittleEndian = data[0] === 0x49;
134
+ const readU16 = (offset)=>isLittleEndian ? data.readUInt16LE(offset) : data.readUInt16BE(offset);
135
+ const readU32 = (offset)=>isLittleEndian ? data.readUInt32LE(offset) : data.readUInt32BE(offset);
136
+ const ifdOffset = readU32(4);
137
+ if (ifdOffset + 2 > data.length) {
138
+ return null;
139
+ }
140
+ const entryCount = readU16(ifdOffset);
141
+ let width;
142
+ let height;
143
+ for(let i = 0; i < entryCount && i < 1000; i++){
144
+ const entry = ifdOffset + 2 + i * 12;
145
+ if (entry + 12 > data.length) {
146
+ break;
147
+ }
148
+ const tag = readU16(entry);
149
+ const fieldType = readU16(entry + 2);
150
+ // SHORT (type 3) values are 16-bit, otherwise read as 32-bit LONG
151
+ const value = fieldType === 3 ? readU16(entry + 8) : readU32(entry + 8);
152
+ if (tag === 256) {
153
+ width = value;
154
+ } else if (tag === 257) {
155
+ height = value;
156
+ }
157
+ }
158
+ return width && height ? {
159
+ height,
160
+ width
161
+ } : null;
162
+ }
163
+ };
164
+ function parseSVG(data) {
165
+ const text = data.toString('utf8', 0, Math.min(data.length, 65536));
166
+ const tagMatch = text.match(/<svg[^>]*>/i);
167
+ if (!tagMatch) {
168
+ return null;
169
+ }
170
+ const tag = tagMatch[0];
171
+ const readLength = (name)=>{
172
+ const match = tag.match(new RegExp(`${name}\\s*=\\s*["']?\\s*([^"'\\s>]+)`, 'i'));
173
+ if (!match) {
174
+ return null;
175
+ }
176
+ // Percentage units are relative and yield no concrete pixel size
177
+ if (/%\s*$/.test(match[1])) {
178
+ return null;
179
+ }
180
+ const value = parseFloat(match[1]);
181
+ return Number.isFinite(value) ? value : null;
182
+ };
183
+ const width = readLength('width');
184
+ const height = readLength('height');
185
+ if (width != null && height != null) {
186
+ return {
187
+ height: Math.round(height),
188
+ width: Math.round(width)
189
+ };
190
+ }
191
+ const viewBoxMatch = tag.match(/viewbox\s*=\s*["']?\s*([\d.\s,+-]+)/i);
192
+ if (viewBoxMatch) {
193
+ const parts = viewBoxMatch[1].trim().split(/[\s,]+/).map(Number);
194
+ if (parts.length === 4 && parts.every((n)=>Number.isFinite(n))) {
195
+ const [, , viewWidth, viewHeight] = parts;
196
+ if (width != null) {
197
+ return {
198
+ height: Math.round(width / viewWidth * viewHeight),
199
+ width: Math.round(width)
200
+ };
201
+ }
202
+ if (height != null) {
203
+ return {
204
+ height: Math.round(height),
205
+ width: Math.round(height / viewHeight * viewWidth)
206
+ };
207
+ }
208
+ return {
209
+ height: Math.round(viewHeight),
210
+ width: Math.round(viewWidth)
211
+ };
212
+ }
213
+ }
214
+ return null;
215
+ }
216
+ /**
217
+ * JPEG XL isn't supported by `image-dimensions`, so its size header is read
218
+ * directly. A JXL file is either a bare codestream starting `FF 0A`, or an
219
+ * ISOBMFF container carrying the codestream in a single `jxlc` box or split
220
+ * across several `jxlp` boxes; either way the dimensions live in the first
221
+ * bits of the codestream (the `SizeHeader`). See https://www.w3.org/TR/jpeg-xl/
222
+ * for the bitstream layout.
223
+ */ function parseJXL(data) {
224
+ if (data[0] === 0xff && data[1] === 0x0a) {
225
+ return parseJXLSizeHeader(data, 2);
226
+ }
227
+ // A boxed codestream still starts with the `FF 0A` signature, so it's
228
+ // skipped here too, same as the bare-codestream case above
229
+ const jxlcBox = findBox(data, 'jxlc', 0);
230
+ if (jxlcBox) {
231
+ return parseJXLSizeHeader(data, jxlcBox.bodyOffset + 2);
232
+ }
233
+ const jxlpBoxes = findAllBoxes(data, 'jxlp');
234
+ if (!jxlpBoxes.length) {
235
+ return null;
236
+ }
237
+ // Each `jxlp` payload is prefixed with a 4-byte partial-codestream index
238
+ const codestream = Buffer.concat(jxlpBoxes.map((box)=>data.subarray(box.bodyOffset + 4, box.offset + box.size)));
239
+ return parseJXLSizeHeader(codestream, 2);
240
+ }
241
+ function isJXLContainerSignature(data) {
242
+ return data.length >= 12 && data.readUInt32BE(0) === 0x0000000c && data.toString('ascii', 4, 8) === 'JXL ' && data[8] === 0x0d && data[9] === 0x0a && data[10] === 0x87 && data[11] === 0x0a;
243
+ }
244
+ function readBoxHeader(data, offset) {
245
+ if (offset + 8 > data.length) {
246
+ return null;
247
+ }
248
+ const name = data.toString('ascii', offset + 4, offset + 8);
249
+ let size = data.readUInt32BE(offset);
250
+ let bodyOffset = offset + 8;
251
+ if (size === 1) {
252
+ // A size of 1 means a 64-bit size follows the 8-byte header
253
+ if (offset + 16 > data.length) {
254
+ return null;
255
+ }
256
+ const largeSize = data.readBigUInt64BE(offset + 8);
257
+ if (largeSize > BigInt(Number.MAX_SAFE_INTEGER)) {
258
+ return null;
259
+ }
260
+ size = Number(largeSize);
261
+ bodyOffset = offset + 16;
262
+ } else if (size === 0) {
263
+ // A size of 0 means the box extends to the end of the buffer
264
+ size = data.length - offset;
265
+ }
266
+ if (size < bodyOffset - offset || offset + size > data.length) {
267
+ return null;
268
+ }
269
+ return {
270
+ name,
271
+ bodyOffset,
272
+ offset,
273
+ size
274
+ };
275
+ }
276
+ // Bounded to the same 1000-entry cap used elsewhere in this file so a
277
+ // malformed chain of boxes can never block the event loop
278
+ function findBox(data, name, startOffset) {
279
+ let offset = startOffset;
280
+ for(let i = 0; i < 1000 && offset < data.length; i++){
281
+ const box = readBoxHeader(data, offset);
282
+ if (!box) {
283
+ return null;
284
+ }
285
+ if (box.name === name) {
286
+ return box;
287
+ }
288
+ offset += box.size;
289
+ }
290
+ return null;
291
+ }
292
+ function findAllBoxes(data, name) {
293
+ const boxes = [];
294
+ let offset = 0;
295
+ for(let i = 0; i < 1000 && offset < data.length; i++){
296
+ const box = readBoxHeader(data, offset);
297
+ if (!box) {
298
+ break;
299
+ }
300
+ if (box.name === name) {
301
+ boxes.push(box);
302
+ }
303
+ offset += box.size;
304
+ }
305
+ return boxes;
306
+ }
307
+ /**
308
+ * Reads the JXL `SizeHeader` bit-packed structure (little-endian, LSB
309
+ * first) starting at `startOffset` in the codestream.
310
+ */ function parseJXLSizeHeader(data, startOffset) {
311
+ let byteOffset = startOffset;
312
+ let bitOffset = 0;
313
+ const readBits = (length)=>{
314
+ let result = 0;
315
+ let bitsRead = 0;
316
+ while(bitsRead < length){
317
+ if (byteOffset >= data.length) {
318
+ throw new RangeError('Unexpected end of JXL codestream');
319
+ }
320
+ const currentByte = data[byteOffset];
321
+ const bitsLeft = 8 - bitOffset;
322
+ const bitsToRead = Math.min(length - bitsRead, bitsLeft);
323
+ const mask = (1 << bitsToRead) - 1;
324
+ result |= (currentByte >> bitOffset & mask) << bitsRead;
325
+ bitsRead += bitsToRead;
326
+ bitOffset += bitsToRead;
327
+ if (bitOffset === 8) {
328
+ byteOffset++;
329
+ bitOffset = 0;
330
+ }
331
+ }
332
+ return result;
333
+ };
334
+ const readExplicitDimension = ()=>{
335
+ const sizeClass = readBits(2);
336
+ const extraBits = [
337
+ 9,
338
+ 13,
339
+ 18,
340
+ 30
341
+ ][sizeClass];
342
+ return 1 + readBits(extraBits);
343
+ };
344
+ try {
345
+ const isSmallImage = readBits(1) === 1;
346
+ const height = isSmallImage ? 8 * (1 + readBits(5)) : readExplicitDimension();
347
+ const widthMode = readBits(3);
348
+ let width;
349
+ if (isSmallImage && widthMode === 0) {
350
+ width = 8 * (1 + readBits(5));
351
+ } else if (widthMode === 0) {
352
+ width = readExplicitDimension();
353
+ } else {
354
+ const aspectRatios = [
355
+ 1,
356
+ 1.2,
357
+ 4 / 3,
358
+ 1.5,
359
+ 16 / 9,
360
+ 5 / 4,
361
+ 2
362
+ ];
363
+ width = Math.floor(height * aspectRatios[widthMode - 1]);
364
+ }
365
+ return {
366
+ height,
367
+ width
368
+ };
369
+ } catch {
370
+ return null;
371
+ }
372
+ }
373
+
374
+ //# sourceMappingURL=probeImageSize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/uploads/probeImageSize.ts"],"sourcesContent":["import { createReadStream } from 'fs'\nimport fs from 'fs/promises'\nimport { imageDimensionsFromData, imageDimensionsFromStream } from 'image-dimensions'\n\nimport type { ProbedImageSize } from './types.js'\n\n/**\n * Image dimension probe used as a fallback when `sharp` is not configured.\n * Reads only the header bytes needed to determine width and height.\n *\n * PNG, JPEG, GIF, WebP, AVIF and HEIF/HEIC are delegated to `image-dimensions`\n * (actively maintained, zero dependencies). BMP, ICO/CUR, SVG, TIFF and JPEG\n * XL have no such maintained equivalent, so they're read here directly; each\n * of those parsers advances by a fixed amount or is bounded by an explicit\n * guard, so malformed input can never block the event loop.\n *\n * Replaces the archived `image-size` package, whose ICNS/HEIF parsers shipped\n * unpatched denial-of-service vulnerabilities (CVE-2025-71330, CVE-2025-71319).\n *\n * Two edge cases changed behavior compared to the previous hand-rolled parser:\n * - JPEG files using arithmetic coding or hierarchical encoding (SOF markers\n * 5-7, 9-11, 13-15) are no longer read; `image-dimensions` only recognizes\n * baseline and progressive JPEG (SOF0-3). These encodings are not produced\n * by browsers or cameras, so this is not expected to affect real uploads.\n * - AVIF/HEIF detection now checks the container's brand list instead of\n * accepting any ISO base media file with a `ftyp` box, so non-image formats\n * that share the same container (for example MP4/MOV) are correctly no\n * longer misidentified as images.\n *\n * @throws if the buffer is not a recognized/parseable image format\n */\nexport function probeImageSize(data: Buffer): ProbedImageSize {\n const modernDimensions = imageDimensionsFromData(data)\n const dimensions = modernDimensions\n ? { height: modernDimensions.height, width: modernDimensions.width }\n : probeLegacyFormat(data)\n\n if (!dimensions || !dimensions.width || !dimensions.height) {\n throw new Error('Unsupported image type: unable to determine dimensions')\n }\n\n return dimensions\n}\n\n/**\n * Bytes read from the start of the file to detect a legacy/JXL format from\n * its header; comfortably covers every signature `detectLegacyType` checks.\n */\nconst HEADER_SNIFF_LENGTH = 4096\n\n/**\n * Probe used when the file lives on disk via `tempFilePath`. PNG, JPEG, GIF,\n * WebP, AVIF and HEIF/HEIC are read through `imageDimensionsFromStream`,\n * which reads only as many bytes as are needed to find the header, so a\n * large file's data is never pulled into memory. BMP, ICO/CUR, SVG, TIFF and\n * JPEG XL are detected from a small header sniff and, only then, read in\n * full for `probeImageSize` to parse.\n *\n * @throws if the file is not a recognized/parseable image format\n */\nexport async function probeImageSizeFromPath(tempFilePath: string): Promise<ProbedImageSize> {\n const headerSniff = await readHeaderSniff(tempFilePath)\n\n if (detectLegacyType(headerSniff)) {\n return probeImageSize(await fs.readFile(tempFilePath))\n }\n\n const modernDimensions = await imageDimensionsFromStream(\n ReadableStream.from(createReadStream(tempFilePath)),\n )\n\n if (modernDimensions) {\n return { height: modernDimensions.height, width: modernDimensions.width }\n }\n\n return probeImageSize(await fs.readFile(tempFilePath))\n}\n\nasync function readHeaderSniff(tempFilePath: string): Promise<Buffer> {\n const handle = await fs.open(tempFilePath, 'r')\n\n try {\n const buffer = Buffer.alloc(HEADER_SNIFF_LENGTH)\n const { bytesRead } = await handle.read(buffer, 0, HEADER_SNIFF_LENGTH, 0)\n return buffer.subarray(0, bytesRead)\n } finally {\n await handle.close()\n }\n}\n\ntype Dimensions = null | ProbedImageSize\n\ntype LegacyImageType = 'bmp' | 'ico' | 'jxl' | 'svg' | 'tiff'\n\nfunction probeLegacyFormat(data: Buffer): Dimensions {\n const type = detectLegacyType(data)\n return type ? legacyParsers[type](data) : null\n}\n\nfunction detectLegacyType(data: Buffer): LegacyImageType | null {\n if (data.length < 2) {\n return null\n }\n\n if (data[0] === 0x42 && data[1] === 0x4d) {\n return 'bmp'\n }\n if (\n data.length >= 8 &&\n ((data[0] === 0x49 && data[1] === 0x49 && data[2] === 0x2a) ||\n (data[0] === 0x4d && data[1] === 0x4d && data[3] === 0x2a))\n ) {\n return 'tiff'\n }\n if (\n data.length >= 6 &&\n data[0] === 0 &&\n data[1] === 0 &&\n (data[2] === 1 || data[2] === 2) &&\n data[3] === 0\n ) {\n return 'ico'\n }\n if ((data[0] === 0xff && data[1] === 0x0a) || isJXLContainerSignature(data)) {\n return 'jxl'\n }\n\n const head = data.toString('utf8', 0, Math.min(data.length, 1000))\n if (/<svg[\\s>]/i.test(head) || (head.trimStart().startsWith('<?xml') && /<svg/i.test(head))) {\n return 'svg'\n }\n\n return null\n}\n\nconst legacyParsers: Record<LegacyImageType, (data: Buffer) => Dimensions> = {\n bmp: (data) => ({ height: Math.abs(data.readInt32LE(22)), width: data.readInt32LE(18) }),\n ico: (data) => {\n const count = data.readUInt16LE(4)\n let best: ProbedImageSize = { height: 0, width: 0 }\n\n for (let i = 0; i < count && i < 1000; i++) {\n const entry = 6 + i * 16\n if (entry + 2 > data.length) {\n break\n }\n // A zero byte means 256 px in the ICO format\n const width = data[entry] === 0 ? 256 : data[entry]!\n const height = data[entry + 1] === 0 ? 256 : data[entry + 1]!\n if (width * height > best.width * best.height) {\n best = { height, width }\n }\n }\n\n return best.width ? best : null\n },\n jxl: (data) => parseJXL(data),\n svg: (data) => parseSVG(data),\n tiff: (data) => {\n const isLittleEndian = data[0] === 0x49\n const readU16 = (offset: number) =>\n isLittleEndian ? data.readUInt16LE(offset) : data.readUInt16BE(offset)\n const readU32 = (offset: number) =>\n isLittleEndian ? data.readUInt32LE(offset) : data.readUInt32BE(offset)\n\n const ifdOffset = readU32(4)\n if (ifdOffset + 2 > data.length) {\n return null\n }\n\n const entryCount = readU16(ifdOffset)\n let width: number | undefined\n let height: number | undefined\n\n for (let i = 0; i < entryCount && i < 1000; i++) {\n const entry = ifdOffset + 2 + i * 12\n if (entry + 12 > data.length) {\n break\n }\n const tag = readU16(entry)\n const fieldType = readU16(entry + 2)\n // SHORT (type 3) values are 16-bit, otherwise read as 32-bit LONG\n const value = fieldType === 3 ? readU16(entry + 8) : readU32(entry + 8)\n if (tag === 256) {\n width = value\n } else if (tag === 257) {\n height = value\n }\n }\n\n return width && height ? { height, width } : null\n },\n}\n\nfunction parseSVG(data: Buffer): Dimensions {\n const text = data.toString('utf8', 0, Math.min(data.length, 65536))\n const tagMatch = text.match(/<svg[^>]*>/i)\n if (!tagMatch) {\n return null\n }\n\n const tag = tagMatch[0]\n const readLength = (name: string): null | number => {\n const match = tag.match(new RegExp(`${name}\\\\s*=\\\\s*[\"']?\\\\s*([^\"'\\\\s>]+)`, 'i'))\n if (!match) {\n return null\n }\n // Percentage units are relative and yield no concrete pixel size\n if (/%\\s*$/.test(match[1]!)) {\n return null\n }\n const value = parseFloat(match[1]!)\n return Number.isFinite(value) ? value : null\n }\n\n const width = readLength('width')\n const height = readLength('height')\n if (width != null && height != null) {\n return { height: Math.round(height), width: Math.round(width) }\n }\n\n const viewBoxMatch = tag.match(/viewbox\\s*=\\s*[\"']?\\s*([\\d.\\s,+-]+)/i)\n if (viewBoxMatch) {\n const parts = viewBoxMatch[1]!\n .trim()\n .split(/[\\s,]+/)\n .map(Number)\n if (parts.length === 4 && parts.every((n) => Number.isFinite(n))) {\n const [, , viewWidth, viewHeight] = parts as [number, number, number, number]\n if (width != null) {\n return { height: Math.round((width / viewWidth) * viewHeight), width: Math.round(width) }\n }\n if (height != null) {\n return { height: Math.round(height), width: Math.round((height / viewHeight) * viewWidth) }\n }\n return { height: Math.round(viewHeight), width: Math.round(viewWidth) }\n }\n }\n\n return null\n}\n\n/**\n * JPEG XL isn't supported by `image-dimensions`, so its size header is read\n * directly. A JXL file is either a bare codestream starting `FF 0A`, or an\n * ISOBMFF container carrying the codestream in a single `jxlc` box or split\n * across several `jxlp` boxes; either way the dimensions live in the first\n * bits of the codestream (the `SizeHeader`). See https://www.w3.org/TR/jpeg-xl/\n * for the bitstream layout.\n */\nfunction parseJXL(data: Buffer): Dimensions {\n if (data[0] === 0xff && data[1] === 0x0a) {\n return parseJXLSizeHeader(data, 2)\n }\n\n // A boxed codestream still starts with the `FF 0A` signature, so it's\n // skipped here too, same as the bare-codestream case above\n const jxlcBox = findBox(data, 'jxlc', 0)\n if (jxlcBox) {\n return parseJXLSizeHeader(data, jxlcBox.bodyOffset + 2)\n }\n\n const jxlpBoxes = findAllBoxes(data, 'jxlp')\n if (!jxlpBoxes.length) {\n return null\n }\n\n // Each `jxlp` payload is prefixed with a 4-byte partial-codestream index\n const codestream = Buffer.concat(\n jxlpBoxes.map((box) => data.subarray(box.bodyOffset + 4, box.offset + box.size)),\n )\n return parseJXLSizeHeader(codestream, 2)\n}\n\nfunction isJXLContainerSignature(data: Buffer): boolean {\n return (\n data.length >= 12 &&\n data.readUInt32BE(0) === 0x0000000c &&\n data.toString('ascii', 4, 8) === 'JXL ' &&\n data[8] === 0x0d &&\n data[9] === 0x0a &&\n data[10] === 0x87 &&\n data[11] === 0x0a\n )\n}\n\ntype Box = { bodyOffset: number; name: string; offset: number; size: number }\n\nfunction readBoxHeader(data: Buffer, offset: number): Box | null {\n if (offset + 8 > data.length) {\n return null\n }\n\n const name = data.toString('ascii', offset + 4, offset + 8)\n let size = data.readUInt32BE(offset)\n let bodyOffset = offset + 8\n\n if (size === 1) {\n // A size of 1 means a 64-bit size follows the 8-byte header\n if (offset + 16 > data.length) {\n return null\n }\n const largeSize = data.readBigUInt64BE(offset + 8)\n if (largeSize > BigInt(Number.MAX_SAFE_INTEGER)) {\n return null\n }\n size = Number(largeSize)\n bodyOffset = offset + 16\n } else if (size === 0) {\n // A size of 0 means the box extends to the end of the buffer\n size = data.length - offset\n }\n\n if (size < bodyOffset - offset || offset + size > data.length) {\n return null\n }\n\n return { name, bodyOffset, offset, size }\n}\n\n// Bounded to the same 1000-entry cap used elsewhere in this file so a\n// malformed chain of boxes can never block the event loop\nfunction findBox(data: Buffer, name: string, startOffset: number): Box | null {\n let offset = startOffset\n\n for (let i = 0; i < 1000 && offset < data.length; i++) {\n const box = readBoxHeader(data, offset)\n if (!box) {\n return null\n }\n if (box.name === name) {\n return box\n }\n offset += box.size\n }\n\n return null\n}\n\nfunction findAllBoxes(data: Buffer, name: string): Box[] {\n const boxes: Box[] = []\n let offset = 0\n\n for (let i = 0; i < 1000 && offset < data.length; i++) {\n const box = readBoxHeader(data, offset)\n if (!box) {\n break\n }\n if (box.name === name) {\n boxes.push(box)\n }\n offset += box.size\n }\n\n return boxes\n}\n\n/**\n * Reads the JXL `SizeHeader` bit-packed structure (little-endian, LSB\n * first) starting at `startOffset` in the codestream.\n */\nfunction parseJXLSizeHeader(data: Buffer, startOffset: number): Dimensions {\n let byteOffset = startOffset\n let bitOffset = 0\n\n const readBits = (length: number): number => {\n let result = 0\n let bitsRead = 0\n\n while (bitsRead < length) {\n if (byteOffset >= data.length) {\n throw new RangeError('Unexpected end of JXL codestream')\n }\n const currentByte = data[byteOffset]!\n const bitsLeft = 8 - bitOffset\n const bitsToRead = Math.min(length - bitsRead, bitsLeft)\n const mask = (1 << bitsToRead) - 1\n result |= ((currentByte >> bitOffset) & mask) << bitsRead\n\n bitsRead += bitsToRead\n bitOffset += bitsToRead\n if (bitOffset === 8) {\n byteOffset++\n bitOffset = 0\n }\n }\n\n return result\n }\n\n const readExplicitDimension = (): number => {\n const sizeClass = readBits(2)\n const extraBits = [9, 13, 18, 30][sizeClass]!\n return 1 + readBits(extraBits)\n }\n\n try {\n const isSmallImage = readBits(1) === 1\n const height = isSmallImage ? 8 * (1 + readBits(5)) : readExplicitDimension()\n const widthMode = readBits(3)\n\n let width: number\n if (isSmallImage && widthMode === 0) {\n width = 8 * (1 + readBits(5))\n } else if (widthMode === 0) {\n width = readExplicitDimension()\n } else {\n const aspectRatios = [1, 1.2, 4 / 3, 1.5, 16 / 9, 5 / 4, 2]\n width = Math.floor(height * aspectRatios[widthMode - 1]!)\n }\n\n return { height, width }\n } catch {\n return null\n }\n}\n"],"names":["createReadStream","fs","imageDimensionsFromData","imageDimensionsFromStream","probeImageSize","data","modernDimensions","dimensions","height","width","probeLegacyFormat","Error","HEADER_SNIFF_LENGTH","probeImageSizeFromPath","tempFilePath","headerSniff","readHeaderSniff","detectLegacyType","readFile","ReadableStream","from","handle","open","buffer","Buffer","alloc","bytesRead","read","subarray","close","type","legacyParsers","length","isJXLContainerSignature","head","toString","Math","min","test","trimStart","startsWith","bmp","abs","readInt32LE","ico","count","readUInt16LE","best","i","entry","jxl","parseJXL","svg","parseSVG","tiff","isLittleEndian","readU16","offset","readUInt16BE","readU32","readUInt32LE","readUInt32BE","ifdOffset","entryCount","tag","fieldType","value","text","tagMatch","match","readLength","name","RegExp","parseFloat","Number","isFinite","round","viewBoxMatch","parts","trim","split","map","every","n","viewWidth","viewHeight","parseJXLSizeHeader","jxlcBox","findBox","bodyOffset","jxlpBoxes","findAllBoxes","codestream","concat","box","size","readBoxHeader","largeSize","readBigUInt64BE","BigInt","MAX_SAFE_INTEGER","startOffset","boxes","push","byteOffset","bitOffset","readBits","result","bitsRead","RangeError","currentByte","bitsLeft","bitsToRead","mask","readExplicitDimension","sizeClass","extraBits","isSmallImage","widthMode","aspectRatios","floor"],"mappings":"AAAA,SAASA,gBAAgB,QAAQ,KAAI;AACrC,OAAOC,QAAQ,cAAa;AAC5B,SAASC,uBAAuB,EAAEC,yBAAyB,QAAQ,mBAAkB;AAIrF;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASC,eAAeC,IAAY;IACzC,MAAMC,mBAAmBJ,wBAAwBG;IACjD,MAAME,aAAaD,mBACf;QAAEE,QAAQF,iBAAiBE,MAAM;QAAEC,OAAOH,iBAAiBG,KAAK;IAAC,IACjEC,kBAAkBL;IAEtB,IAAI,CAACE,cAAc,CAACA,WAAWE,KAAK,IAAI,CAACF,WAAWC,MAAM,EAAE;QAC1D,MAAM,IAAIG,MAAM;IAClB;IAEA,OAAOJ;AACT;AAEA;;;CAGC,GACD,MAAMK,sBAAsB;AAE5B;;;;;;;;;CASC,GACD,OAAO,eAAeC,uBAAuBC,YAAoB;IAC/D,MAAMC,cAAc,MAAMC,gBAAgBF;IAE1C,IAAIG,iBAAiBF,cAAc;QACjC,OAAOX,eAAe,MAAMH,GAAGiB,QAAQ,CAACJ;IAC1C;IAEA,MAAMR,mBAAmB,MAAMH,0BAC7BgB,eAAeC,IAAI,CAACpB,iBAAiBc;IAGvC,IAAIR,kBAAkB;QACpB,OAAO;YAAEE,QAAQF,iBAAiBE,MAAM;YAAEC,OAAOH,iBAAiBG,KAAK;QAAC;IAC1E;IAEA,OAAOL,eAAe,MAAMH,GAAGiB,QAAQ,CAACJ;AAC1C;AAEA,eAAeE,gBAAgBF,YAAoB;IACjD,MAAMO,SAAS,MAAMpB,GAAGqB,IAAI,CAACR,cAAc;IAE3C,IAAI;QACF,MAAMS,SAASC,OAAOC,KAAK,CAACb;QAC5B,MAAM,EAAEc,SAAS,EAAE,GAAG,MAAML,OAAOM,IAAI,CAACJ,QAAQ,GAAGX,qBAAqB;QACxE,OAAOW,OAAOK,QAAQ,CAAC,GAAGF;IAC5B,SAAU;QACR,MAAML,OAAOQ,KAAK;IACpB;AACF;AAMA,SAASnB,kBAAkBL,IAAY;IACrC,MAAMyB,OAAOb,iBAAiBZ;IAC9B,OAAOyB,OAAOC,aAAa,CAACD,KAAK,CAACzB,QAAQ;AAC5C;AAEA,SAASY,iBAAiBZ,IAAY;IACpC,IAAIA,KAAK2B,MAAM,GAAG,GAAG;QACnB,OAAO;IACT;IAEA,IAAI3B,IAAI,CAAC,EAAE,KAAK,QAAQA,IAAI,CAAC,EAAE,KAAK,MAAM;QACxC,OAAO;IACT;IACA,IACEA,KAAK2B,MAAM,IAAI,KACd,CAAA,AAAC3B,IAAI,CAAC,EAAE,KAAK,QAAQA,IAAI,CAAC,EAAE,KAAK,QAAQA,IAAI,CAAC,EAAE,KAAK,QACnDA,IAAI,CAAC,EAAE,KAAK,QAAQA,IAAI,CAAC,EAAE,KAAK,QAAQA,IAAI,CAAC,EAAE,KAAK,IAAI,GAC3D;QACA,OAAO;IACT;IACA,IACEA,KAAK2B,MAAM,IAAI,KACf3B,IAAI,CAAC,EAAE,KAAK,KACZA,IAAI,CAAC,EAAE,KAAK,KACXA,CAAAA,IAAI,CAAC,EAAE,KAAK,KAAKA,IAAI,CAAC,EAAE,KAAK,CAAA,KAC9BA,IAAI,CAAC,EAAE,KAAK,GACZ;QACA,OAAO;IACT;IACA,IAAI,AAACA,IAAI,CAAC,EAAE,KAAK,QAAQA,IAAI,CAAC,EAAE,KAAK,QAAS4B,wBAAwB5B,OAAO;QAC3E,OAAO;IACT;IAEA,MAAM6B,OAAO7B,KAAK8B,QAAQ,CAAC,QAAQ,GAAGC,KAAKC,GAAG,CAAChC,KAAK2B,MAAM,EAAE;IAC5D,IAAI,aAAaM,IAAI,CAACJ,SAAUA,KAAKK,SAAS,GAAGC,UAAU,CAAC,YAAY,QAAQF,IAAI,CAACJ,OAAQ;QAC3F,OAAO;IACT;IAEA,OAAO;AACT;AAEA,MAAMH,gBAAuE;IAC3EU,KAAK,CAACpC,OAAU,CAAA;YAAEG,QAAQ4B,KAAKM,GAAG,CAACrC,KAAKsC,WAAW,CAAC;YAAMlC,OAAOJ,KAAKsC,WAAW,CAAC;QAAI,CAAA;IACtFC,KAAK,CAACvC;QACJ,MAAMwC,QAAQxC,KAAKyC,YAAY,CAAC;QAChC,IAAIC,OAAwB;YAAEvC,QAAQ;YAAGC,OAAO;QAAE;QAElD,IAAK,IAAIuC,IAAI,GAAGA,IAAIH,SAASG,IAAI,MAAMA,IAAK;YAC1C,MAAMC,QAAQ,IAAID,IAAI;YACtB,IAAIC,QAAQ,IAAI5C,KAAK2B,MAAM,EAAE;gBAC3B;YACF;YACA,6CAA6C;YAC7C,MAAMvB,QAAQJ,IAAI,CAAC4C,MAAM,KAAK,IAAI,MAAM5C,IAAI,CAAC4C,MAAM;YACnD,MAAMzC,SAASH,IAAI,CAAC4C,QAAQ,EAAE,KAAK,IAAI,MAAM5C,IAAI,CAAC4C,QAAQ,EAAE;YAC5D,IAAIxC,QAAQD,SAASuC,KAAKtC,KAAK,GAAGsC,KAAKvC,MAAM,EAAE;gBAC7CuC,OAAO;oBAAEvC;oBAAQC;gBAAM;YACzB;QACF;QAEA,OAAOsC,KAAKtC,KAAK,GAAGsC,OAAO;IAC7B;IACAG,KAAK,CAAC7C,OAAS8C,SAAS9C;IACxB+C,KAAK,CAAC/C,OAASgD,SAAShD;IACxBiD,MAAM,CAACjD;QACL,MAAMkD,iBAAiBlD,IAAI,CAAC,EAAE,KAAK;QACnC,MAAMmD,UAAU,CAACC,SACfF,iBAAiBlD,KAAKyC,YAAY,CAACW,UAAUpD,KAAKqD,YAAY,CAACD;QACjE,MAAME,UAAU,CAACF,SACfF,iBAAiBlD,KAAKuD,YAAY,CAACH,UAAUpD,KAAKwD,YAAY,CAACJ;QAEjE,MAAMK,YAAYH,QAAQ;QAC1B,IAAIG,YAAY,IAAIzD,KAAK2B,MAAM,EAAE;YAC/B,OAAO;QACT;QAEA,MAAM+B,aAAaP,QAAQM;QAC3B,IAAIrD;QACJ,IAAID;QAEJ,IAAK,IAAIwC,IAAI,GAAGA,IAAIe,cAAcf,IAAI,MAAMA,IAAK;YAC/C,MAAMC,QAAQa,YAAY,IAAId,IAAI;YAClC,IAAIC,QAAQ,KAAK5C,KAAK2B,MAAM,EAAE;gBAC5B;YACF;YACA,MAAMgC,MAAMR,QAAQP;YACpB,MAAMgB,YAAYT,QAAQP,QAAQ;YAClC,kEAAkE;YAClE,MAAMiB,QAAQD,cAAc,IAAIT,QAAQP,QAAQ,KAAKU,QAAQV,QAAQ;YACrE,IAAIe,QAAQ,KAAK;gBACfvD,QAAQyD;YACV,OAAO,IAAIF,QAAQ,KAAK;gBACtBxD,SAAS0D;YACX;QACF;QAEA,OAAOzD,SAASD,SAAS;YAAEA;YAAQC;QAAM,IAAI;IAC/C;AACF;AAEA,SAAS4C,SAAShD,IAAY;IAC5B,MAAM8D,OAAO9D,KAAK8B,QAAQ,CAAC,QAAQ,GAAGC,KAAKC,GAAG,CAAChC,KAAK2B,MAAM,EAAE;IAC5D,MAAMoC,WAAWD,KAAKE,KAAK,CAAC;IAC5B,IAAI,CAACD,UAAU;QACb,OAAO;IACT;IAEA,MAAMJ,MAAMI,QAAQ,CAAC,EAAE;IACvB,MAAME,aAAa,CAACC;QAClB,MAAMF,QAAQL,IAAIK,KAAK,CAAC,IAAIG,OAAO,GAAGD,KAAK,8BAA8B,CAAC,EAAE;QAC5E,IAAI,CAACF,OAAO;YACV,OAAO;QACT;QACA,iEAAiE;QACjE,IAAI,QAAQ/B,IAAI,CAAC+B,KAAK,CAAC,EAAE,GAAI;YAC3B,OAAO;QACT;QACA,MAAMH,QAAQO,WAAWJ,KAAK,CAAC,EAAE;QACjC,OAAOK,OAAOC,QAAQ,CAACT,SAASA,QAAQ;IAC1C;IAEA,MAAMzD,QAAQ6D,WAAW;IACzB,MAAM9D,SAAS8D,WAAW;IAC1B,IAAI7D,SAAS,QAAQD,UAAU,MAAM;QACnC,OAAO;YAAEA,QAAQ4B,KAAKwC,KAAK,CAACpE;YAASC,OAAO2B,KAAKwC,KAAK,CAACnE;QAAO;IAChE;IAEA,MAAMoE,eAAeb,IAAIK,KAAK,CAAC;IAC/B,IAAIQ,cAAc;QAChB,MAAMC,QAAQD,YAAY,CAAC,EAAE,CAC1BE,IAAI,GACJC,KAAK,CAAC,UACNC,GAAG,CAACP;QACP,IAAII,MAAM9C,MAAM,KAAK,KAAK8C,MAAMI,KAAK,CAAC,CAACC,IAAMT,OAAOC,QAAQ,CAACQ,KAAK;YAChE,MAAM,KAAKC,WAAWC,WAAW,GAAGP;YACpC,IAAIrE,SAAS,MAAM;gBACjB,OAAO;oBAAED,QAAQ4B,KAAKwC,KAAK,CAAC,AAACnE,QAAQ2E,YAAaC;oBAAa5E,OAAO2B,KAAKwC,KAAK,CAACnE;gBAAO;YAC1F;YACA,IAAID,UAAU,MAAM;gBAClB,OAAO;oBAAEA,QAAQ4B,KAAKwC,KAAK,CAACpE;oBAASC,OAAO2B,KAAKwC,KAAK,CAAC,AAACpE,SAAS6E,aAAcD;gBAAW;YAC5F;YACA,OAAO;gBAAE5E,QAAQ4B,KAAKwC,KAAK,CAACS;gBAAa5E,OAAO2B,KAAKwC,KAAK,CAACQ;YAAW;QACxE;IACF;IAEA,OAAO;AACT;AAEA;;;;;;;CAOC,GACD,SAASjC,SAAS9C,IAAY;IAC5B,IAAIA,IAAI,CAAC,EAAE,KAAK,QAAQA,IAAI,CAAC,EAAE,KAAK,MAAM;QACxC,OAAOiF,mBAAmBjF,MAAM;IAClC;IAEA,sEAAsE;IACtE,2DAA2D;IAC3D,MAAMkF,UAAUC,QAAQnF,MAAM,QAAQ;IACtC,IAAIkF,SAAS;QACX,OAAOD,mBAAmBjF,MAAMkF,QAAQE,UAAU,GAAG;IACvD;IAEA,MAAMC,YAAYC,aAAatF,MAAM;IACrC,IAAI,CAACqF,UAAU1D,MAAM,EAAE;QACrB,OAAO;IACT;IAEA,yEAAyE;IACzE,MAAM4D,aAAapE,OAAOqE,MAAM,CAC9BH,UAAUT,GAAG,CAAC,CAACa,MAAQzF,KAAKuB,QAAQ,CAACkE,IAAIL,UAAU,GAAG,GAAGK,IAAIrC,MAAM,GAAGqC,IAAIC,IAAI;IAEhF,OAAOT,mBAAmBM,YAAY;AACxC;AAEA,SAAS3D,wBAAwB5B,IAAY;IAC3C,OACEA,KAAK2B,MAAM,IAAI,MACf3B,KAAKwD,YAAY,CAAC,OAAO,cACzBxD,KAAK8B,QAAQ,CAAC,SAAS,GAAG,OAAO,UACjC9B,IAAI,CAAC,EAAE,KAAK,QACZA,IAAI,CAAC,EAAE,KAAK,QACZA,IAAI,CAAC,GAAG,KAAK,QACbA,IAAI,CAAC,GAAG,KAAK;AAEjB;AAIA,SAAS2F,cAAc3F,IAAY,EAAEoD,MAAc;IACjD,IAAIA,SAAS,IAAIpD,KAAK2B,MAAM,EAAE;QAC5B,OAAO;IACT;IAEA,MAAMuC,OAAOlE,KAAK8B,QAAQ,CAAC,SAASsB,SAAS,GAAGA,SAAS;IACzD,IAAIsC,OAAO1F,KAAKwD,YAAY,CAACJ;IAC7B,IAAIgC,aAAahC,SAAS;IAE1B,IAAIsC,SAAS,GAAG;QACd,4DAA4D;QAC5D,IAAItC,SAAS,KAAKpD,KAAK2B,MAAM,EAAE;YAC7B,OAAO;QACT;QACA,MAAMiE,YAAY5F,KAAK6F,eAAe,CAACzC,SAAS;QAChD,IAAIwC,YAAYE,OAAOzB,OAAO0B,gBAAgB,GAAG;YAC/C,OAAO;QACT;QACAL,OAAOrB,OAAOuB;QACdR,aAAahC,SAAS;IACxB,OAAO,IAAIsC,SAAS,GAAG;QACrB,6DAA6D;QAC7DA,OAAO1F,KAAK2B,MAAM,GAAGyB;IACvB;IAEA,IAAIsC,OAAON,aAAahC,UAAUA,SAASsC,OAAO1F,KAAK2B,MAAM,EAAE;QAC7D,OAAO;IACT;IAEA,OAAO;QAAEuC;QAAMkB;QAAYhC;QAAQsC;IAAK;AAC1C;AAEA,sEAAsE;AACtE,0DAA0D;AAC1D,SAASP,QAAQnF,IAAY,EAAEkE,IAAY,EAAE8B,WAAmB;IAC9D,IAAI5C,SAAS4C;IAEb,IAAK,IAAIrD,IAAI,GAAGA,IAAI,QAAQS,SAASpD,KAAK2B,MAAM,EAAEgB,IAAK;QACrD,MAAM8C,MAAME,cAAc3F,MAAMoD;QAChC,IAAI,CAACqC,KAAK;YACR,OAAO;QACT;QACA,IAAIA,IAAIvB,IAAI,KAAKA,MAAM;YACrB,OAAOuB;QACT;QACArC,UAAUqC,IAAIC,IAAI;IACpB;IAEA,OAAO;AACT;AAEA,SAASJ,aAAatF,IAAY,EAAEkE,IAAY;IAC9C,MAAM+B,QAAe,EAAE;IACvB,IAAI7C,SAAS;IAEb,IAAK,IAAIT,IAAI,GAAGA,IAAI,QAAQS,SAASpD,KAAK2B,MAAM,EAAEgB,IAAK;QACrD,MAAM8C,MAAME,cAAc3F,MAAMoD;QAChC,IAAI,CAACqC,KAAK;YACR;QACF;QACA,IAAIA,IAAIvB,IAAI,KAAKA,MAAM;YACrB+B,MAAMC,IAAI,CAACT;QACb;QACArC,UAAUqC,IAAIC,IAAI;IACpB;IAEA,OAAOO;AACT;AAEA;;;CAGC,GACD,SAAShB,mBAAmBjF,IAAY,EAAEgG,WAAmB;IAC3D,IAAIG,aAAaH;IACjB,IAAII,YAAY;IAEhB,MAAMC,WAAW,CAAC1E;QAChB,IAAI2E,SAAS;QACb,IAAIC,WAAW;QAEf,MAAOA,WAAW5E,OAAQ;YACxB,IAAIwE,cAAcnG,KAAK2B,MAAM,EAAE;gBAC7B,MAAM,IAAI6E,WAAW;YACvB;YACA,MAAMC,cAAczG,IAAI,CAACmG,WAAW;YACpC,MAAMO,WAAW,IAAIN;YACrB,MAAMO,aAAa5E,KAAKC,GAAG,CAACL,SAAS4E,UAAUG;YAC/C,MAAME,OAAO,AAAC,CAAA,KAAKD,UAAS,IAAK;YACjCL,UAAU,AAAC,CAAA,AAACG,eAAeL,YAAaQ,IAAG,KAAML;YAEjDA,YAAYI;YACZP,aAAaO;YACb,IAAIP,cAAc,GAAG;gBACnBD;gBACAC,YAAY;YACd;QACF;QAEA,OAAOE;IACT;IAEA,MAAMO,wBAAwB;QAC5B,MAAMC,YAAYT,SAAS;QAC3B,MAAMU,YAAY;YAAC;YAAG;YAAI;YAAI;SAAG,CAACD,UAAU;QAC5C,OAAO,IAAIT,SAASU;IACtB;IAEA,IAAI;QACF,MAAMC,eAAeX,SAAS,OAAO;QACrC,MAAMlG,SAAS6G,eAAe,IAAK,CAAA,IAAIX,SAAS,EAAC,IAAKQ;QACtD,MAAMI,YAAYZ,SAAS;QAE3B,IAAIjG;QACJ,IAAI4G,gBAAgBC,cAAc,GAAG;YACnC7G,QAAQ,IAAK,CAAA,IAAIiG,SAAS,EAAC;QAC7B,OAAO,IAAIY,cAAc,GAAG;YAC1B7G,QAAQyG;QACV,OAAO;YACL,MAAMK,eAAe;gBAAC;gBAAG;gBAAK,IAAI;gBAAG;gBAAK,KAAK;gBAAG,IAAI;gBAAG;aAAE;YAC3D9G,QAAQ2B,KAAKoF,KAAK,CAAChH,SAAS+G,YAAY,CAACD,YAAY,EAAE;QACzD;QAEA,OAAO;YAAE9G;YAAQC;QAAM;IACzB,EAAE,OAAM;QACN,OAAO;IACT;AACF"}