payload 3.89.0 → 3.90.1

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 (459) hide show
  1. package/dist/admin/forms/Field.d.ts +2 -0
  2. package/dist/admin/forms/Field.d.ts.map +1 -1
  3. package/dist/admin/forms/Field.js.map +1 -1
  4. package/dist/admin/forms/Form.d.ts +2 -0
  5. package/dist/admin/forms/Form.d.ts.map +1 -1
  6. package/dist/admin/forms/Form.js.map +1 -1
  7. package/dist/admin/functions/index.d.ts +3 -1
  8. package/dist/admin/functions/index.d.ts.map +1 -1
  9. package/dist/admin/functions/index.js.map +1 -1
  10. package/dist/admin/views/dashboard.d.ts +1 -1
  11. package/dist/admin/views/dashboard.d.ts.map +1 -1
  12. package/dist/admin/views/dashboard.js.map +1 -1
  13. package/dist/auth/applyUserReadAccess.d.ts +15 -0
  14. package/dist/auth/applyUserReadAccess.d.ts.map +1 -0
  15. package/dist/auth/applyUserReadAccess.js +41 -0
  16. package/dist/auth/applyUserReadAccess.js.map +1 -0
  17. package/dist/auth/baseFields/apiKey/canCreateOrUpdateAPIKey.d.ts +4 -0
  18. package/dist/auth/baseFields/apiKey/canCreateOrUpdateAPIKey.d.ts.map +1 -0
  19. package/dist/auth/baseFields/apiKey/canCreateOrUpdateAPIKey.js +20 -0
  20. package/dist/auth/baseFields/apiKey/canCreateOrUpdateAPIKey.js.map +1 -0
  21. package/dist/auth/baseFields/apiKey/encryptAPIKey.d.ts +4 -0
  22. package/dist/auth/baseFields/apiKey/encryptAPIKey.d.ts.map +1 -0
  23. package/dist/auth/baseFields/apiKey/encryptAPIKey.js +16 -0
  24. package/dist/auth/baseFields/apiKey/encryptAPIKey.js.map +1 -0
  25. package/dist/auth/baseFields/apiKey/index.d.ts +6 -0
  26. package/dist/auth/baseFields/apiKey/index.d.ts.map +1 -0
  27. package/dist/auth/baseFields/apiKey/index.js +112 -0
  28. package/dist/auth/baseFields/apiKey/index.js.map +1 -0
  29. package/dist/auth/baseFields/apiKey/omitAPIKey.d.ts +4 -0
  30. package/dist/auth/baseFields/apiKey/omitAPIKey.d.ts.map +1 -0
  31. package/dist/auth/baseFields/apiKey/omitAPIKey.js +8 -0
  32. package/dist/auth/baseFields/apiKey/omitAPIKey.js.map +1 -0
  33. package/dist/auth/baseFields/apiKey/omitAPIKeyIndex.d.ts +4 -0
  34. package/dist/auth/baseFields/apiKey/omitAPIKeyIndex.d.ts.map +1 -0
  35. package/dist/auth/baseFields/apiKey/omitAPIKeyIndex.js +5 -0
  36. package/dist/auth/baseFields/apiKey/omitAPIKeyIndex.js.map +1 -0
  37. package/dist/auth/baseFields/apiKey/omitEncryptedAPIKey.d.ts +4 -0
  38. package/dist/auth/baseFields/apiKey/omitEncryptedAPIKey.d.ts.map +1 -0
  39. package/dist/auth/baseFields/apiKey/omitEncryptedAPIKey.js +5 -0
  40. package/dist/auth/baseFields/apiKey/omitEncryptedAPIKey.js.map +1 -0
  41. package/dist/auth/baseFields/apiKey/setAPIKeyIndex.d.ts +4 -0
  42. package/dist/auth/baseFields/apiKey/setAPIKeyIndex.d.ts.map +1 -0
  43. package/dist/auth/baseFields/apiKey/setAPIKeyIndex.js +17 -0
  44. package/dist/auth/baseFields/apiKey/setAPIKeyIndex.js.map +1 -0
  45. package/dist/auth/baseFields/auth.d.ts +1 -0
  46. package/dist/auth/baseFields/auth.d.ts.map +1 -1
  47. package/dist/auth/baseFields/auth.js +9 -0
  48. package/dist/auth/baseFields/auth.js.map +1 -1
  49. package/dist/auth/defaultUnlockAccess.d.ts +3 -0
  50. package/dist/auth/defaultUnlockAccess.d.ts.map +1 -0
  51. package/dist/auth/defaultUnlockAccess.js +8 -0
  52. package/dist/auth/defaultUnlockAccess.js.map +1 -0
  53. package/dist/auth/endpoints/index.d.ts +1 -0
  54. package/dist/auth/endpoints/index.d.ts.map +1 -1
  55. package/dist/auth/endpoints/index.js +8 -0
  56. package/dist/auth/endpoints/index.js.map +1 -1
  57. package/dist/auth/endpoints/revealAPIKey.d.ts +7 -0
  58. package/dist/auth/endpoints/revealAPIKey.d.ts.map +1 -0
  59. package/dist/auth/endpoints/revealAPIKey.js +120 -0
  60. package/dist/auth/endpoints/revealAPIKey.js.map +1 -0
  61. package/dist/auth/executeAccess.d.ts +3 -1
  62. package/dist/auth/executeAccess.d.ts.map +1 -1
  63. package/dist/auth/executeAccess.js +2 -1
  64. package/dist/auth/executeAccess.js.map +1 -1
  65. package/dist/auth/getAuthFields.d.ts +1 -1
  66. package/dist/auth/getAuthFields.d.ts.map +1 -1
  67. package/dist/auth/getAuthFields.js +7 -4
  68. package/dist/auth/getAuthFields.js.map +1 -1
  69. package/dist/auth/getFieldsToSign.d.ts.map +1 -1
  70. package/dist/auth/getFieldsToSign.js +17 -10
  71. package/dist/auth/getFieldsToSign.js.map +1 -1
  72. package/dist/auth/getFieldsToSign.spec.js +114 -0
  73. package/dist/auth/getFieldsToSign.spec.js.map +1 -0
  74. package/dist/auth/jwt.d.ts.map +1 -1
  75. package/dist/auth/jwt.js +2 -0
  76. package/dist/auth/jwt.js.map +1 -1
  77. package/dist/auth/jwt.spec.js +24 -0
  78. package/dist/auth/jwt.spec.js.map +1 -0
  79. package/dist/auth/jwtAuth.d.ts +9 -0
  80. package/dist/auth/jwtAuth.d.ts.map +1 -0
  81. package/dist/auth/jwtAuth.js +8 -0
  82. package/dist/auth/jwtAuth.js.map +1 -0
  83. package/dist/auth/operations/auth.d.ts.map +1 -1
  84. package/dist/auth/operations/auth.js +2 -1
  85. package/dist/auth/operations/auth.js.map +1 -1
  86. package/dist/auth/operations/forgotPassword.d.ts.map +1 -1
  87. package/dist/auth/operations/forgotPassword.js +95 -7
  88. package/dist/auth/operations/forgotPassword.js.map +1 -1
  89. package/dist/auth/operations/local/auth.js +3 -1
  90. package/dist/auth/operations/local/auth.js.map +1 -1
  91. package/dist/auth/operations/login.d.ts.map +1 -1
  92. package/dist/auth/operations/login.js +48 -26
  93. package/dist/auth/operations/login.js.map +1 -1
  94. package/dist/auth/operations/refresh.d.ts.map +1 -1
  95. package/dist/auth/operations/refresh.js +32 -9
  96. package/dist/auth/operations/refresh.js.map +1 -1
  97. package/dist/auth/operations/registerFirstUser.d.ts.map +1 -1
  98. package/dist/auth/operations/registerFirstUser.js +3 -4
  99. package/dist/auth/operations/registerFirstUser.js.map +1 -1
  100. package/dist/auth/operations/resetPassword.d.ts.map +1 -1
  101. package/dist/auth/operations/resetPassword.js +31 -22
  102. package/dist/auth/operations/resetPassword.js.map +1 -1
  103. package/dist/auth/operations/unlock.d.ts.map +1 -1
  104. package/dist/auth/operations/unlock.js +1 -0
  105. package/dist/auth/operations/unlock.js.map +1 -1
  106. package/dist/auth/strategies/apiKey.d.ts.map +1 -1
  107. package/dist/auth/strategies/apiKey.js +15 -1
  108. package/dist/auth/strategies/apiKey.js.map +1 -1
  109. package/dist/auth/strategies/jwt.d.ts.map +1 -1
  110. package/dist/auth/strategies/jwt.js +61 -10
  111. package/dist/auth/strategies/jwt.js.map +1 -1
  112. package/dist/auth/strategies/jwt.spec.js +281 -0
  113. package/dist/auth/strategies/jwt.spec.js.map +1 -0
  114. package/dist/auth/strategies/local/authenticate.d.ts +5 -1
  115. package/dist/auth/strategies/local/authenticate.d.ts.map +1 -1
  116. package/dist/auth/strategies/local/authenticate.js +8 -3
  117. package/dist/auth/strategies/local/authenticate.js.map +1 -1
  118. package/dist/auth/strategies/local/authenticate.spec.js +37 -10
  119. package/dist/auth/strategies/local/authenticate.spec.js.map +1 -1
  120. package/dist/auth/strategies/local/generatePasswordSaltHash.d.ts +9 -1
  121. package/dist/auth/strategies/local/generatePasswordSaltHash.d.ts.map +1 -1
  122. package/dist/auth/strategies/local/generatePasswordSaltHash.js +61 -34
  123. package/dist/auth/strategies/local/generatePasswordSaltHash.js.map +1 -1
  124. package/dist/auth/types.d.ts +16 -1
  125. package/dist/auth/types.d.ts.map +1 -1
  126. package/dist/auth/types.js.map +1 -1
  127. package/dist/collections/config/client.d.ts +1 -0
  128. package/dist/collections/config/client.d.ts.map +1 -1
  129. package/dist/collections/config/client.js +3 -0
  130. package/dist/collections/config/client.js.map +1 -1
  131. package/dist/collections/config/defaults.d.ts.map +1 -1
  132. package/dist/collections/config/defaults.js +4 -2
  133. package/dist/collections/config/defaults.js.map +1 -1
  134. package/dist/collections/config/sanitize.d.ts.map +1 -1
  135. package/dist/collections/config/sanitize.js +17 -6
  136. package/dist/collections/config/sanitize.js.map +1 -1
  137. package/dist/collections/endpoints/index.d.ts +1 -0
  138. package/dist/collections/endpoints/index.d.ts.map +1 -1
  139. package/dist/collections/endpoints/index.js +6 -5
  140. package/dist/collections/endpoints/index.js.map +1 -1
  141. package/dist/collections/operations/create.d.ts.map +1 -1
  142. package/dist/collections/operations/create.js +105 -8
  143. package/dist/collections/operations/create.js.map +1 -1
  144. package/dist/collections/operations/deleteByID.js +13 -13
  145. package/dist/collections/operations/deleteByID.js.map +1 -1
  146. package/dist/collections/operations/findDistinct.d.ts.map +1 -1
  147. package/dist/collections/operations/findDistinct.js +96 -18
  148. package/dist/collections/operations/findDistinct.js.map +1 -1
  149. package/dist/collections/operations/restoreVersion.d.ts.map +1 -1
  150. package/dist/collections/operations/restoreVersion.js +47 -13
  151. package/dist/collections/operations/restoreVersion.js.map +1 -1
  152. package/dist/collections/operations/update.d.ts.map +1 -1
  153. package/dist/collections/operations/update.js +118 -18
  154. package/dist/collections/operations/update.js.map +1 -1
  155. package/dist/collections/operations/updateByID.d.ts.map +1 -1
  156. package/dist/collections/operations/updateByID.js +62 -2
  157. package/dist/collections/operations/updateByID.js.map +1 -1
  158. package/dist/collections/operations/utilities/update.d.ts.map +1 -1
  159. package/dist/collections/operations/utilities/update.js +71 -15
  160. package/dist/collections/operations/utilities/update.js.map +1 -1
  161. package/dist/config/orderable/index.d.ts.map +1 -1
  162. package/dist/config/orderable/index.js +67 -14
  163. package/dist/config/orderable/index.js.map +1 -1
  164. package/dist/config/sanitize.d.ts.map +1 -1
  165. package/dist/config/sanitize.js +1 -1
  166. package/dist/config/sanitize.js.map +1 -1
  167. package/dist/config/types.d.ts +13 -1
  168. package/dist/config/types.d.ts.map +1 -1
  169. package/dist/config/types.js.map +1 -1
  170. package/dist/database/getLocalizedPaths.d.ts +2 -1
  171. package/dist/database/getLocalizedPaths.d.ts.map +1 -1
  172. package/dist/database/getLocalizedPaths.js +12 -3
  173. package/dist/database/getLocalizedPaths.js.map +1 -1
  174. package/dist/database/isNestedRelationshipQuery.d.ts +9 -0
  175. package/dist/database/isNestedRelationshipQuery.d.ts.map +1 -0
  176. package/dist/database/isNestedRelationshipQuery.js +14 -0
  177. package/dist/database/isNestedRelationshipQuery.js.map +1 -0
  178. package/dist/database/prefixWherePaths.d.ts +6 -0
  179. package/dist/database/prefixWherePaths.d.ts.map +1 -0
  180. package/dist/database/prefixWherePaths.js +19 -0
  181. package/dist/database/prefixWherePaths.js.map +1 -0
  182. package/dist/database/prefixWherePaths.spec.js +46 -0
  183. package/dist/database/prefixWherePaths.spec.js.map +1 -0
  184. package/dist/database/queryValidation/validateQueryPaths.d.ts +2 -1
  185. package/dist/database/queryValidation/validateQueryPaths.d.ts.map +1 -1
  186. package/dist/database/queryValidation/validateQueryPaths.js +4 -1
  187. package/dist/database/queryValidation/validateQueryPaths.js.map +1 -1
  188. package/dist/database/queryValidation/validateSearchParams.d.ts +2 -1
  189. package/dist/database/queryValidation/validateSearchParams.d.ts.map +1 -1
  190. package/dist/database/queryValidation/validateSearchParams.js +87 -4
  191. package/dist/database/queryValidation/validateSearchParams.js.map +1 -1
  192. package/dist/database/types.d.ts +5 -0
  193. package/dist/database/types.d.ts.map +1 -1
  194. package/dist/database/types.js.map +1 -1
  195. package/dist/email/normalizeSendEmailOptions.js.map +1 -1
  196. package/dist/email/types.d.ts +4 -1
  197. package/dist/email/types.d.ts.map +1 -1
  198. package/dist/email/types.js.map +1 -1
  199. package/dist/exports/internal.d.ts +7 -0
  200. package/dist/exports/internal.d.ts.map +1 -1
  201. package/dist/exports/internal.js +7 -1
  202. package/dist/exports/internal.js.map +1 -1
  203. package/dist/exports/shared.d.ts +3 -0
  204. package/dist/exports/shared.d.ts.map +1 -1
  205. package/dist/exports/shared.js +3 -0
  206. package/dist/exports/shared.js.map +1 -1
  207. package/dist/fields/config/types.d.ts +7 -5
  208. package/dist/fields/config/types.d.ts.map +1 -1
  209. package/dist/fields/config/types.js.map +1 -1
  210. package/dist/fields/hooks/beforeChange/index.d.ts +7 -1
  211. package/dist/fields/hooks/beforeChange/index.d.ts.map +1 -1
  212. package/dist/fields/hooks/beforeChange/index.js +4 -2
  213. package/dist/fields/hooks/beforeChange/index.js.map +1 -1
  214. package/dist/fields/hooks/beforeChange/index.spec.js +206 -0
  215. package/dist/fields/hooks/beforeChange/index.spec.js.map +1 -0
  216. package/dist/fields/hooks/beforeChange/promise.d.ts +2 -1
  217. package/dist/fields/hooks/beforeChange/promise.d.ts.map +1 -1
  218. package/dist/fields/hooks/beforeChange/promise.js +51 -9
  219. package/dist/fields/hooks/beforeChange/promise.js.map +1 -1
  220. package/dist/fields/hooks/beforeChange/traverseFields.d.ts +2 -1
  221. package/dist/fields/hooks/beforeChange/traverseFields.d.ts.map +1 -1
  222. package/dist/fields/hooks/beforeChange/traverseFields.js +3 -2
  223. package/dist/fields/hooks/beforeChange/traverseFields.js.map +1 -1
  224. package/dist/fields/hooks/beforeDuplicate/promise.d.ts.map +1 -1
  225. package/dist/fields/hooks/beforeDuplicate/promise.js +4 -0
  226. package/dist/fields/hooks/beforeDuplicate/promise.js.map +1 -1
  227. package/dist/fields/hooks/beforeValidate/getFallbackValue.d.ts +2 -1
  228. package/dist/fields/hooks/beforeValidate/getFallbackValue.d.ts.map +1 -1
  229. package/dist/fields/hooks/beforeValidate/getFallbackValue.js +2 -2
  230. package/dist/fields/hooks/beforeValidate/getFallbackValue.js.map +1 -1
  231. package/dist/fields/hooks/beforeValidate/index.d.ts +6 -1
  232. package/dist/fields/hooks/beforeValidate/index.d.ts.map +1 -1
  233. package/dist/fields/hooks/beforeValidate/index.js +3 -1
  234. package/dist/fields/hooks/beforeValidate/index.js.map +1 -1
  235. package/dist/fields/hooks/beforeValidate/index.spec.js +90 -0
  236. package/dist/fields/hooks/beforeValidate/index.spec.js.map +1 -0
  237. package/dist/fields/hooks/beforeValidate/promise.d.ts +6 -1
  238. package/dist/fields/hooks/beforeValidate/promise.d.ts.map +1 -1
  239. package/dist/fields/hooks/beforeValidate/promise.js +23 -8
  240. package/dist/fields/hooks/beforeValidate/promise.js.map +1 -1
  241. package/dist/fields/hooks/beforeValidate/traverseFields.d.ts +6 -1
  242. package/dist/fields/hooks/beforeValidate/traverseFields.d.ts.map +1 -1
  243. package/dist/fields/hooks/beforeValidate/traverseFields.js +3 -1
  244. package/dist/fields/hooks/beforeValidate/traverseFields.js.map +1 -1
  245. package/dist/fields/validations.d.ts.map +1 -1
  246. package/dist/fields/validations.js +3 -1
  247. package/dist/fields/validations.js.map +1 -1
  248. package/dist/globals/operations/restoreVersion.d.ts.map +1 -1
  249. package/dist/globals/operations/restoreVersion.js +45 -11
  250. package/dist/globals/operations/restoreVersion.js.map +1 -1
  251. package/dist/globals/operations/update.d.ts.map +1 -1
  252. package/dist/globals/operations/update.js +95 -16
  253. package/dist/globals/operations/update.js.map +1 -1
  254. package/dist/index.bundled.d.ts +102 -24
  255. package/dist/index.d.ts +3 -1
  256. package/dist/index.d.ts.map +1 -1
  257. package/dist/index.js +2 -2
  258. package/dist/index.js.map +1 -1
  259. package/dist/preferences/config.d.ts.map +1 -1
  260. package/dist/preferences/config.js +2 -1
  261. package/dist/preferences/config.js.map +1 -1
  262. package/dist/query-presets/access.d.ts.map +1 -1
  263. package/dist/query-presets/access.js +2 -1
  264. package/dist/query-presets/access.js.map +1 -1
  265. package/dist/queues/config/types/index.d.ts +2 -1
  266. package/dist/queues/config/types/index.d.ts.map +1 -1
  267. package/dist/queues/config/types/index.js.map +1 -1
  268. package/dist/uploads/assertClientUploadAccess.d.ts +7 -0
  269. package/dist/uploads/assertClientUploadAccess.d.ts.map +1 -0
  270. package/dist/uploads/assertClientUploadAccess.js +27 -0
  271. package/dist/uploads/assertClientUploadAccess.js.map +1 -0
  272. package/dist/uploads/assertClientUploadAllowed.d.ts +11 -0
  273. package/dist/uploads/assertClientUploadAllowed.d.ts.map +1 -0
  274. package/dist/uploads/assertClientUploadAllowed.js +46 -0
  275. package/dist/uploads/assertClientUploadAllowed.js.map +1 -0
  276. package/dist/uploads/assertClientUploadAllowed.spec.js +91 -0
  277. package/dist/uploads/assertClientUploadAllowed.spec.js.map +1 -0
  278. package/dist/uploads/checkFileRestrictions.d.ts +4 -1
  279. package/dist/uploads/checkFileRestrictions.d.ts.map +1 -1
  280. package/dist/uploads/checkFileRestrictions.js +66 -26
  281. package/dist/uploads/checkFileRestrictions.js.map +1 -1
  282. package/dist/uploads/clientUploadReceipt.d.ts +23 -0
  283. package/dist/uploads/clientUploadReceipt.d.ts.map +1 -0
  284. package/dist/uploads/clientUploadReceipt.js +55 -0
  285. package/dist/uploads/clientUploadReceipt.js.map +1 -0
  286. package/dist/uploads/deleteAssociatedFiles.d.ts.map +1 -1
  287. package/dist/uploads/deleteAssociatedFiles.js +33 -8
  288. package/dist/uploads/deleteAssociatedFiles.js.map +1 -1
  289. package/dist/uploads/deleteAssociatedFiles.spec.js +124 -0
  290. package/dist/uploads/deleteAssociatedFiles.spec.js.map +1 -0
  291. package/dist/uploads/detectSvgFromXml.d.ts +1 -3
  292. package/dist/uploads/detectSvgFromXml.d.ts.map +1 -1
  293. package/dist/uploads/detectSvgFromXml.js +3 -40
  294. package/dist/uploads/detectSvgFromXml.js.map +1 -1
  295. package/dist/uploads/endpoints/getFile.d.ts.map +1 -1
  296. package/dist/uploads/endpoints/getFile.js +5 -3
  297. package/dist/uploads/endpoints/getFile.js.map +1 -1
  298. package/dist/uploads/fetchAPI-multipart/handlers.d.ts +2 -2
  299. package/dist/uploads/fetchAPI-multipart/handlers.d.ts.map +1 -1
  300. package/dist/uploads/fetchAPI-multipart/handlers.js +18 -5
  301. package/dist/uploads/fetchAPI-multipart/handlers.js.map +1 -1
  302. package/dist/uploads/fetchAPI-multipart/index.d.ts.map +1 -1
  303. package/dist/uploads/fetchAPI-multipart/index.js +24 -2
  304. package/dist/uploads/fetchAPI-multipart/index.js.map +1 -1
  305. package/dist/uploads/fetchAPI-multipart/processMultipart.d.ts +0 -6
  306. package/dist/uploads/fetchAPI-multipart/processMultipart.d.ts.map +1 -1
  307. package/dist/uploads/fetchAPI-multipart/processMultipart.js +146 -126
  308. package/dist/uploads/fetchAPI-multipart/processMultipart.js.map +1 -1
  309. package/dist/uploads/fetchAPI-multipart/processMultipart.spec.js +663 -0
  310. package/dist/uploads/fetchAPI-multipart/processMultipart.spec.js.map +1 -0
  311. package/dist/uploads/generateFileData.d.ts +3 -1
  312. package/dist/uploads/generateFileData.d.ts.map +1 -1
  313. package/dist/uploads/generateFileData.js +29 -16
  314. package/dist/uploads/generateFileData.js.map +1 -1
  315. package/dist/uploads/getBaseFields.d.ts.map +1 -1
  316. package/dist/uploads/getBaseFields.js +3 -1
  317. package/dist/uploads/getBaseFields.js.map +1 -1
  318. package/dist/uploads/getExternalFile.d.ts +1 -1
  319. package/dist/uploads/getExternalFile.d.ts.map +1 -1
  320. package/dist/uploads/getExternalFile.js +60 -15
  321. package/dist/uploads/getExternalFile.js.map +1 -1
  322. package/dist/uploads/getFileTypeFallback.d.ts.map +1 -1
  323. package/dist/uploads/getFileTypeFallback.js +3 -1
  324. package/dist/uploads/getFileTypeFallback.js.map +1 -1
  325. package/dist/uploads/getFileTypeIdentity.d.ts +19 -0
  326. package/dist/uploads/getFileTypeIdentity.d.ts.map +1 -0
  327. package/dist/uploads/getFileTypeIdentity.js +34 -0
  328. package/dist/uploads/getFileTypeIdentity.js.map +1 -0
  329. package/dist/uploads/getFileTypeIdentity.spec.js +43 -0
  330. package/dist/uploads/getFileTypeIdentity.spec.js.map +1 -0
  331. package/dist/uploads/isProcessableImage.d.ts +2 -0
  332. package/dist/uploads/isProcessableImage.d.ts.map +1 -0
  333. package/dist/uploads/isProcessableImage.js +7 -0
  334. package/dist/uploads/isProcessableImage.js.map +1 -0
  335. package/dist/uploads/safeFetch.d.ts.map +1 -1
  336. package/dist/uploads/safeFetch.js +3 -2
  337. package/dist/uploads/safeFetch.js.map +1 -1
  338. package/dist/uploads/sanitizeUploadData.d.ts +26 -0
  339. package/dist/uploads/sanitizeUploadData.d.ts.map +1 -0
  340. package/dist/uploads/sanitizeUploadData.js +159 -0
  341. package/dist/uploads/sanitizeUploadData.js.map +1 -0
  342. package/dist/uploads/sanitizeUploadData.spec.js +255 -0
  343. package/dist/uploads/sanitizeUploadData.spec.js.map +1 -0
  344. package/dist/uploads/types.d.ts +11 -3
  345. package/dist/uploads/types.d.ts.map +1 -1
  346. package/dist/uploads/types.js.map +1 -1
  347. package/dist/uploads/uploadContentSecurityPolicy.d.ts +2 -0
  348. package/dist/uploads/uploadContentSecurityPolicy.d.ts.map +1 -0
  349. package/dist/uploads/uploadContentSecurityPolicy.js +3 -0
  350. package/dist/uploads/uploadContentSecurityPolicy.js.map +1 -0
  351. package/dist/uploads/validateISOBaseMediaFile.d.ts +4 -0
  352. package/dist/uploads/validateISOBaseMediaFile.d.ts.map +1 -0
  353. package/dist/uploads/validateISOBaseMediaFile.js +91 -0
  354. package/dist/uploads/validateISOBaseMediaFile.js.map +1 -0
  355. package/dist/uploads/validateISOBaseMediaFile.spec.js +130 -0
  356. package/dist/uploads/validateISOBaseMediaFile.spec.js.map +1 -0
  357. package/dist/uploads/validateSvg.d.ts +10 -4
  358. package/dist/uploads/validateSvg.d.ts.map +1 -1
  359. package/dist/uploads/validateSvg.js +280 -40
  360. package/dist/uploads/validateSvg.js.map +1 -1
  361. package/dist/uploads/validateSvg.spec.js +123 -0
  362. package/dist/uploads/validateSvg.spec.js.map +1 -0
  363. package/dist/uploads/validateUploadFilename.d.ts +3 -0
  364. package/dist/uploads/validateUploadFilename.d.ts.map +1 -0
  365. package/dist/uploads/validateUploadFilename.js +13 -0
  366. package/dist/uploads/validateUploadFilename.js.map +1 -0
  367. package/dist/uploads/validateUploadFilename.spec.js +24 -0
  368. package/dist/uploads/validateUploadFilename.spec.js.map +1 -0
  369. package/dist/utilities/addDataAndFileToRequest.d.ts.map +1 -1
  370. package/dist/utilities/addDataAndFileToRequest.js +28 -1
  371. package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
  372. package/dist/utilities/addDataAndFileToRequest.spec.js +158 -0
  373. package/dist/utilities/addDataAndFileToRequest.spec.js.map +1 -1
  374. package/dist/utilities/createPayloadRequest.d.ts.map +1 -1
  375. package/dist/utilities/createPayloadRequest.js +2 -1
  376. package/dist/utilities/createPayloadRequest.js.map +1 -1
  377. package/dist/utilities/deepCopyObject.d.ts.map +1 -1
  378. package/dist/utilities/deepCopyObject.js +110 -19
  379. package/dist/utilities/deepCopyObject.js.map +1 -1
  380. package/dist/utilities/deepCopyObject.spec.js +216 -0
  381. package/dist/utilities/deepCopyObject.spec.js.map +1 -0
  382. package/dist/utilities/fieldPath.d.ts +13 -0
  383. package/dist/utilities/fieldPath.d.ts.map +1 -0
  384. package/dist/utilities/fieldPath.js +51 -0
  385. package/dist/utilities/fieldPath.js.map +1 -0
  386. package/dist/utilities/fieldPath.spec.js +155 -0
  387. package/dist/utilities/fieldPath.spec.js.map +1 -0
  388. package/dist/utilities/getEntityPermissions/getEntityPermissions.d.ts.map +1 -1
  389. package/dist/utilities/getEntityPermissions/getEntityPermissions.js +2 -0
  390. package/dist/utilities/getEntityPermissions/getEntityPermissions.js.map +1 -1
  391. package/dist/utilities/getObjectDotNotation.d.ts.map +1 -1
  392. package/dist/utilities/getObjectDotNotation.js +7 -1
  393. package/dist/utilities/getObjectDotNotation.js.map +1 -1
  394. package/dist/utilities/getObjectDotNotation.spec.js +33 -0
  395. package/dist/utilities/getObjectDotNotation.spec.js.map +1 -0
  396. package/dist/utilities/getSafeRedirect.spec.js +14 -0
  397. package/dist/utilities/getSafeRedirect.spec.js.map +1 -1
  398. package/dist/utilities/getTopLevelFieldNames.d.ts +2 -0
  399. package/dist/utilities/getTopLevelFieldNames.d.ts.map +1 -0
  400. package/dist/utilities/getTopLevelFieldNames.js +3 -0
  401. package/dist/utilities/getTopLevelFieldNames.js.map +1 -0
  402. package/dist/utilities/getTopLevelFieldNames.spec.js +18 -0
  403. package/dist/utilities/getTopLevelFieldNames.spec.js.map +1 -0
  404. package/dist/utilities/handleEndpoints.js +1 -1
  405. package/dist/utilities/handleEndpoints.js.map +1 -1
  406. package/dist/utilities/parseParams/index.d.ts.map +1 -1
  407. package/dist/utilities/parseParams/index.js +3 -1
  408. package/dist/utilities/parseParams/index.js.map +1 -1
  409. package/dist/utilities/parseParams/index.spec.js +8 -0
  410. package/dist/utilities/parseParams/index.spec.js.map +1 -1
  411. package/dist/utilities/telemetry/featureInfo/getFeatureInfo.d.ts +4 -0
  412. package/dist/utilities/telemetry/featureInfo/getFeatureInfo.d.ts.map +1 -0
  413. package/dist/utilities/telemetry/featureInfo/getFeatureInfo.js +248 -0
  414. package/dist/utilities/telemetry/featureInfo/getFeatureInfo.js.map +1 -0
  415. package/dist/utilities/telemetry/featureInfo/types.d.ts +62 -0
  416. package/dist/utilities/telemetry/featureInfo/types.d.ts.map +1 -0
  417. package/dist/utilities/telemetry/featureInfo/types.js +3 -0
  418. package/dist/utilities/telemetry/featureInfo/types.js.map +1 -0
  419. package/dist/utilities/telemetry/getProjectContext.d.ts +14 -0
  420. package/dist/utilities/telemetry/getProjectContext.d.ts.map +1 -0
  421. package/dist/utilities/telemetry/getProjectContext.js +36 -0
  422. package/dist/utilities/telemetry/getProjectContext.js.map +1 -0
  423. package/dist/utilities/telemetry/index.d.ts +7 -1
  424. package/dist/utilities/telemetry/index.d.ts.map +1 -1
  425. package/dist/utilities/telemetry/index.js +22 -0
  426. package/dist/utilities/telemetry/index.js.map +1 -1
  427. package/dist/utilities/traverseFields.d.ts.map +1 -1
  428. package/dist/utilities/traverseFields.js +5 -14
  429. package/dist/utilities/traverseFields.js.map +1 -1
  430. package/dist/utilities/unflatten.d.ts.map +1 -1
  431. package/dist/utilities/unflatten.js +21 -9
  432. package/dist/utilities/unflatten.js.map +1 -1
  433. package/dist/utilities/unflatten.spec.js +38 -0
  434. package/dist/utilities/unflatten.spec.js.map +1 -0
  435. package/dist/versions/allLocalesPublicationStatus.d.ts +38 -0
  436. package/dist/versions/allLocalesPublicationStatus.d.ts.map +1 -0
  437. package/dist/versions/allLocalesPublicationStatus.js +57 -0
  438. package/dist/versions/allLocalesPublicationStatus.js.map +1 -0
  439. package/dist/versions/getLatestGlobalVersion.d.ts.map +1 -1
  440. package/dist/versions/getLatestGlobalVersion.js +10 -2
  441. package/dist/versions/getLatestGlobalVersion.js.map +1 -1
  442. package/dist/versions/getRestoredStatusesToAuthorize.d.ts +9 -0
  443. package/dist/versions/getRestoredStatusesToAuthorize.d.ts.map +1 -0
  444. package/dist/versions/getRestoredStatusesToAuthorize.js +22 -0
  445. package/dist/versions/getRestoredStatusesToAuthorize.js.map +1 -0
  446. package/dist/versions/getRestoredStatusesToAuthorize.spec.js +50 -0
  447. package/dist/versions/getRestoredStatusesToAuthorize.spec.js.map +1 -0
  448. package/dist/versions/schedule/job.d.ts +2 -2
  449. package/dist/versions/schedule/job.d.ts.map +1 -1
  450. package/dist/versions/schedule/job.js +11 -7
  451. package/dist/versions/schedule/job.js.map +1 -1
  452. package/dist/versions/schedule/types.d.ts +5 -1
  453. package/dist/versions/schedule/types.d.ts.map +1 -1
  454. package/dist/versions/schedule/types.js.map +1 -1
  455. package/package.json +4 -2
  456. package/dist/auth/baseFields/apiKey.d.ts +0 -3
  457. package/dist/auth/baseFields/apiKey.d.ts.map +0 -1
  458. package/dist/auth/baseFields/apiKey.js +0 -59
  459. package/dist/auth/baseFields/apiKey.js.map +0 -1
@@ -0,0 +1,663 @@
1
+ import fs from 'fs';
2
+ import { mkdtemp, readFile, readdir, rm, stat, writeFile } from 'fs/promises';
3
+ import { tmpdir } from 'os';
4
+ import path from 'path';
5
+ import { describe, expect, it, vi } from 'vitest';
6
+ import { processMultipartFormdata } from './index.js';
7
+ const requestFor = (form)=>new Request('http://localhost/api/media', {
8
+ body: form,
9
+ method: 'POST'
10
+ });
11
+ const fileForm = (size)=>{
12
+ const form = new FormData();
13
+ form.append('file', new Blob([
14
+ new Uint8Array(size)
15
+ ]), 'sample.bin');
16
+ return form;
17
+ };
18
+ const streamedFileRequest = ({ chunk, chunkCount, isClosed = true, onCancel })=>{
19
+ const header = Buffer.from('--sample\r\nContent-Disposition: form-data; name="file"; filename="sample.bin"\r\nContent-Type: application/octet-stream\r\n\r\n');
20
+ const footer = Buffer.from('\r\n--sample--\r\n');
21
+ let chunksRead = 0;
22
+ const body = new ReadableStream({
23
+ cancel () {
24
+ onCancel?.();
25
+ },
26
+ pull (controller) {
27
+ if (chunksRead === 0) {
28
+ controller.enqueue(header);
29
+ } else if (chunksRead <= chunkCount) {
30
+ controller.enqueue(chunk);
31
+ } else if (isClosed) {
32
+ controller.enqueue(footer);
33
+ controller.close();
34
+ }
35
+ chunksRead += 1;
36
+ }
37
+ });
38
+ return new Request('http://localhost/api/media', {
39
+ body,
40
+ duplex: 'half',
41
+ method: 'POST',
42
+ headers: {
43
+ 'content-type': 'multipart/form-data; boundary=sample'
44
+ }
45
+ });
46
+ };
47
+ describe('multipart limits', ()=>{
48
+ it('should reject files above the default size with a partial limit override', async ()=>{
49
+ await expect(processMultipartFormdata({
50
+ options: {
51
+ limits: {
52
+ fields: 2
53
+ }
54
+ },
55
+ request: requestFor(fileForm(20 * 1024 * 1024 + 1))
56
+ }).then(()=>'accepted')).rejects.toMatchObject({
57
+ status: 413
58
+ });
59
+ });
60
+ it.each([
61
+ {
62
+ kind: 'files',
63
+ count: 3,
64
+ append: ({ form, index })=>form.append('file', new Blob([
65
+ 'sample'
66
+ ]), `sample-${index}.txt`)
67
+ },
68
+ {
69
+ kind: 'fields',
70
+ count: 3,
71
+ append: ({ form, index })=>form.append(`field${index}`, 'sample')
72
+ }
73
+ ])('should reject requests above the configured $kind count', async ({ kind, count, append })=>{
74
+ const form = new FormData();
75
+ for(let i = 0; i < count; i++){
76
+ append({
77
+ form,
78
+ index: i
79
+ });
80
+ }
81
+ await expect(processMultipartFormdata({
82
+ options: {
83
+ limits: {
84
+ [kind]: 2
85
+ }
86
+ },
87
+ request: requestFor(form)
88
+ })).rejects.toMatchObject({
89
+ status: 413
90
+ });
91
+ });
92
+ it('should preserve explicitly requested file truncation', async ()=>{
93
+ const result = await processMultipartFormdata({
94
+ options: {
95
+ abortOnLimit: false,
96
+ limits: {
97
+ fileSize: 3
98
+ }
99
+ },
100
+ request: requestFor(fileForm(6))
101
+ });
102
+ expect(result.files.file).toMatchObject({
103
+ size: 3,
104
+ truncated: true
105
+ });
106
+ });
107
+ it('should parse ordinary files and fields', async ()=>{
108
+ const form = fileForm(6);
109
+ form.append('_payload', '{"title":"Sample"}');
110
+ const result = await processMultipartFormdata({
111
+ request: requestFor(form)
112
+ });
113
+ expect(result.files.file.size).toBe(6);
114
+ expect(result.fields._payload).toBe('{"title":"Sample"}');
115
+ });
116
+ it.each([
117
+ {
118
+ label: 'NaN',
119
+ requestSizeLimit: Number.NaN
120
+ },
121
+ {
122
+ label: 'a negative value',
123
+ requestSizeLimit: -1
124
+ },
125
+ {
126
+ label: 'negative Infinity',
127
+ requestSizeLimit: -Infinity
128
+ },
129
+ {
130
+ label: 'a fractional value',
131
+ requestSizeLimit: 1.5
132
+ },
133
+ {
134
+ label: 'an unsafe integer',
135
+ requestSizeLimit: Number.MAX_SAFE_INTEGER + 1
136
+ }
137
+ ])('should reject $label as a request size limit', async ({ requestSizeLimit })=>{
138
+ const request = requestFor(fileForm(1));
139
+ await expect(processMultipartFormdata({
140
+ options: {
141
+ requestSizeLimit
142
+ },
143
+ request
144
+ })).rejects.toThrow('requestSizeLimit must be Infinity or a non-negative safe integer representing bytes');
145
+ expect(request.body.locked).toBe(false);
146
+ });
147
+ it('should accept zero as a request size limit', async ()=>{
148
+ await expect(processMultipartFormdata({
149
+ options: {
150
+ requestSizeLimit: 0
151
+ },
152
+ request: requestFor(fileForm(1))
153
+ })).rejects.toThrow('Multipart request size limit has been reached');
154
+ });
155
+ it.each([
156
+ Number.MAX_SAFE_INTEGER,
157
+ Infinity
158
+ ])('should accept %s as a request size limit', async (requestSizeLimit)=>{
159
+ const result = await processMultipartFormdata({
160
+ options: {
161
+ requestSizeLimit
162
+ },
163
+ request: requestFor(fileForm(1))
164
+ });
165
+ expect(result.files.file.size).toBe(1);
166
+ });
167
+ });
168
+ describe('multipart streaming', ()=>{
169
+ it('should cancel an unfinished body promptly when a file reaches its limit', async ()=>{
170
+ let cancelled = false;
171
+ const body = new ReadableStream({
172
+ start (controller) {
173
+ controller.enqueue(Buffer.from('--sample\r\nContent-Disposition: form-data; name="file"; filename="sample.txt"\r\nContent-Type: text/plain\r\n\r\nsample data'));
174
+ },
175
+ cancel () {
176
+ cancelled = true;
177
+ }
178
+ });
179
+ const request = new Request('http://localhost/api/media', {
180
+ body,
181
+ duplex: 'half',
182
+ method: 'POST',
183
+ headers: {
184
+ 'content-type': 'multipart/form-data; boundary=sample'
185
+ }
186
+ });
187
+ await expect(processMultipartFormdata({
188
+ options: {
189
+ limits: {
190
+ fileSize: 3
191
+ }
192
+ },
193
+ request
194
+ })).rejects.toMatchObject({
195
+ status: 413
196
+ });
197
+ expect(cancelled).toBe(true);
198
+ }, 1000);
199
+ it.each([
200
+ {
201
+ label: 'omitted',
202
+ override: {}
203
+ },
204
+ {
205
+ label: 'explicitly undefined',
206
+ override: {
207
+ requestSizeLimit: undefined
208
+ }
209
+ }
210
+ ])('should enforce the default request size when it is $label', async ({ override })=>{
211
+ const directory = await mkdtemp(path.join(tmpdir(), 'multipart-'));
212
+ try {
213
+ const options = {
214
+ limits: {
215
+ fileSize: Infinity
216
+ },
217
+ tempFileDir: directory,
218
+ useTempFiles: true,
219
+ ...override
220
+ };
221
+ await expect(processMultipartFormdata({
222
+ options,
223
+ request: streamedFileRequest({
224
+ chunk: Buffer.alloc(1024 * 1024),
225
+ chunkCount: 51
226
+ })
227
+ })).rejects.toMatchObject({
228
+ status: 413
229
+ });
230
+ expect(await readdir(directory)).toEqual([]);
231
+ } finally{
232
+ await rm(directory, {
233
+ recursive: true,
234
+ force: true
235
+ });
236
+ }
237
+ });
238
+ it('should accept requests within the default request size', async ()=>{
239
+ const directory = await mkdtemp(path.join(tmpdir(), 'multipart-'));
240
+ try {
241
+ const result = await processMultipartFormdata({
242
+ options: {
243
+ limits: {
244
+ fileSize: Infinity
245
+ },
246
+ tempFileDir: directory,
247
+ useTempFiles: true
248
+ },
249
+ request: streamedFileRequest({
250
+ chunk: Buffer.alloc(1024 * 1024),
251
+ chunkCount: 49
252
+ })
253
+ });
254
+ expect((await stat(result.files.file.tempFilePath)).size).toBe(49 * 1024 * 1024);
255
+ } finally{
256
+ await rm(directory, {
257
+ recursive: true,
258
+ force: true
259
+ });
260
+ }
261
+ });
262
+ it('should accept requests above the default size with a larger finite limit', async ()=>{
263
+ const directory = await mkdtemp(path.join(tmpdir(), 'multipart-'));
264
+ try {
265
+ const result = await processMultipartFormdata({
266
+ options: {
267
+ limits: {
268
+ fileSize: Infinity
269
+ },
270
+ requestSizeLimit: 52 * 1024 * 1024,
271
+ tempFileDir: directory,
272
+ useTempFiles: true
273
+ },
274
+ request: streamedFileRequest({
275
+ chunk: Buffer.alloc(1024 * 1024),
276
+ chunkCount: 51
277
+ })
278
+ });
279
+ expect((await stat(result.files.file.tempFilePath)).size).toBe(51 * 1024 * 1024);
280
+ } finally{
281
+ await rm(directory, {
282
+ recursive: true,
283
+ force: true
284
+ });
285
+ }
286
+ });
287
+ it('should accept requests above the default size when the limit is disabled', async ()=>{
288
+ const directory = await mkdtemp(path.join(tmpdir(), 'multipart-'));
289
+ try {
290
+ const result = await processMultipartFormdata({
291
+ options: {
292
+ limits: {
293
+ fileSize: Infinity
294
+ },
295
+ requestSizeLimit: Infinity,
296
+ tempFileDir: directory,
297
+ useTempFiles: true
298
+ },
299
+ request: streamedFileRequest({
300
+ chunk: Buffer.alloc(1024 * 1024),
301
+ chunkCount: 51
302
+ })
303
+ });
304
+ expect((await stat(result.files.file.tempFilePath)).size).toBe(51 * 1024 * 1024);
305
+ } finally{
306
+ await rm(directory, {
307
+ recursive: true,
308
+ force: true
309
+ });
310
+ }
311
+ });
312
+ it('should cancel and clean up before forwarding a chunk above the request size limit', async ()=>{
313
+ const directory = await mkdtemp(path.join(tmpdir(), 'multipart-'));
314
+ let isCancelled = false;
315
+ try {
316
+ await expect(processMultipartFormdata({
317
+ options: {
318
+ limits: {
319
+ fileSize: 192 * 1024
320
+ },
321
+ requestSizeLimit: 200 * 1024,
322
+ responseOnLimit: 'File size limit has been reached',
323
+ tempFileDir: directory,
324
+ useTempFiles: true
325
+ },
326
+ request: streamedFileRequest({
327
+ chunk: Buffer.alloc(128 * 1024),
328
+ chunkCount: 2,
329
+ isClosed: false,
330
+ onCancel: ()=>{
331
+ isCancelled = true;
332
+ }
333
+ })
334
+ })).rejects.toThrow('Multipart request size limit has been reached');
335
+ expect(isCancelled).toBe(true);
336
+ expect(await readdir(directory)).toEqual([]);
337
+ } finally{
338
+ await rm(directory, {
339
+ recursive: true,
340
+ force: true
341
+ });
342
+ }
343
+ }, 1000);
344
+ it.each([
345
+ {
346
+ kind: 'files',
347
+ count: 4,
348
+ append: ({ form, index })=>form.append('file', new Blob([
349
+ 'sample'
350
+ ]), `sample-${index}.txt`)
351
+ },
352
+ {
353
+ kind: 'fields',
354
+ count: 21,
355
+ append: ({ form, index })=>form.append(`field${index}`, 'sample')
356
+ }
357
+ ])('should enforce the default $kind count with another limit overridden', async ({ count, append })=>{
358
+ const form = new FormData();
359
+ for(let i = 0; i < count; i++){
360
+ append({
361
+ form,
362
+ index: i
363
+ });
364
+ }
365
+ await expect(processMultipartFormdata({
366
+ options: {
367
+ limits: {
368
+ fileSize: 100
369
+ }
370
+ },
371
+ request: requestFor(form)
372
+ }).then(()=>'accepted')).rejects.toMatchObject({
373
+ status: 413
374
+ });
375
+ });
376
+ it('should accept an explicitly increased file count', async ()=>{
377
+ const form = new FormData();
378
+ for(let i = 0; i < 11; i++)form.append(`file${i}`, new Blob([
379
+ 'sample'
380
+ ]), `sample-${i}.txt`);
381
+ const result = await processMultipartFormdata({
382
+ options: {
383
+ limits: {
384
+ files: 11
385
+ }
386
+ },
387
+ request: requestFor(form)
388
+ });
389
+ expect(Object.keys(result.files)).toHaveLength(11);
390
+ });
391
+ it('should reject oversized fields', async ()=>{
392
+ const form = new FormData();
393
+ form.append('title', 'sample');
394
+ await expect(processMultipartFormdata({
395
+ options: {
396
+ limits: {
397
+ fieldSize: 3
398
+ }
399
+ },
400
+ request: requestFor(form)
401
+ })).rejects.toMatchObject({
402
+ status: 413
403
+ });
404
+ });
405
+ it('should reject requests above the configured part count', async ()=>{
406
+ const form = fileForm(6);
407
+ form.append('title', 'sample');
408
+ await expect(processMultipartFormdata({
409
+ options: {
410
+ limits: {
411
+ parts: 1
412
+ }
413
+ },
414
+ request: requestFor(form)
415
+ })).rejects.toMatchObject({
416
+ status: 413
417
+ });
418
+ });
419
+ it('should remove completed and partial temporary files after a limit', async ()=>{
420
+ const directory = await mkdtemp(path.join(tmpdir(), 'multipart-'));
421
+ try {
422
+ const form = new FormData();
423
+ form.append('first', new Blob([
424
+ 'ok'
425
+ ]), 'first.txt');
426
+ form.append('second', new Blob([
427
+ 'sample'
428
+ ]), 'second.txt');
429
+ await expect(processMultipartFormdata({
430
+ options: {
431
+ limits: {
432
+ fileSize: 3
433
+ },
434
+ tempFileDir: directory,
435
+ useTempFiles: true
436
+ },
437
+ request: requestFor(form)
438
+ })).rejects.toMatchObject({
439
+ status: 413
440
+ });
441
+ expect(await readdir(directory)).toEqual([]);
442
+ } finally{
443
+ await rm(directory, {
444
+ recursive: true,
445
+ force: true
446
+ });
447
+ }
448
+ });
449
+ it('should flush ordinary temporary files before returning', async ()=>{
450
+ const directory = await mkdtemp(path.join(tmpdir(), 'multipart-'));
451
+ try {
452
+ const result = await processMultipartFormdata({
453
+ options: {
454
+ tempFileDir: directory,
455
+ useTempFiles: true
456
+ },
457
+ request: requestFor(fileForm(100_000))
458
+ });
459
+ expect((await readFile(result.files.file.tempFilePath)).length).toBe(100_000);
460
+ expect(result.files.file.data.length).toBe(0);
461
+ } finally{
462
+ await rm(directory, {
463
+ recursive: true,
464
+ force: true
465
+ });
466
+ }
467
+ });
468
+ it('should reject incomplete multipart data without waiting for upload timers', async ()=>{
469
+ const request = new Request('http://localhost/api/media', {
470
+ body: '--sample\r\nContent-Disposition: form-data; name="file"; filename="sample.txt"\r\n\r\nsample',
471
+ method: 'POST',
472
+ headers: {
473
+ 'content-type': 'multipart/form-data; boundary=sample'
474
+ }
475
+ });
476
+ await expect(processMultipartFormdata({
477
+ request
478
+ })).rejects.toThrow();
479
+ }, 1000);
480
+ });
481
+ describe('multipart completion', ()=>{
482
+ it('should finish an empty temporary file part', async ()=>{
483
+ const directory = await mkdtemp(path.join(tmpdir(), 'multipart-'));
484
+ try {
485
+ const request = new Request('http://localhost/api/media', {
486
+ body: '--sample\r\nContent-Disposition: form-data; name="file"; filename=""\r\nContent-Type: application/octet-stream\r\n\r\n\r\n--sample--\r\n',
487
+ method: 'POST',
488
+ headers: {
489
+ 'content-type': 'multipart/form-data; boundary=sample'
490
+ }
491
+ });
492
+ const result = await processMultipartFormdata({
493
+ options: {
494
+ tempFileDir: directory,
495
+ useTempFiles: true
496
+ },
497
+ request
498
+ });
499
+ expect(result.files).toBeUndefined();
500
+ expect(await readdir(directory)).toEqual([]);
501
+ } finally{
502
+ await rm(directory, {
503
+ recursive: true,
504
+ force: true
505
+ });
506
+ }
507
+ }, 1000);
508
+ it('should cancel a stalled upload on timeout', async ()=>{
509
+ let cancelled = false;
510
+ const body = new ReadableStream({
511
+ start (controller) {
512
+ controller.enqueue(Buffer.from('--sample\r\nContent-Disposition: form-data; name="file"; filename="sample.txt"\r\nContent-Type: text/plain\r\n\r\nsample'));
513
+ },
514
+ cancel () {
515
+ cancelled = true;
516
+ }
517
+ });
518
+ const request = new Request('http://localhost/api/media', {
519
+ body,
520
+ duplex: 'half',
521
+ method: 'POST',
522
+ headers: {
523
+ 'content-type': 'multipart/form-data; boundary=sample'
524
+ }
525
+ });
526
+ await expect(processMultipartFormdata({
527
+ options: {
528
+ uploadTimeout: 10
529
+ },
530
+ request
531
+ })).rejects.toThrow('Upload timeout');
532
+ expect(cancelled).toBe(true);
533
+ }, 1000);
534
+ it('should preserve defaults for undefined limit values', async ()=>{
535
+ await expect(processMultipartFormdata({
536
+ options: {
537
+ abortOnLimit: undefined,
538
+ limits: {
539
+ fileSize: undefined
540
+ }
541
+ },
542
+ request: requestFor(fileForm(20 * 1024 * 1024 + 1))
543
+ }).then(()=>'accepted')).rejects.toMatchObject({
544
+ status: 413
545
+ });
546
+ });
547
+ });
548
+ it('should wait for temporary file backpressure before reading more body chunks', async ()=>{
549
+ const directory = await mkdtemp(path.join(tmpdir(), 'multipart-'));
550
+ const createWriteStream = fs.createWriteStream;
551
+ let releaseWrite;
552
+ let startedWrite;
553
+ const gate = new Promise((resolve)=>{
554
+ releaseWrite = resolve;
555
+ });
556
+ const started = new Promise((resolve)=>{
557
+ startedWrite = resolve;
558
+ });
559
+ const spy = vi.spyOn(fs, 'createWriteStream').mockImplementation((filePath)=>{
560
+ const stream = createWriteStream(filePath, {
561
+ highWaterMark: 1
562
+ });
563
+ const write = stream._write.bind(stream);
564
+ stream._write = (chunk, encoding, callback)=>{
565
+ startedWrite();
566
+ void gate.then(()=>write(chunk, encoding, callback));
567
+ };
568
+ const writev = stream._writev.bind(stream);
569
+ stream._writev = (chunks, callback)=>{
570
+ startedWrite();
571
+ void gate.then(()=>writev(chunks, callback));
572
+ };
573
+ return stream;
574
+ });
575
+ let pulls = 0;
576
+ const body = new ReadableStream({
577
+ pull (controller) {
578
+ pulls++;
579
+ if (pulls === 1) controller.enqueue(Buffer.from('--sample\r\nContent-Disposition: form-data; name="file"; filename="sample.bin"\r\nContent-Type: application/octet-stream\r\n\r\n'));
580
+ else if (pulls <= 17) controller.enqueue(Buffer.alloc(64 * 1024));
581
+ else {
582
+ controller.enqueue(Buffer.from('\r\n--sample--\r\n'));
583
+ controller.close();
584
+ }
585
+ }
586
+ });
587
+ const request = new Request('http://localhost/api/media', {
588
+ body,
589
+ duplex: 'half',
590
+ method: 'POST',
591
+ headers: {
592
+ 'content-type': 'multipart/form-data; boundary=sample'
593
+ }
594
+ });
595
+ const parsing = processMultipartFormdata({
596
+ options: {
597
+ tempFileDir: directory,
598
+ useTempFiles: true
599
+ },
600
+ request
601
+ });
602
+ try {
603
+ await started;
604
+ await new Promise((resolve)=>setImmediate(resolve));
605
+ expect(pulls).toBeLessThanOrEqual(4);
606
+ } finally{
607
+ releaseWrite();
608
+ try {
609
+ const result = await parsing;
610
+ expect((await readFile(result.files.file.tempFilePath)).length).toBe(1024 * 1024);
611
+ } finally{
612
+ spy.mockRestore();
613
+ await rm(directory, {
614
+ recursive: true,
615
+ force: true
616
+ });
617
+ }
618
+ }
619
+ });
620
+ it('should reject temporary file write errors and release the request', async ()=>{
621
+ const directory = await mkdtemp(path.join(tmpdir(), 'multipart-'));
622
+ try {
623
+ const destination = path.join(directory, 'sample.txt');
624
+ await writeFile(destination, 'sample');
625
+ const request = requestFor(fileForm(100_000));
626
+ await expect(processMultipartFormdata({
627
+ options: {
628
+ tempFileDir: destination,
629
+ useTempFiles: true
630
+ },
631
+ request
632
+ })).rejects.toMatchObject({
633
+ code: 'ENOTDIR'
634
+ });
635
+ expect(request.body.locked).toBe(false);
636
+ } finally{
637
+ await rm(directory, {
638
+ recursive: true,
639
+ force: true
640
+ });
641
+ }
642
+ }, 1000);
643
+ it('should propagate body read errors without leaving the reader locked', async ()=>{
644
+ const body = new ReadableStream({
645
+ start (controller) {
646
+ controller.error(new Error('Read failed'));
647
+ }
648
+ });
649
+ const request = new Request('http://localhost/api/media', {
650
+ body,
651
+ duplex: 'half',
652
+ method: 'POST',
653
+ headers: {
654
+ 'content-type': 'multipart/form-data; boundary=sample'
655
+ }
656
+ });
657
+ await expect(processMultipartFormdata({
658
+ request
659
+ })).rejects.toThrow('Read failed');
660
+ expect(body.locked).toBe(false);
661
+ });
662
+
663
+ //# sourceMappingURL=processMultipart.spec.js.map