@depup/payload 3.82.1-depup.0 → 3.86.0-depup.5

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 (196) hide show
  1. package/README.md +15 -13
  2. package/bin.js +11 -0
  3. package/changes.json +25 -17
  4. package/dist/admin/fields/Row.d.ts +2 -2
  5. package/dist/admin/fields/Row.d.ts.map +1 -1
  6. package/dist/admin/fields/Row.js.map +1 -1
  7. package/dist/admin/forms/Field.d.ts +1 -3
  8. package/dist/admin/forms/Field.d.ts.map +1 -1
  9. package/dist/admin/forms/Field.js.map +1 -1
  10. package/dist/admin/views/index.d.ts +5 -1
  11. package/dist/admin/views/index.d.ts.map +1 -1
  12. package/dist/admin/views/index.js.map +1 -1
  13. package/dist/bin/generateImportMap/index.d.ts.map +1 -1
  14. package/dist/bin/generateImportMap/index.js +1 -0
  15. package/dist/bin/generateImportMap/index.js.map +1 -1
  16. package/dist/bin/generateImportMap/iterateCollections.d.ts.map +1 -1
  17. package/dist/bin/generateImportMap/iterateCollections.js +11 -0
  18. package/dist/bin/generateImportMap/iterateCollections.js.map +1 -1
  19. package/dist/bin/index.d.ts.map +1 -1
  20. package/dist/bin/index.js +3 -1
  21. package/dist/bin/index.js.map +1 -1
  22. package/dist/collections/config/sanitize.d.ts +5 -0
  23. package/dist/collections/config/sanitize.d.ts.map +1 -1
  24. package/dist/collections/config/sanitize.js +21 -0
  25. package/dist/collections/config/sanitize.js.map +1 -1
  26. package/dist/collections/config/sanitize.spec.js +120 -0
  27. package/dist/collections/config/sanitize.spec.js.map +1 -0
  28. package/dist/collections/config/types.d.ts +24 -1
  29. package/dist/collections/config/types.d.ts.map +1 -1
  30. package/dist/collections/config/types.js.map +1 -1
  31. package/dist/collections/operations/create.d.ts.map +1 -1
  32. package/dist/collections/operations/create.js +1 -0
  33. package/dist/collections/operations/create.js.map +1 -1
  34. package/dist/collections/operations/delete.d.ts.map +1 -1
  35. package/dist/collections/operations/delete.js +3 -0
  36. package/dist/collections/operations/delete.js.map +1 -1
  37. package/dist/collections/operations/restoreVersion.d.ts.map +1 -1
  38. package/dist/collections/operations/restoreVersion.js +1 -0
  39. package/dist/collections/operations/restoreVersion.js.map +1 -1
  40. package/dist/collections/operations/update.d.ts.map +1 -1
  41. package/dist/collections/operations/update.js +7 -2
  42. package/dist/collections/operations/update.js.map +1 -1
  43. package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.d.ts +9 -0
  44. package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.d.ts.map +1 -0
  45. package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.js +170 -0
  46. package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.js.map +1 -0
  47. package/dist/collections/operations/utilities/update.d.ts.map +1 -1
  48. package/dist/collections/operations/utilities/update.js +16 -8
  49. package/dist/collections/operations/utilities/update.js.map +1 -1
  50. package/dist/config/build.js +5 -4
  51. package/dist/config/build.js.map +1 -1
  52. package/dist/config/definePlugin.d.ts +41 -0
  53. package/dist/config/definePlugin.d.ts.map +1 -0
  54. package/dist/config/definePlugin.js +34 -0
  55. package/dist/config/definePlugin.js.map +1 -0
  56. package/dist/config/orderable/index.d.ts.map +1 -1
  57. package/dist/config/orderable/index.js +23 -0
  58. package/dist/config/orderable/index.js.map +1 -1
  59. package/dist/config/types.d.ts +30 -2
  60. package/dist/config/types.d.ts.map +1 -1
  61. package/dist/config/types.js.map +1 -1
  62. package/dist/email/normalizeSendEmailOptions.d.ts +13 -0
  63. package/dist/email/normalizeSendEmailOptions.d.ts.map +1 -0
  64. package/dist/email/normalizeSendEmailOptions.js +20 -0
  65. package/dist/email/normalizeSendEmailOptions.js.map +1 -0
  66. package/dist/email/types.d.ts +7 -2
  67. package/dist/email/types.d.ts.map +1 -1
  68. package/dist/email/types.js.map +1 -1
  69. package/dist/errors/APIError.d.ts +2 -1
  70. package/dist/errors/APIError.d.ts.map +1 -1
  71. package/dist/errors/APIError.js +1 -3
  72. package/dist/errors/APIError.js.map +1 -1
  73. package/dist/errors/ValidationError.d.ts +3 -1
  74. package/dist/errors/ValidationError.d.ts.map +1 -1
  75. package/dist/errors/ValidationError.js +1 -3
  76. package/dist/errors/ValidationError.js.map +1 -1
  77. package/dist/fields/config/sanitize.d.ts.map +1 -1
  78. package/dist/fields/config/sanitize.js +3 -0
  79. package/dist/fields/config/sanitize.js.map +1 -1
  80. package/dist/fields/config/sanitize.spec.js +66 -0
  81. package/dist/fields/config/sanitize.spec.js.map +1 -1
  82. package/dist/fields/config/types.d.ts +3 -2
  83. package/dist/fields/config/types.d.ts.map +1 -1
  84. package/dist/fields/config/types.js.map +1 -1
  85. package/dist/fields/hooks/beforeValidate/promise.js +2 -2
  86. package/dist/fields/hooks/beforeValidate/promise.js.map +1 -1
  87. package/dist/globals/operations/restoreVersion.d.ts.map +1 -1
  88. package/dist/globals/operations/restoreVersion.js +1 -0
  89. package/dist/globals/operations/restoreVersion.js.map +1 -1
  90. package/dist/index.bundled.d.ts +484 -115
  91. package/dist/index.d.ts +19 -1
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +16 -2
  94. package/dist/index.js.map +1 -1
  95. package/dist/queues/config/collection.d.ts.map +1 -1
  96. package/dist/queues/config/collection.js +0 -1
  97. package/dist/queues/config/collection.js.map +1 -1
  98. package/dist/queues/endpoints/run.d.ts.map +1 -1
  99. package/dist/queues/endpoints/run.js +0 -3
  100. package/dist/queues/endpoints/run.js.map +1 -1
  101. package/dist/queues/errors/calculateBackoffWaitUntil.d.ts.map +1 -1
  102. package/dist/queues/errors/calculateBackoffWaitUntil.js +5 -13
  103. package/dist/queues/errors/calculateBackoffWaitUntil.js.map +1 -1
  104. package/dist/queues/errors/handleWorkflowError.d.ts.map +1 -1
  105. package/dist/queues/errors/handleWorkflowError.js +9 -1
  106. package/dist/queues/errors/handleWorkflowError.js.map +1 -1
  107. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.d.ts.map +1 -1
  108. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.js +2 -1
  109. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.js.map +1 -1
  110. package/dist/queues/operations/handleSchedules/defaultAfterSchedule.js +1 -1
  111. package/dist/queues/operations/handleSchedules/defaultAfterSchedule.js.map +1 -1
  112. package/dist/queues/operations/handleSchedules/index.d.ts.map +1 -1
  113. package/dist/queues/operations/handleSchedules/index.js +4 -1
  114. package/dist/queues/operations/handleSchedules/index.js.map +1 -1
  115. package/dist/queues/operations/runJobs/index.d.ts.map +1 -1
  116. package/dist/queues/operations/runJobs/index.js +44 -26
  117. package/dist/queues/operations/runJobs/index.js.map +1 -1
  118. package/dist/queues/operations/runJobs/runJSONJob/index.d.ts.map +1 -1
  119. package/dist/queues/operations/runJobs/runJSONJob/index.js +1 -0
  120. package/dist/queues/operations/runJobs/runJSONJob/index.js.map +1 -1
  121. package/dist/queues/utilities/updateJob.d.ts.map +1 -1
  122. package/dist/queues/utilities/updateJob.js +2 -1
  123. package/dist/queues/utilities/updateJob.js.map +1 -1
  124. package/dist/types/index.d.ts +4 -6
  125. package/dist/types/index.d.ts.map +1 -1
  126. package/dist/types/index.js.map +1 -1
  127. package/dist/uploads/checkFileAccess.d.ts.map +1 -1
  128. package/dist/uploads/checkFileAccess.js +30 -9
  129. package/dist/uploads/checkFileAccess.js.map +1 -1
  130. package/dist/uploads/checkFileRestrictions.d.ts.map +1 -1
  131. package/dist/uploads/checkFileRestrictions.js +48 -8
  132. package/dist/uploads/checkFileRestrictions.js.map +1 -1
  133. package/dist/uploads/fetchAPI-multipart/isEligibleRequest.d.ts.map +1 -1
  134. package/dist/uploads/fetchAPI-multipart/isEligibleRequest.js +2 -1
  135. package/dist/uploads/fetchAPI-multipart/isEligibleRequest.js.map +1 -1
  136. package/dist/uploads/fetchAPI-multipart/isEligibleRequest.spec.js +29 -0
  137. package/dist/uploads/fetchAPI-multipart/isEligibleRequest.spec.js.map +1 -0
  138. package/dist/uploads/fetchAPI-multipart/processMultipart.d.ts.map +1 -1
  139. package/dist/uploads/fetchAPI-multipart/processMultipart.js +11 -2
  140. package/dist/uploads/fetchAPI-multipart/processMultipart.js.map +1 -1
  141. package/dist/uploads/generateFileData.d.ts +2 -1
  142. package/dist/uploads/generateFileData.d.ts.map +1 -1
  143. package/dist/uploads/generateFileData.js +5 -2
  144. package/dist/uploads/generateFileData.js.map +1 -1
  145. package/dist/uploads/getSafeFilename.d.ts +9 -4
  146. package/dist/uploads/getSafeFilename.d.ts.map +1 -1
  147. package/dist/uploads/getSafeFilename.js +5 -5
  148. package/dist/uploads/getSafeFilename.js.map +1 -1
  149. package/dist/uploads/types.d.ts +4 -0
  150. package/dist/uploads/types.d.ts.map +1 -1
  151. package/dist/uploads/types.js.map +1 -1
  152. package/dist/utilities/addDataAndFileToRequest.d.ts.map +1 -1
  153. package/dist/utilities/addDataAndFileToRequest.js +16 -3
  154. package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
  155. package/dist/utilities/addDataAndFileToRequest.spec.js +41 -0
  156. package/dist/utilities/addDataAndFileToRequest.spec.js.map +1 -0
  157. package/dist/utilities/createPayloadRequest.d.ts.map +1 -1
  158. package/dist/utilities/createPayloadRequest.js +1 -0
  159. package/dist/utilities/createPayloadRequest.js.map +1 -1
  160. package/dist/utilities/filterDataToSelectedLocales.d.ts.map +1 -1
  161. package/dist/utilities/filterDataToSelectedLocales.js +74 -31
  162. package/dist/utilities/filterDataToSelectedLocales.js.map +1 -1
  163. package/dist/utilities/filterDataToSelectedLocales.spec.js +337 -0
  164. package/dist/utilities/filterDataToSelectedLocales.spec.js.map +1 -1
  165. package/dist/utilities/formatErrors.d.ts +1 -1
  166. package/dist/utilities/formatErrors.d.ts.map +1 -1
  167. package/dist/utilities/formatErrors.js +4 -7
  168. package/dist/utilities/formatErrors.js.map +1 -1
  169. package/dist/utilities/formatErrors.spec.js +101 -0
  170. package/dist/utilities/formatErrors.spec.js.map +1 -0
  171. package/dist/utilities/isURLAllowed.d.ts.map +1 -1
  172. package/dist/utilities/isURLAllowed.js +9 -3
  173. package/dist/utilities/isURLAllowed.js.map +1 -1
  174. package/dist/utilities/isURLAllowed.spec.js +78 -0
  175. package/dist/utilities/isURLAllowed.spec.js.map +1 -0
  176. package/dist/utilities/parseParams/index.d.ts +1 -1
  177. package/dist/utilities/parseParams/index.d.ts.map +1 -1
  178. package/dist/utilities/parseParams/index.js +3 -0
  179. package/dist/utilities/parseParams/index.js.map +1 -1
  180. package/dist/utilities/parseParams/index.spec.js +24 -0
  181. package/dist/utilities/parseParams/index.spec.js.map +1 -1
  182. package/dist/utilities/profiling.d.ts +12 -0
  183. package/dist/utilities/profiling.d.ts.map +1 -0
  184. package/dist/utilities/profiling.js +56 -0
  185. package/dist/utilities/profiling.js.map +1 -0
  186. package/dist/utilities/profiling.spec.js +53 -0
  187. package/dist/utilities/profiling.spec.js.map +1 -0
  188. package/dist/versions/saveVersion.js +1 -1
  189. package/dist/versions/saveVersion.js.map +1 -1
  190. package/dist/versions/schedule/job.d.ts.map +1 -1
  191. package/dist/versions/schedule/job.js +4 -1
  192. package/dist/versions/schedule/job.js.map +1 -1
  193. package/dist/versions/updateLatestVersion.d.ts.map +1 -1
  194. package/dist/versions/updateLatestVersion.js +55 -8
  195. package/dist/versions/updateLatestVersion.js.map +1 -1
  196. package/package.json +42 -35
@@ -1 +1 @@
1
- {"version":3,"file":"updateJob.d.ts","sourceRoot":"","sources":["../../../src/queues/utilities/updateJob.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAIvE,KAAK,QAAQ,GAAG;IACd,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,cAAc,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,KAAK,QAAQ,GAAG;IACd,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED,KAAK,SAAS,GAAG;IACf,EAAE,CAAC,EAAE,KAAK,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,KAAK,WAAW,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC,GAAG,QAAQ,CAAA;AAEpD;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,4BAKxD;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,EAC/B,EAAE,EACF,IAAI,EACJ,KAAK,EACL,kBAAkB,EAClB,KAAK,EAAE,QAAQ,EACf,GAAG,EACH,SAAS,EACT,IAAI,EACJ,KAAK,EAAE,QAAQ,GAChB,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAiErC"}
1
+ {"version":3,"file":"updateJob.d.ts","sourceRoot":"","sources":["../../../src/queues/utilities/updateJob.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAKvE,KAAK,QAAQ,GAAG;IACd,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,cAAc,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,KAAK,QAAQ,GAAG;IACd,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED,KAAK,SAAS,GAAG;IACf,EAAE,CAAC,EAAE,KAAK,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,KAAK,WAAW,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC,GAAG,QAAQ,CAAA;AAEpD;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,4BAKxD;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,EAC/B,EAAE,EACF,IAAI,EACJ,KAAK,EACL,kBAAkB,EAClB,KAAK,EAAE,QAAQ,EACf,GAAG,EACH,SAAS,EACT,IAAI,EACJ,KAAK,EAAE,QAAQ,GAChB,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAiErC"}
@@ -1,4 +1,5 @@
1
1
  import { jobAfterRead, jobsCollectionSlug } from '../config/collection.js';
2
+ import { getCurrentDate } from './getCurrentDate.js';
2
3
  /**
3
4
  * Convenience method for updateJobs by id
4
5
  */ export async function updateJob(args) {
@@ -39,7 +40,7 @@ import { jobAfterRead, jobsCollectionSlug } from '../config/collection.js';
39
40
  };
40
41
  if (typeof data.updatedAt === 'undefined') {
41
42
  // Ensure updatedAt date is always updated
42
- data.updatedAt = new Date().toISOString();
43
+ data.updatedAt = getCurrentDate().toISOString();
43
44
  }
44
45
  const args = id ? {
45
46
  id,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/queues/utilities/updateJob.ts"],"sourcesContent":["import type { ManyOptions } from '../../collections/operations/local/update.js'\nimport type { UpdateJobsArgs } from '../../database/types.js'\nimport type { Job } from '../../index.js'\nimport type { PayloadRequest, Sort, Where } from '../../types/index.js'\n\nimport { jobAfterRead, jobsCollectionSlug } from '../config/collection.js'\n\ntype BaseArgs = {\n data: Partial<Job>\n depth?: number\n disableTransaction?: boolean\n limit?: number\n req: PayloadRequest\n returning?: boolean\n}\n\ntype ArgsByID = {\n id: number | string\n limit?: never\n sort?: never\n where?: never\n}\n\ntype ArgsWhere = {\n id?: never\n limit?: number\n sort?: Sort\n where: Where\n}\n\ntype RunJobsArgs = (ArgsByID | ArgsWhere) & BaseArgs\n\n/**\n * Convenience method for updateJobs by id\n */\nexport async function updateJob(args: ArgsByID & BaseArgs) {\n const result = await updateJobs(args)\n if (result) {\n return result[0]\n }\n}\n\n/**\n * Helper for updating jobs in the most performant way possible.\n * Handles deciding whether it can used direct db methods or not, and if so,\n * manually runs the afterRead hook that populates the `taskStatus` property.\n */\nexport async function updateJobs({\n id,\n data,\n depth,\n disableTransaction,\n limit: limitArg,\n req,\n returning,\n sort,\n where: whereArg,\n}: RunJobsArgs): Promise<Job[] | null> {\n const limit = id ? 1 : limitArg\n const where = id ? { id: { equals: id } } : whereArg\n\n if (depth || req.payload.config?.jobs?.runHooks) {\n const result = await req.payload.update({\n id,\n collection: jobsCollectionSlug,\n data,\n depth,\n disableTransaction,\n limit,\n req,\n where,\n } as ManyOptions<any, any>)\n if (returning === false || !result) {\n return null\n }\n return result.docs as Job[]\n }\n\n const jobReq = {\n transactionID:\n req.payload.db.name !== 'mongoose'\n ? ((await req.payload.db.beginTransaction()) as string)\n : undefined,\n }\n\n if (typeof data.updatedAt === 'undefined') {\n // Ensure updatedAt date is always updated\n data.updatedAt = new Date().toISOString()\n }\n\n const args: UpdateJobsArgs = id\n ? {\n id,\n data,\n req: jobReq,\n returning,\n }\n : {\n data,\n limit,\n req: jobReq,\n returning,\n sort,\n where: where as Where,\n }\n\n const updatedJobs: Job[] | null = await req.payload.db.updateJobs(args)\n\n if (req.payload.db.name !== 'mongoose' && jobReq.transactionID) {\n await req.payload.db.commitTransaction(jobReq.transactionID)\n }\n\n if (returning === false || !updatedJobs?.length) {\n return null\n }\n\n return updatedJobs.map((updatedJob) => {\n return jobAfterRead({\n config: req.payload.config,\n doc: updatedJob,\n })\n })\n}\n"],"names":["jobAfterRead","jobsCollectionSlug","updateJob","args","result","updateJobs","id","data","depth","disableTransaction","limit","limitArg","req","returning","sort","where","whereArg","equals","payload","config","jobs","runHooks","update","collection","docs","jobReq","transactionID","db","name","beginTransaction","undefined","updatedAt","Date","toISOString","updatedJobs","commitTransaction","length","map","updatedJob","doc"],"mappings":"AAKA,SAASA,YAAY,EAAEC,kBAAkB,QAAQ,0BAAyB;AA2B1E;;CAEC,GACD,OAAO,eAAeC,UAAUC,IAAyB;IACvD,MAAMC,SAAS,MAAMC,WAAWF;IAChC,IAAIC,QAAQ;QACV,OAAOA,MAAM,CAAC,EAAE;IAClB;AACF;AAEA;;;;CAIC,GACD,OAAO,eAAeC,WAAW,EAC/BC,EAAE,EACFC,IAAI,EACJC,KAAK,EACLC,kBAAkB,EAClBC,OAAOC,QAAQ,EACfC,GAAG,EACHC,SAAS,EACTC,IAAI,EACJC,OAAOC,QAAQ,EACH;IACZ,MAAMN,QAAQJ,KAAK,IAAIK;IACvB,MAAMI,QAAQT,KAAK;QAAEA,IAAI;YAAEW,QAAQX;QAAG;IAAE,IAAIU;IAE5C,IAAIR,SAASI,IAAIM,OAAO,CAACC,MAAM,EAAEC,MAAMC,UAAU;QAC/C,MAAMjB,SAAS,MAAMQ,IAAIM,OAAO,CAACI,MAAM,CAAC;YACtChB;YACAiB,YAAYtB;YACZM;YACAC;YACAC;YACAC;YACAE;YACAG;QACF;QACA,IAAIF,cAAc,SAAS,CAACT,QAAQ;YAClC,OAAO;QACT;QACA,OAAOA,OAAOoB,IAAI;IACpB;IAEA,MAAMC,SAAS;QACbC,eACEd,IAAIM,OAAO,CAACS,EAAE,CAACC,IAAI,KAAK,aAClB,MAAMhB,IAAIM,OAAO,CAACS,EAAE,CAACE,gBAAgB,KACvCC;IACR;IAEA,IAAI,OAAOvB,KAAKwB,SAAS,KAAK,aAAa;QACzC,0CAA0C;QAC1CxB,KAAKwB,SAAS,GAAG,IAAIC,OAAOC,WAAW;IACzC;IAEA,MAAM9B,OAAuBG,KACzB;QACEA;QACAC;QACAK,KAAKa;QACLZ;IACF,IACA;QACEN;QACAG;QACAE,KAAKa;QACLZ;QACAC;QACAC,OAAOA;IACT;IAEJ,MAAMmB,cAA4B,MAAMtB,IAAIM,OAAO,CAACS,EAAE,CAACtB,UAAU,CAACF;IAElE,IAAIS,IAAIM,OAAO,CAACS,EAAE,CAACC,IAAI,KAAK,cAAcH,OAAOC,aAAa,EAAE;QAC9D,MAAMd,IAAIM,OAAO,CAACS,EAAE,CAACQ,iBAAiB,CAACV,OAAOC,aAAa;IAC7D;IAEA,IAAIb,cAAc,SAAS,CAACqB,aAAaE,QAAQ;QAC/C,OAAO;IACT;IAEA,OAAOF,YAAYG,GAAG,CAAC,CAACC;QACtB,OAAOtC,aAAa;YAClBmB,QAAQP,IAAIM,OAAO,CAACC,MAAM;YAC1BoB,KAAKD;QACP;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/queues/utilities/updateJob.ts"],"sourcesContent":["import type { ManyOptions } from '../../collections/operations/local/update.js'\nimport type { UpdateJobsArgs } from '../../database/types.js'\nimport type { Job } from '../../index.js'\nimport type { PayloadRequest, Sort, Where } from '../../types/index.js'\n\nimport { jobAfterRead, jobsCollectionSlug } from '../config/collection.js'\nimport { getCurrentDate } from './getCurrentDate.js'\n\ntype BaseArgs = {\n data: Partial<Job>\n depth?: number\n disableTransaction?: boolean\n limit?: number\n req: PayloadRequest\n returning?: boolean\n}\n\ntype ArgsByID = {\n id: number | string\n limit?: never\n sort?: never\n where?: never\n}\n\ntype ArgsWhere = {\n id?: never\n limit?: number\n sort?: Sort\n where: Where\n}\n\ntype RunJobsArgs = (ArgsByID | ArgsWhere) & BaseArgs\n\n/**\n * Convenience method for updateJobs by id\n */\nexport async function updateJob(args: ArgsByID & BaseArgs) {\n const result = await updateJobs(args)\n if (result) {\n return result[0]\n }\n}\n\n/**\n * Helper for updating jobs in the most performant way possible.\n * Handles deciding whether it can used direct db methods or not, and if so,\n * manually runs the afterRead hook that populates the `taskStatus` property.\n */\nexport async function updateJobs({\n id,\n data,\n depth,\n disableTransaction,\n limit: limitArg,\n req,\n returning,\n sort,\n where: whereArg,\n}: RunJobsArgs): Promise<Job[] | null> {\n const limit = id ? 1 : limitArg\n const where = id ? { id: { equals: id } } : whereArg\n\n if (depth || req.payload.config?.jobs?.runHooks) {\n const result = await req.payload.update({\n id,\n collection: jobsCollectionSlug,\n data,\n depth,\n disableTransaction,\n limit,\n req,\n where,\n } as ManyOptions<any, any>)\n if (returning === false || !result) {\n return null\n }\n return result.docs as Job[]\n }\n\n const jobReq = {\n transactionID:\n req.payload.db.name !== 'mongoose'\n ? ((await req.payload.db.beginTransaction()) as string)\n : undefined,\n }\n\n if (typeof data.updatedAt === 'undefined') {\n // Ensure updatedAt date is always updated\n data.updatedAt = getCurrentDate().toISOString()\n }\n\n const args: UpdateJobsArgs = id\n ? {\n id,\n data,\n req: jobReq,\n returning,\n }\n : {\n data,\n limit,\n req: jobReq,\n returning,\n sort,\n where: where as Where,\n }\n\n const updatedJobs: Job[] | null = await req.payload.db.updateJobs(args)\n\n if (req.payload.db.name !== 'mongoose' && jobReq.transactionID) {\n await req.payload.db.commitTransaction(jobReq.transactionID)\n }\n\n if (returning === false || !updatedJobs?.length) {\n return null\n }\n\n return updatedJobs.map((updatedJob) => {\n return jobAfterRead({\n config: req.payload.config,\n doc: updatedJob,\n })\n })\n}\n"],"names":["jobAfterRead","jobsCollectionSlug","getCurrentDate","updateJob","args","result","updateJobs","id","data","depth","disableTransaction","limit","limitArg","req","returning","sort","where","whereArg","equals","payload","config","jobs","runHooks","update","collection","docs","jobReq","transactionID","db","name","beginTransaction","undefined","updatedAt","toISOString","updatedJobs","commitTransaction","length","map","updatedJob","doc"],"mappings":"AAKA,SAASA,YAAY,EAAEC,kBAAkB,QAAQ,0BAAyB;AAC1E,SAASC,cAAc,QAAQ,sBAAqB;AA2BpD;;CAEC,GACD,OAAO,eAAeC,UAAUC,IAAyB;IACvD,MAAMC,SAAS,MAAMC,WAAWF;IAChC,IAAIC,QAAQ;QACV,OAAOA,MAAM,CAAC,EAAE;IAClB;AACF;AAEA;;;;CAIC,GACD,OAAO,eAAeC,WAAW,EAC/BC,EAAE,EACFC,IAAI,EACJC,KAAK,EACLC,kBAAkB,EAClBC,OAAOC,QAAQ,EACfC,GAAG,EACHC,SAAS,EACTC,IAAI,EACJC,OAAOC,QAAQ,EACH;IACZ,MAAMN,QAAQJ,KAAK,IAAIK;IACvB,MAAMI,QAAQT,KAAK;QAAEA,IAAI;YAAEW,QAAQX;QAAG;IAAE,IAAIU;IAE5C,IAAIR,SAASI,IAAIM,OAAO,CAACC,MAAM,EAAEC,MAAMC,UAAU;QAC/C,MAAMjB,SAAS,MAAMQ,IAAIM,OAAO,CAACI,MAAM,CAAC;YACtChB;YACAiB,YAAYvB;YACZO;YACAC;YACAC;YACAC;YACAE;YACAG;QACF;QACA,IAAIF,cAAc,SAAS,CAACT,QAAQ;YAClC,OAAO;QACT;QACA,OAAOA,OAAOoB,IAAI;IACpB;IAEA,MAAMC,SAAS;QACbC,eACEd,IAAIM,OAAO,CAACS,EAAE,CAACC,IAAI,KAAK,aAClB,MAAMhB,IAAIM,OAAO,CAACS,EAAE,CAACE,gBAAgB,KACvCC;IACR;IAEA,IAAI,OAAOvB,KAAKwB,SAAS,KAAK,aAAa;QACzC,0CAA0C;QAC1CxB,KAAKwB,SAAS,GAAG9B,iBAAiB+B,WAAW;IAC/C;IAEA,MAAM7B,OAAuBG,KACzB;QACEA;QACAC;QACAK,KAAKa;QACLZ;IACF,IACA;QACEN;QACAG;QACAE,KAAKa;QACLZ;QACAC;QACAC,OAAOA;IACT;IAEJ,MAAMkB,cAA4B,MAAMrB,IAAIM,OAAO,CAACS,EAAE,CAACtB,UAAU,CAACF;IAElE,IAAIS,IAAIM,OAAO,CAACS,EAAE,CAACC,IAAI,KAAK,cAAcH,OAAOC,aAAa,EAAE;QAC9D,MAAMd,IAAIM,OAAO,CAACS,EAAE,CAACO,iBAAiB,CAACT,OAAOC,aAAa;IAC7D;IAEA,IAAIb,cAAc,SAAS,CAACoB,aAAaE,QAAQ;QAC/C,OAAO;IACT;IAEA,OAAOF,YAAYG,GAAG,CAAC,CAACC;QACtB,OAAOtC,aAAa;YAClBoB,QAAQP,IAAIM,OAAO,CAACC,MAAM;YAC1BmB,KAAKD;QACP;IACF;AACF"}
@@ -5,6 +5,7 @@ import type { URL } from 'url';
5
5
  import type { DataFromCollectionSlug, QueryDraftDataFromCollectionSlug, TypeWithID, TypeWithTimestamps } from '../collections/config/types.js';
6
6
  import type payload from '../index.js';
7
7
  import type { CollectionSlug, DataFromGlobalSlug, GlobalSlug, Payload, RequestContext, TypedCollectionJoins, TypedCollectionSelect, TypedFallbackLocale, TypedLocale, TypedUser } from '../index.js';
8
+ import type { File } from '../uploads/types.js';
8
9
  import type { Operator } from './constants.js';
9
10
  export type { Payload } from '../index.js';
10
11
  export type CustomPayloadRequestProperties = {
@@ -89,12 +90,9 @@ type PayloadRequestData = {
89
90
  * Context of the file when it was uploaded via client side.
90
91
  */
91
92
  clientUploadContext?: unknown;
92
- data: Buffer;
93
- mimetype: string;
94
- name: string;
95
- size: number;
96
- tempFilePath?: string;
97
- };
93
+ } & File;
94
+ /** All files from multipart form data, keyed by field name */
95
+ files?: Record<string, File | File[]>;
98
96
  };
99
97
  export interface PayloadRequest extends CustomPayloadRequestProperties, Partial<Request>, PayloadRequestData {
100
98
  headers: Request['headers'];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/index.ts"],"sourcesContent":["import type { I18n, TFunction } from '@payloadcms/translations'\nimport type DataLoader from 'dataloader'\nimport type { OptionalKeys, RequiredKeys } from 'ts-essentials'\nimport type { URL } from 'url'\n\nimport type {\n DataFromCollectionSlug,\n QueryDraftDataFromCollectionSlug,\n TypeWithID,\n TypeWithTimestamps,\n} from '../collections/config/types.js'\nimport type payload from '../index.js'\nimport type {\n CollectionSlug,\n DataFromGlobalSlug,\n GlobalSlug,\n Payload,\n RequestContext,\n TypedCollectionJoins,\n TypedCollectionSelect,\n TypedFallbackLocale,\n TypedLocale,\n TypedUser,\n} from '../index.js'\nimport type { Operator } from './constants.js'\nexport type { Payload } from '../index.js'\n\nexport type CustomPayloadRequestProperties = {\n context: RequestContext\n /** The locale that should be used for a field when it is not translated to the requested locale */\n fallbackLocale?: TypedFallbackLocale\n i18n: I18n\n /**\n * The requested locale if specified\n * Only available for localized collections\n *\n * Suppressing warning below as it is a valid use case - won't be an issue if generated types exist\n */\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n locale?: 'all' | TypedLocale\n /**\n * The payload object\n */\n payload: typeof payload\n /**\n * The context in which the request is being made\n */\n payloadAPI: 'GraphQL' | 'local' | 'REST'\n /** Optimized document loader */\n payloadDataLoader: {\n /**\n * Wraps `payload.find` with a cache to deduplicate requests\n * @experimental This is may be replaced by a more robust cache strategy in future versions\n * By calling this method with the same arguments many times in one request, it will only be handled one time\n * const result = await req.payloadDataLoader.find({\n * collection,\n * req,\n * where: findWhere,\n * })\n */\n find: Payload['find']\n } & DataLoader<string, TypeWithID>\n /** Resized versions of the image that was uploaded during this request */\n payloadUploadSizes?: Record<string, Buffer>\n /** Query params on the request */\n query: Record<string, unknown>\n /** Any response headers that are required to be set when a response is sent */\n responseHeaders?: Headers\n /** The route parameters\n * @example\n * /:collection/:id -> /posts/123\n * { collection: 'posts', id: '123' }\n */\n routeParams?: Record<string, unknown>\n /** Translate function - duplicate of i18n.t */\n t: TFunction\n /**\n * Identifier for the database transaction for interactions in a single, all-or-nothing operation.\n * Can also be used to ensure consistency when multiple operations try to create a transaction concurrently on the same request.\n */\n transactionID?: number | Promise<number | string> | string\n /**\n * Used to ensure consistency when multiple operations try to create a transaction concurrently on the same request\n * @deprecated This is not used anywhere, instead `transactionID` is used for the above. Will be removed in next major version.\n */\n transactionIDPromise?: Promise<void>\n /** The signed-in user */\n user: null | TypedUser\n} & Pick<\n URL,\n 'hash' | 'host' | 'href' | 'origin' | 'pathname' | 'port' | 'protocol' | 'search' | 'searchParams'\n>\ntype PayloadRequestData = {\n /**\n * Data from the request body\n *\n * Within Payload operations, i.e. hooks, data will be there\n * BUT in custom endpoints it will not be, you will need to\n * use either:\n * 1. `const data = await req.json()`\n *\n * 2. import { addDataAndFileToRequest } from 'payload'\n * `await addDataAndFileToRequest(req)`\n *\n * You should not expect this object to be the document data. It is the request data.\n * */\n data?: JsonObject\n /** The file on the request, same rules apply as the `data` property */\n file?: {\n /**\n * Context of the file when it was uploaded via client side.\n */\n clientUploadContext?: unknown\n data: Buffer\n mimetype: string\n name: string\n size: number\n tempFilePath?: string\n }\n}\nexport interface PayloadRequest\n extends CustomPayloadRequestProperties,\n Partial<Request>,\n PayloadRequestData {\n headers: Request['headers']\n}\n\nexport type { Operator }\n\n// Makes it so things like passing new Date() will error\nexport type JsonValue = JsonArray | JsonObject | unknown //Date | JsonArray | JsonObject | boolean | null | number | string // TODO: Evaluate proper, strong type for this\n\nexport type JsonArray = Array<JsonValue>\n\nexport interface JsonObject {\n [key: string]: any\n}\n\nexport type WhereField = {\n // any json-serializable value\n [key in Operator]?: JsonValue\n}\n\nexport type Where = {\n [key: string]: Where[] | WhereField\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n and?: Where[]\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n or?: Where[]\n}\n\nexport type Sort = Array<string> | string\n\ntype SerializableValue = boolean | number | object | string\nexport type DefaultValue =\n | ((args: {\n locale?: TypedLocale\n req: PayloadRequest\n user: PayloadRequest['user']\n }) => SerializableValue)\n | SerializableValue\n\n/**\n * Applies pagination for join fields for including collection relationships\n */\nexport type JoinQuery<TSlug extends CollectionSlug = string> =\n TypedCollectionJoins[TSlug] extends Record<string, string>\n ?\n | false\n | Partial<{\n [K in keyof TypedCollectionJoins[TSlug]]:\n | {\n count?: boolean\n limit?: number\n page?: number\n sort?: string\n where?: Where\n }\n | false\n }>\n : never\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Document = any\n\nexport type Operation = 'create' | 'delete' | 'read' | 'update'\nexport type VersionOperations = 'readVersions'\nexport type AuthOperations = 'unlock'\nexport type AllOperations = AuthOperations | Operation | VersionOperations\n\nexport function docHasTimestamps(doc: any): doc is TypeWithTimestamps {\n return doc?.createdAt && doc?.updatedAt\n}\n\nexport type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N // This is a commonly used trick to detect 'any'\nexport type IsAny<T> = IfAny<T, true, false>\nexport type ReplaceAny<T, DefaultType> = IsAny<T> extends true ? DefaultType : T\n\nexport type SelectIncludeType = {\n [k: string]: SelectIncludeType | true\n}\n\nexport type SelectExcludeType = {\n [k: string]: false | SelectExcludeType\n}\n\nexport type SelectMode = 'exclude' | 'include'\n\nexport type SelectType = SelectExcludeType | SelectIncludeType\n\nexport type ApplyDisableErrors<T, DisableErrors = false> = false extends DisableErrors\n ? T\n : null | T\n\nexport type TransformDataWithSelect<\n Data extends Record<string, any>,\n Select extends SelectType,\n> = Select extends never\n ? Data\n : string extends keyof Select\n ? Data\n : // START Handle types when they aren't generated\n // For example in any package in this repository outside of tests / plugins\n // This stil gives us autocomplete when using include select mode, i.e select: {title :true} returns type {title: any, id: string | number}\n string extends keyof Omit<Data, 'id'>\n ? Select extends SelectIncludeType\n ? {\n [K in Data extends TypeWithID ? 'id' | keyof Select : keyof Select]: K extends 'id'\n ? number | string\n : unknown\n }\n : Data\n : // END Handle types when they aren't generated\n // Handle include mode\n Select extends SelectIncludeType\n ? {\n [K in keyof Data as K extends keyof Select\n ? Select[K] extends object | true\n ? K\n : never\n : // select 'id' always\n K extends 'id'\n ? K\n : never]: Data[K]\n }\n : // Handle exclude mode\n {\n [K in keyof Data as K extends keyof Select\n ? Select[K] extends object | undefined\n ? K\n : never\n : K]: Data[K]\n }\n\nexport type TransformCollectionWithSelect<\n TSlug extends CollectionSlug,\n TSelect extends SelectType,\n> = TSelect extends SelectType\n ? TransformDataWithSelect<DataFromCollectionSlug<TSlug>, TSelect>\n : DataFromCollectionSlug<TSlug>\n\nexport type DraftTransformCollectionWithSelect<\n TSlug extends CollectionSlug,\n TSelect extends SelectType,\n> = TSelect extends SelectType\n ? TransformDataWithSelect<QueryDraftDataFromCollectionSlug<TSlug>, TSelect>\n : QueryDraftDataFromCollectionSlug<TSlug>\n\nexport type TransformGlobalWithSelect<\n TSlug extends GlobalSlug,\n TSelect extends SelectType,\n> = TSelect extends SelectType\n ? TransformDataWithSelect<DataFromGlobalSlug<TSlug>, TSelect>\n : DataFromGlobalSlug<TSlug>\n\nexport type PopulateType = Partial<TypedCollectionSelect>\n\nexport type ResolvedFilterOptions = { [collection: string]: Where }\n\nexport type PickPreserveOptional<T, K extends keyof T> = Partial<\n Pick<T, Extract<K, OptionalKeys<T>>>\n> &\n Pick<T, Extract<K, RequiredKeys<T>>>\n\nexport type MaybePromise<T> = Promise<T> | T\n"],"names":["docHasTimestamps","doc","createdAt","updatedAt"],"mappings":"AA8LA,OAAO,SAASA,iBAAiBC,GAAQ;IACvC,OAAOA,KAAKC,aAAaD,KAAKE;AAChC"}
1
+ {"version":3,"sources":["../../src/types/index.ts"],"sourcesContent":["import type { I18n, TFunction } from '@payloadcms/translations'\nimport type DataLoader from 'dataloader'\nimport type { OptionalKeys, RequiredKeys } from 'ts-essentials'\nimport type { URL } from 'url'\n\nimport type {\n DataFromCollectionSlug,\n QueryDraftDataFromCollectionSlug,\n TypeWithID,\n TypeWithTimestamps,\n} from '../collections/config/types.js'\nimport type payload from '../index.js'\nimport type {\n CollectionSlug,\n DataFromGlobalSlug,\n GlobalSlug,\n Payload,\n RequestContext,\n TypedCollectionJoins,\n TypedCollectionSelect,\n TypedFallbackLocale,\n TypedLocale,\n TypedUser,\n} from '../index.js'\nimport type { File } from '../uploads/types.js'\nimport type { Operator } from './constants.js'\nexport type { Payload } from '../index.js'\n\nexport type CustomPayloadRequestProperties = {\n context: RequestContext\n /** The locale that should be used for a field when it is not translated to the requested locale */\n fallbackLocale?: TypedFallbackLocale\n i18n: I18n\n /**\n * The requested locale if specified\n * Only available for localized collections\n *\n * Suppressing warning below as it is a valid use case - won't be an issue if generated types exist\n */\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n locale?: 'all' | TypedLocale\n /**\n * The payload object\n */\n payload: typeof payload\n /**\n * The context in which the request is being made\n */\n payloadAPI: 'GraphQL' | 'local' | 'REST'\n /** Optimized document loader */\n payloadDataLoader: {\n /**\n * Wraps `payload.find` with a cache to deduplicate requests\n * @experimental This is may be replaced by a more robust cache strategy in future versions\n * By calling this method with the same arguments many times in one request, it will only be handled one time\n * const result = await req.payloadDataLoader.find({\n * collection,\n * req,\n * where: findWhere,\n * })\n */\n find: Payload['find']\n } & DataLoader<string, TypeWithID>\n /** Resized versions of the image that was uploaded during this request */\n payloadUploadSizes?: Record<string, Buffer>\n /** Query params on the request */\n query: Record<string, unknown>\n /** Any response headers that are required to be set when a response is sent */\n responseHeaders?: Headers\n /** The route parameters\n * @example\n * /:collection/:id -> /posts/123\n * { collection: 'posts', id: '123' }\n */\n routeParams?: Record<string, unknown>\n /** Translate function - duplicate of i18n.t */\n t: TFunction\n /**\n * Identifier for the database transaction for interactions in a single, all-or-nothing operation.\n * Can also be used to ensure consistency when multiple operations try to create a transaction concurrently on the same request.\n */\n transactionID?: number | Promise<number | string> | string\n /**\n * Used to ensure consistency when multiple operations try to create a transaction concurrently on the same request\n * @deprecated This is not used anywhere, instead `transactionID` is used for the above. Will be removed in next major version.\n */\n transactionIDPromise?: Promise<void>\n /** The signed-in user */\n user: null | TypedUser\n} & Pick<\n URL,\n 'hash' | 'host' | 'href' | 'origin' | 'pathname' | 'port' | 'protocol' | 'search' | 'searchParams'\n>\ntype PayloadRequestData = {\n /**\n * Data from the request body\n *\n * Within Payload operations, i.e. hooks, data will be there\n * BUT in custom endpoints it will not be, you will need to\n * use either:\n * 1. `const data = await req.json()`\n *\n * 2. import { addDataAndFileToRequest } from 'payload'\n * `await addDataAndFileToRequest(req)`\n *\n * You should not expect this object to be the document data. It is the request data.\n * */\n data?: JsonObject\n /** The file on the request, same rules apply as the `data` property */\n file?: {\n /**\n * Context of the file when it was uploaded via client side.\n */\n clientUploadContext?: unknown\n } & File\n /** All files from multipart form data, keyed by field name */\n files?: Record<string, File | File[]>\n}\nexport interface PayloadRequest\n extends CustomPayloadRequestProperties,\n Partial<Request>,\n PayloadRequestData {\n headers: Request['headers']\n}\n\nexport type { Operator }\n\n// Makes it so things like passing new Date() will error\nexport type JsonValue = JsonArray | JsonObject | unknown //Date | JsonArray | JsonObject | boolean | null | number | string // TODO: Evaluate proper, strong type for this\n\nexport type JsonArray = Array<JsonValue>\n\nexport interface JsonObject {\n [key: string]: any\n}\n\nexport type WhereField = {\n // any json-serializable value\n [key in Operator]?: JsonValue\n}\n\nexport type Where = {\n [key: string]: Where[] | WhereField\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n and?: Where[]\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n or?: Where[]\n}\n\nexport type Sort = Array<string> | string\n\ntype SerializableValue = boolean | number | object | string\nexport type DefaultValue =\n | ((args: {\n locale?: TypedLocale\n req: PayloadRequest\n user: PayloadRequest['user']\n }) => SerializableValue)\n | SerializableValue\n\n/**\n * Applies pagination for join fields for including collection relationships\n */\nexport type JoinQuery<TSlug extends CollectionSlug = string> =\n TypedCollectionJoins[TSlug] extends Record<string, string>\n ?\n | false\n | Partial<{\n [K in keyof TypedCollectionJoins[TSlug]]:\n | {\n count?: boolean\n limit?: number\n page?: number\n sort?: string\n where?: Where\n }\n | false\n }>\n : never\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Document = any\n\nexport type Operation = 'create' | 'delete' | 'read' | 'update'\nexport type VersionOperations = 'readVersions'\nexport type AuthOperations = 'unlock'\nexport type AllOperations = AuthOperations | Operation | VersionOperations\n\nexport function docHasTimestamps(doc: any): doc is TypeWithTimestamps {\n return doc?.createdAt && doc?.updatedAt\n}\n\nexport type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N // This is a commonly used trick to detect 'any'\nexport type IsAny<T> = IfAny<T, true, false>\nexport type ReplaceAny<T, DefaultType> = IsAny<T> extends true ? DefaultType : T\n\nexport type SelectIncludeType = {\n [k: string]: SelectIncludeType | true\n}\n\nexport type SelectExcludeType = {\n [k: string]: false | SelectExcludeType\n}\n\nexport type SelectMode = 'exclude' | 'include'\n\nexport type SelectType = SelectExcludeType | SelectIncludeType\n\nexport type ApplyDisableErrors<T, DisableErrors = false> = false extends DisableErrors\n ? T\n : null | T\n\nexport type TransformDataWithSelect<\n Data extends Record<string, any>,\n Select extends SelectType,\n> = Select extends never\n ? Data\n : string extends keyof Select\n ? Data\n : // START Handle types when they aren't generated\n // For example in any package in this repository outside of tests / plugins\n // This stil gives us autocomplete when using include select mode, i.e select: {title :true} returns type {title: any, id: string | number}\n string extends keyof Omit<Data, 'id'>\n ? Select extends SelectIncludeType\n ? {\n [K in Data extends TypeWithID ? 'id' | keyof Select : keyof Select]: K extends 'id'\n ? number | string\n : unknown\n }\n : Data\n : // END Handle types when they aren't generated\n // Handle include mode\n Select extends SelectIncludeType\n ? {\n [K in keyof Data as K extends keyof Select\n ? Select[K] extends object | true\n ? K\n : never\n : // select 'id' always\n K extends 'id'\n ? K\n : never]: Data[K]\n }\n : // Handle exclude mode\n {\n [K in keyof Data as K extends keyof Select\n ? Select[K] extends object | undefined\n ? K\n : never\n : K]: Data[K]\n }\n\nexport type TransformCollectionWithSelect<\n TSlug extends CollectionSlug,\n TSelect extends SelectType,\n> = TSelect extends SelectType\n ? TransformDataWithSelect<DataFromCollectionSlug<TSlug>, TSelect>\n : DataFromCollectionSlug<TSlug>\n\nexport type DraftTransformCollectionWithSelect<\n TSlug extends CollectionSlug,\n TSelect extends SelectType,\n> = TSelect extends SelectType\n ? TransformDataWithSelect<QueryDraftDataFromCollectionSlug<TSlug>, TSelect>\n : QueryDraftDataFromCollectionSlug<TSlug>\n\nexport type TransformGlobalWithSelect<\n TSlug extends GlobalSlug,\n TSelect extends SelectType,\n> = TSelect extends SelectType\n ? TransformDataWithSelect<DataFromGlobalSlug<TSlug>, TSelect>\n : DataFromGlobalSlug<TSlug>\n\nexport type PopulateType = Partial<TypedCollectionSelect>\n\nexport type ResolvedFilterOptions = { [collection: string]: Where }\n\nexport type PickPreserveOptional<T, K extends keyof T> = Partial<\n Pick<T, Extract<K, OptionalKeys<T>>>\n> &\n Pick<T, Extract<K, RequiredKeys<T>>>\n\nexport type MaybePromise<T> = Promise<T> | T\n"],"names":["docHasTimestamps","doc","createdAt","updatedAt"],"mappings":"AA4LA,OAAO,SAASA,iBAAiBC,GAAQ;IACvC,OAAOA,KAAKC,aAAaD,KAAKE;AAChC"}
@@ -1 +1 @@
1
- {"version":3,"file":"checkFileAccess.d.ts","sourceRoot":"","sources":["../../src/uploads/checkFileAccess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,mBAAmB,CAAA;AAK9D,eAAO,MAAM,eAAe,2CAKzB;IACD,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,cAAc,CAAA;CACpB,KAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CA8CjC,CAAA"}
1
+ {"version":3,"file":"checkFileAccess.d.ts","sourceRoot":"","sources":["../../src/uploads/checkFileAccess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,mBAAmB,CAAA;AAO9D,eAAO,MAAM,eAAe,2CAKzB;IACD,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,cAAc,CAAA;CACpB,KAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAoEjC,CAAA"}
@@ -1,5 +1,7 @@
1
1
  import { executeAccess } from '../auth/executeAccess.js';
2
2
  import { Forbidden } from '../errors/Forbidden.js';
3
+ import { hasDraftsEnabled } from '../utilities/getVersionsConfig.js';
4
+ import { appendVersionToQueryKey } from '../versions/drafts/appendVersionToQueryKey.js';
3
5
  export const checkFileAccess = async ({ collection, filename, prefix, req })=>{
4
6
  if (filename.includes('../') || filename.includes('..\\')) {
5
7
  throw new Forbidden(req.t);
@@ -42,20 +44,39 @@ export const checkFileAccess = async ({ collection, filename, prefix, req })=>{
42
44
  });
43
45
  });
44
46
  }
47
+ const where = {
48
+ and: [
49
+ filenameCondition,
50
+ ...constraints
51
+ ]
52
+ };
45
53
  const doc = await req.payload.db.findOne({
46
54
  collection: config.slug,
47
55
  req,
48
- where: {
49
- and: [
50
- filenameCondition,
51
- ...constraints
52
- ]
53
- }
56
+ where
54
57
  });
55
- if (!doc) {
56
- throw new Forbidden(req.t);
58
+ if (doc) {
59
+ return doc;
57
60
  }
58
- return doc;
61
+ // Queries the version collection if `hasDraftsEnabled` is true:
62
+ //
63
+ // The base collection row only reflects the most recently committed
64
+ // (published) state. When a file is reuploaded on a draft, the new
65
+ // filename is written to the latest *version*, while the base row still
66
+ // points at the previously committed filename. The findOne above therefore
67
+ // misses the draft-only filename and access is wrongly denied.
68
+ if (hasDraftsEnabled(config)) {
69
+ const { docs } = await req.payload.db.queryDrafts({
70
+ collection: config.slug,
71
+ limit: 1,
72
+ req,
73
+ where: appendVersionToQueryKey(where)
74
+ });
75
+ if (docs[0]) {
76
+ return docs[0];
77
+ }
78
+ }
79
+ throw new Forbidden(req.t);
59
80
  }
60
81
  };
61
82
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/uploads/checkFileAccess.ts"],"sourcesContent":["import type { Collection, TypeWithID } from '../collections/config/types.js'\nimport type { PayloadRequest, Where } from '../types/index.js'\n\nimport { executeAccess } from '../auth/executeAccess.js'\nimport { Forbidden } from '../errors/Forbidden.js'\n\nexport const checkFileAccess = async ({\n collection,\n filename,\n prefix,\n req,\n}: {\n collection: Collection\n filename: string\n prefix?: string\n req: PayloadRequest\n}): Promise<TypeWithID | undefined> => {\n if (filename.includes('../') || filename.includes('..\\\\')) {\n throw new Forbidden(req.t)\n }\n const { config } = collection\n\n const accessResult = await executeAccess(\n { data: { filename }, isReadingStaticFile: true, req },\n config.access.read,\n )\n\n const constraints: Where[] = []\n\n if (typeof accessResult === 'object') {\n constraints.push(accessResult)\n }\n\n if (typeof prefix === 'string') {\n constraints.push({ prefix: { equals: prefix } })\n }\n\n if (constraints.length > 0) {\n const filenameCondition: Where = {\n or: [{ filename: { equals: filename } }],\n }\n\n if (config.upload.imageSizes) {\n config.upload.imageSizes.forEach(({ name }) => {\n filenameCondition.or!.push({\n [`sizes.${name}.filename`]: { equals: filename },\n })\n })\n }\n\n const doc = await req.payload.db.findOne({\n collection: config.slug,\n req,\n where: { and: [filenameCondition, ...constraints] },\n })\n\n if (!doc) {\n throw new Forbidden(req.t)\n }\n\n return doc\n }\n}\n"],"names":["executeAccess","Forbidden","checkFileAccess","collection","filename","prefix","req","includes","t","config","accessResult","data","isReadingStaticFile","access","read","constraints","push","equals","length","filenameCondition","or","upload","imageSizes","forEach","name","doc","payload","db","findOne","slug","where","and"],"mappings":"AAGA,SAASA,aAAa,QAAQ,2BAA0B;AACxD,SAASC,SAAS,QAAQ,yBAAwB;AAElD,OAAO,MAAMC,kBAAkB,OAAO,EACpCC,UAAU,EACVC,QAAQ,EACRC,MAAM,EACNC,GAAG,EAMJ;IACC,IAAIF,SAASG,QAAQ,CAAC,UAAUH,SAASG,QAAQ,CAAC,SAAS;QACzD,MAAM,IAAIN,UAAUK,IAAIE,CAAC;IAC3B;IACA,MAAM,EAAEC,MAAM,EAAE,GAAGN;IAEnB,MAAMO,eAAe,MAAMV,cACzB;QAAEW,MAAM;YAAEP;QAAS;QAAGQ,qBAAqB;QAAMN;IAAI,GACrDG,OAAOI,MAAM,CAACC,IAAI;IAGpB,MAAMC,cAAuB,EAAE;IAE/B,IAAI,OAAOL,iBAAiB,UAAU;QACpCK,YAAYC,IAAI,CAACN;IACnB;IAEA,IAAI,OAAOL,WAAW,UAAU;QAC9BU,YAAYC,IAAI,CAAC;YAAEX,QAAQ;gBAAEY,QAAQZ;YAAO;QAAE;IAChD;IAEA,IAAIU,YAAYG,MAAM,GAAG,GAAG;QAC1B,MAAMC,oBAA2B;YAC/BC,IAAI;gBAAC;oBAAEhB,UAAU;wBAAEa,QAAQb;oBAAS;gBAAE;aAAE;QAC1C;QAEA,IAAIK,OAAOY,MAAM,CAACC,UAAU,EAAE;YAC5Bb,OAAOY,MAAM,CAACC,UAAU,CAACC,OAAO,CAAC,CAAC,EAAEC,IAAI,EAAE;gBACxCL,kBAAkBC,EAAE,CAAEJ,IAAI,CAAC;oBACzB,CAAC,CAAC,MAAM,EAAEQ,KAAK,SAAS,CAAC,CAAC,EAAE;wBAAEP,QAAQb;oBAAS;gBACjD;YACF;QACF;QAEA,MAAMqB,MAAM,MAAMnB,IAAIoB,OAAO,CAACC,EAAE,CAACC,OAAO,CAAC;YACvCzB,YAAYM,OAAOoB,IAAI;YACvBvB;YACAwB,OAAO;gBAAEC,KAAK;oBAACZ;uBAAsBJ;iBAAY;YAAC;QACpD;QAEA,IAAI,CAACU,KAAK;YACR,MAAM,IAAIxB,UAAUK,IAAIE,CAAC;QAC3B;QAEA,OAAOiB;IACT;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/uploads/checkFileAccess.ts"],"sourcesContent":["import type { Collection, TypeWithID } from '../collections/config/types.js'\nimport type { PayloadRequest, Where } from '../types/index.js'\n\nimport { executeAccess } from '../auth/executeAccess.js'\nimport { Forbidden } from '../errors/Forbidden.js'\nimport { hasDraftsEnabled } from '../utilities/getVersionsConfig.js'\nimport { appendVersionToQueryKey } from '../versions/drafts/appendVersionToQueryKey.js'\n\nexport const checkFileAccess = async ({\n collection,\n filename,\n prefix,\n req,\n}: {\n collection: Collection\n filename: string\n prefix?: string\n req: PayloadRequest\n}): Promise<TypeWithID | undefined> => {\n if (filename.includes('../') || filename.includes('..\\\\')) {\n throw new Forbidden(req.t)\n }\n const { config } = collection\n\n const accessResult = await executeAccess(\n { data: { filename }, isReadingStaticFile: true, req },\n config.access.read,\n )\n\n const constraints: Where[] = []\n\n if (typeof accessResult === 'object') {\n constraints.push(accessResult)\n }\n\n if (typeof prefix === 'string') {\n constraints.push({ prefix: { equals: prefix } })\n }\n\n if (constraints.length > 0) {\n const filenameCondition: Where = {\n or: [{ filename: { equals: filename } }],\n }\n\n if (config.upload.imageSizes) {\n config.upload.imageSizes.forEach(({ name }) => {\n filenameCondition.or!.push({\n [`sizes.${name}.filename`]: { equals: filename },\n })\n })\n }\n\n const where: Where = { and: [filenameCondition, ...constraints] }\n\n const doc = await req.payload.db.findOne({\n collection: config.slug,\n req,\n where,\n })\n\n if (doc) {\n return doc\n }\n\n // Queries the version collection if `hasDraftsEnabled` is true:\n //\n // The base collection row only reflects the most recently committed\n // (published) state. When a file is reuploaded on a draft, the new\n // filename is written to the latest *version*, while the base row still\n // points at the previously committed filename. The findOne above therefore\n // misses the draft-only filename and access is wrongly denied.\n if (hasDraftsEnabled(config)) {\n const { docs } = await req.payload.db.queryDrafts({\n collection: config.slug,\n limit: 1,\n req,\n where: appendVersionToQueryKey(where),\n })\n\n if (docs[0]) {\n return docs[0]\n }\n }\n\n throw new Forbidden(req.t)\n }\n}\n"],"names":["executeAccess","Forbidden","hasDraftsEnabled","appendVersionToQueryKey","checkFileAccess","collection","filename","prefix","req","includes","t","config","accessResult","data","isReadingStaticFile","access","read","constraints","push","equals","length","filenameCondition","or","upload","imageSizes","forEach","name","where","and","doc","payload","db","findOne","slug","docs","queryDrafts","limit"],"mappings":"AAGA,SAASA,aAAa,QAAQ,2BAA0B;AACxD,SAASC,SAAS,QAAQ,yBAAwB;AAClD,SAASC,gBAAgB,QAAQ,oCAAmC;AACpE,SAASC,uBAAuB,QAAQ,gDAA+C;AAEvF,OAAO,MAAMC,kBAAkB,OAAO,EACpCC,UAAU,EACVC,QAAQ,EACRC,MAAM,EACNC,GAAG,EAMJ;IACC,IAAIF,SAASG,QAAQ,CAAC,UAAUH,SAASG,QAAQ,CAAC,SAAS;QACzD,MAAM,IAAIR,UAAUO,IAAIE,CAAC;IAC3B;IACA,MAAM,EAAEC,MAAM,EAAE,GAAGN;IAEnB,MAAMO,eAAe,MAAMZ,cACzB;QAAEa,MAAM;YAAEP;QAAS;QAAGQ,qBAAqB;QAAMN;IAAI,GACrDG,OAAOI,MAAM,CAACC,IAAI;IAGpB,MAAMC,cAAuB,EAAE;IAE/B,IAAI,OAAOL,iBAAiB,UAAU;QACpCK,YAAYC,IAAI,CAACN;IACnB;IAEA,IAAI,OAAOL,WAAW,UAAU;QAC9BU,YAAYC,IAAI,CAAC;YAAEX,QAAQ;gBAAEY,QAAQZ;YAAO;QAAE;IAChD;IAEA,IAAIU,YAAYG,MAAM,GAAG,GAAG;QAC1B,MAAMC,oBAA2B;YAC/BC,IAAI;gBAAC;oBAAEhB,UAAU;wBAAEa,QAAQb;oBAAS;gBAAE;aAAE;QAC1C;QAEA,IAAIK,OAAOY,MAAM,CAACC,UAAU,EAAE;YAC5Bb,OAAOY,MAAM,CAACC,UAAU,CAACC,OAAO,CAAC,CAAC,EAAEC,IAAI,EAAE;gBACxCL,kBAAkBC,EAAE,CAAEJ,IAAI,CAAC;oBACzB,CAAC,CAAC,MAAM,EAAEQ,KAAK,SAAS,CAAC,CAAC,EAAE;wBAAEP,QAAQb;oBAAS;gBACjD;YACF;QACF;QAEA,MAAMqB,QAAe;YAAEC,KAAK;gBAACP;mBAAsBJ;aAAY;QAAC;QAEhE,MAAMY,MAAM,MAAMrB,IAAIsB,OAAO,CAACC,EAAE,CAACC,OAAO,CAAC;YACvC3B,YAAYM,OAAOsB,IAAI;YACvBzB;YACAmB;QACF;QAEA,IAAIE,KAAK;YACP,OAAOA;QACT;QAEA,gEAAgE;QAChE,EAAE;QACF,oEAAoE;QACpE,mEAAmE;QACnE,wEAAwE;QACxE,2EAA2E;QAC3E,+DAA+D;QAC/D,IAAI3B,iBAAiBS,SAAS;YAC5B,MAAM,EAAEuB,IAAI,EAAE,GAAG,MAAM1B,IAAIsB,OAAO,CAACC,EAAE,CAACI,WAAW,CAAC;gBAChD9B,YAAYM,OAAOsB,IAAI;gBACvBG,OAAO;gBACP5B;gBACAmB,OAAOxB,wBAAwBwB;YACjC;YAEA,IAAIO,IAAI,CAAC,EAAE,EAAE;gBACX,OAAOA,IAAI,CAAC,EAAE;YAChB;QACF;QAEA,MAAM,IAAIjC,UAAUO,IAAIE,CAAC;IAC3B;AACF,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"checkFileRestrictions.d.ts","sourceRoot":"","sources":["../../src/uploads/checkFileRestrictions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAS5E;;GAEG;AACH,eAAO,MAAM,6BAA6B,EAAE,aAgC3C,CAAA;AAED,eAAO,MAAM,qBAAqB,+BAI/B,2BAA2B,KAAG,OAAO,CAAC,IAAI,CAuH5C,CAAA"}
1
+ {"version":3,"file":"checkFileRestrictions.d.ts","sourceRoot":"","sources":["../../src/uploads/checkFileRestrictions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAS5E;;GAEG;AACH,eAAO,MAAM,6BAA6B,EAAE,aAgC3C,CAAA;AAED,eAAO,MAAM,qBAAqB,+BAI/B,2BAA2B,KAAG,OAAO,CAAC,IAAI,CAyJ5C,CAAA"}
@@ -1,4 +1,5 @@
1
- import { fileTypeFromBuffer } from 'file-type';
1
+ import { fileTypeFromBuffer, fileTypeFromFile } from 'file-type';
2
+ import fs from 'fs/promises';
2
3
  import { ValidationError } from '../errors/index.js';
3
4
  import { validateMimeType } from '../utilities/validateMimeType.js';
4
5
  import { validatePDF } from '../utilities/validatePDF.js';
@@ -221,7 +222,6 @@ import { validateSvg } from './validateSvg.js';
221
222
  export const checkFileRestrictions = async ({ collection, file, req })=>{
222
223
  const errors = [];
223
224
  const { upload: uploadConfig } = collection;
224
- const useTempFiles = req?.payload?.config?.upload?.useTempFiles ?? false;
225
225
  const configMimeTypes = uploadConfig && typeof uploadConfig === 'object' && 'mimeTypes' in uploadConfig && Array.isArray(uploadConfig.mimeTypes) ? uploadConfig.mimeTypes : [];
226
226
  const allowRestrictedFileTypes = uploadConfig && typeof uploadConfig === 'object' && 'allowRestrictedFileTypes' in uploadConfig ? uploadConfig.allowRestrictedFileTypes : false;
227
227
  const expectsDetectableType = (mimeType)=>{
@@ -240,13 +240,53 @@ export const checkFileRestrictions = async ({ collection, file, req })=>{
240
240
  if (allowRestrictedFileTypes) {
241
241
  return;
242
242
  }
243
+ // For temp files, use fileTypeFromFile so large files (e.g. video) are never loaded into memory
244
+ // just for detection. For content validation (SVG safety, PDF integrity), the full buffer is
245
+ // loaded lazily and only when the file type actually requires it.
246
+ const { tempFilePath } = file;
247
+ const isTempFile = !!tempFilePath && (!file.data || file.data.length === 0);
248
+ // Lazily reads the full file — only reached for small text-based types (SVG, PDF).
249
+ let _fileBuffer;
250
+ const getFileBuffer = async ()=>{
251
+ if (_fileBuffer) {
252
+ return _fileBuffer;
253
+ }
254
+ if (!isTempFile || !tempFilePath) {
255
+ return _fileBuffer = file.data;
256
+ }
257
+ try {
258
+ _fileBuffer = await fs.readFile(tempFilePath);
259
+ return _fileBuffer;
260
+ } catch {
261
+ throw new ValidationError({
262
+ errors: [
263
+ {
264
+ message: 'Could not read uploaded file for validation.',
265
+ path: 'file'
266
+ }
267
+ ]
268
+ });
269
+ }
270
+ };
243
271
  // Secondary mimetype check to assess file type from buffer
244
272
  if (configMimeTypes.length > 0) {
245
- let detected = await fileTypeFromBuffer(file.data);
273
+ let detected;
274
+ try {
275
+ detected = isTempFile && tempFilePath ? await fileTypeFromFile(tempFilePath) : await fileTypeFromBuffer(file.data);
276
+ } catch {
277
+ throw new ValidationError({
278
+ errors: [
279
+ {
280
+ message: 'Could not read uploaded file for type detection.',
281
+ path: 'file'
282
+ }
283
+ ]
284
+ });
285
+ }
246
286
  const typeFromExtension = file.name.split('.').pop() || '';
247
287
  // Handle SVG files that are detected as XML due to <?xml declarations
248
288
  if (detected?.mime === 'application/xml' && configMimeTypes.some((type)=>type.includes('image/') && (type.includes('svg') || type === 'image/*'))) {
249
- const isSvg = detectSvgFromXml(file.data);
289
+ const isSvg = detectSvgFromXml(await getFileBuffer());
250
290
  if (isSvg) {
251
291
  detected = {
252
292
  ext: 'svg',
@@ -254,7 +294,7 @@ export const checkFileRestrictions = async ({ collection, file, req })=>{
254
294
  };
255
295
  }
256
296
  }
257
- if (!detected && !useTempFiles) {
297
+ if (!detected) {
258
298
  const mimeTypeFromExtension = getFileTypeFallback(file.name).mime;
259
299
  const extIsValid = validateMimeType(mimeTypeFromExtension, configMimeTypes);
260
300
  if (!extIsValid) {
@@ -262,14 +302,14 @@ export const checkFileRestrictions = async ({ collection, file, req })=>{
262
302
  } else {
263
303
  // SVG security check (text-based files not detectable by buffer)
264
304
  if (typeFromExtension.toLowerCase() === 'svg') {
265
- const isSafeSvg = validateSvg(file.data);
305
+ const isSafeSvg = validateSvg(await getFileBuffer());
266
306
  if (!isSafeSvg) {
267
307
  errors.push('SVG file contains potentially harmful content.');
268
308
  }
269
309
  }
270
310
  // PDF validation
271
311
  if (mimeTypeFromExtension === 'application/pdf') {
272
- const isValidPDF = validatePDF(file.data);
312
+ const isValidPDF = validatePDF(await getFileBuffer());
273
313
  if (!isValidPDF) {
274
314
  errors.push('Invalid or corrupted PDF file.');
275
315
  }
@@ -281,7 +321,7 @@ export const checkFileRestrictions = async ({ collection, file, req })=>{
281
321
  }
282
322
  const passesMimeTypeCheck = detected?.mime && validateMimeType(detected.mime, configMimeTypes);
283
323
  if (passesMimeTypeCheck && detected?.mime === 'application/pdf') {
284
- const isValidPDF = validatePDF(file?.data);
324
+ const isValidPDF = validatePDF(await getFileBuffer());
285
325
  if (!isValidPDF) {
286
326
  errors.push('Invalid PDF file.');
287
327
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/uploads/checkFileRestrictions.ts"],"sourcesContent":["import { fileTypeFromBuffer } from 'file-type'\n\nimport type { checkFileRestrictionsParams, FileAllowList } from './types.js'\n\nimport { ValidationError } from '../errors/index.js'\nimport { validateMimeType } from '../utilities/validateMimeType.js'\nimport { validatePDF } from '../utilities/validatePDF.js'\nimport { detectSvgFromXml } from './detectSvgFromXml.js'\nimport { getFileTypeFallback } from './getFileTypeFallback.js'\nimport { validateSvg } from './validateSvg.js'\n\n/**\n * Restricted file types and their extensions.\n */\nexport const RESTRICTED_FILE_EXT_AND_TYPES: FileAllowList = [\n { extensions: ['exe', 'dll'], mimeType: 'application/x-msdownload' },\n { extensions: ['exe', 'com', 'app', 'action'], mimeType: 'application/x-executable' },\n { extensions: ['bat', 'cmd'], mimeType: 'application/x-msdos-program' },\n { extensions: ['exe', 'com'], mimeType: 'application/x-ms-dos-executable' },\n { extensions: ['dmg'], mimeType: 'application/x-apple-diskimage' },\n { extensions: ['deb'], mimeType: 'application/x-debian-package' },\n { extensions: ['rpm'], mimeType: 'application/x-redhat-package-manager' },\n { extensions: ['exe', 'dll'], mimeType: 'application/vnd.microsoft.portable-executable' },\n { extensions: ['msi'], mimeType: 'application/x-msi' },\n { extensions: ['jar', 'ear', 'war'], mimeType: 'application/java-archive' },\n { extensions: ['desktop'], mimeType: 'application/x-desktop' },\n { extensions: ['cpl'], mimeType: 'application/x-cpl' },\n { extensions: ['lnk'], mimeType: 'application/x-ms-shortcut' },\n { extensions: ['pkg'], mimeType: 'application/x-apple-installer' },\n { extensions: ['htm', 'html', 'shtml', 'xhtml'], mimeType: 'text/html' },\n { extensions: ['php', 'phtml'], mimeType: 'application/x-httpd-php' },\n { extensions: ['js', 'jse'], mimeType: 'text/javascript' },\n { extensions: ['jsp'], mimeType: 'application/x-jsp' },\n { extensions: ['py'], mimeType: 'text/x-python' },\n { extensions: ['rb'], mimeType: 'text/x-ruby' },\n { extensions: ['pl'], mimeType: 'text/x-perl' },\n { extensions: ['ps1', 'psc1', 'psd1', 'psh', 'psm1'], mimeType: 'application/x-powershell' },\n { extensions: ['vbe', 'vbs'], mimeType: 'application/x-vbscript' },\n { extensions: ['ws', 'wsc', 'wsf', 'wsh'], mimeType: 'application/x-ms-wsh' },\n { extensions: ['scr'], mimeType: 'application/x-msdownload' },\n { extensions: ['asp', 'aspx'], mimeType: 'application/x-asp' },\n { extensions: ['hta'], mimeType: 'application/x-hta' },\n { extensions: ['reg'], mimeType: 'application/x-registry' },\n { extensions: ['url'], mimeType: 'application/x-url' },\n { extensions: ['workflow'], mimeType: 'application/x-workflow' },\n { extensions: ['command'], mimeType: 'application/x-command' },\n]\n\nexport const checkFileRestrictions = async ({\n collection,\n file,\n req,\n}: checkFileRestrictionsParams): Promise<void> => {\n const errors: string[] = []\n const { upload: uploadConfig } = collection\n const useTempFiles = req?.payload?.config?.upload?.useTempFiles ?? false\n const configMimeTypes =\n uploadConfig &&\n typeof uploadConfig === 'object' &&\n 'mimeTypes' in uploadConfig &&\n Array.isArray(uploadConfig.mimeTypes)\n ? uploadConfig.mimeTypes\n : []\n\n const allowRestrictedFileTypes =\n uploadConfig && typeof uploadConfig === 'object' && 'allowRestrictedFileTypes' in uploadConfig\n ? (uploadConfig as { allowRestrictedFileTypes?: boolean }).allowRestrictedFileTypes\n : false\n\n const expectsDetectableType = (mimeType: string): boolean => {\n const textBasedTypes = ['/svg', 'image/svg+xml', 'image/x-xbitmap', 'image/x-xpixmap']\n\n if (textBasedTypes.includes(mimeType)) {\n return false\n }\n\n return (\n mimeType.startsWith('image/') ||\n mimeType.startsWith('video/') ||\n mimeType.startsWith('audio/') ||\n mimeType === 'application/pdf'\n )\n }\n\n // Skip validation if `allowRestrictedFileTypes` is true\n if (allowRestrictedFileTypes) {\n return\n }\n\n // Secondary mimetype check to assess file type from buffer\n if (configMimeTypes.length > 0) {\n let detected = await fileTypeFromBuffer(file.data)\n const typeFromExtension = file.name.split('.').pop() || ''\n\n // Handle SVG files that are detected as XML due to <?xml declarations\n if (\n detected?.mime === 'application/xml' &&\n configMimeTypes.some(\n (type) => type.includes('image/') && (type.includes('svg') || type === 'image/*'),\n )\n ) {\n const isSvg = detectSvgFromXml(file.data)\n if (isSvg) {\n detected = { ext: 'svg' as any, mime: 'image/svg+xml' as any }\n }\n }\n\n if (!detected && !useTempFiles) {\n const mimeTypeFromExtension = getFileTypeFallback(file.name).mime\n const extIsValid = validateMimeType(mimeTypeFromExtension, configMimeTypes)\n\n if (!extIsValid) {\n errors.push(\n `File type ${mimeTypeFromExtension} (from extension ${typeFromExtension}) is not allowed.`,\n )\n } else {\n // SVG security check (text-based files not detectable by buffer)\n if (typeFromExtension.toLowerCase() === 'svg') {\n const isSafeSvg = validateSvg(file.data)\n if (!isSafeSvg) {\n errors.push('SVG file contains potentially harmful content.')\n }\n }\n\n // PDF validation\n if (mimeTypeFromExtension === 'application/pdf') {\n const isValidPDF = validatePDF(file.data)\n if (!isValidPDF) {\n errors.push('Invalid or corrupted PDF file.')\n }\n }\n }\n\n if (expectsDetectableType(mimeTypeFromExtension)) {\n req.payload.logger.warn(\n `File buffer returned no detectable MIME type for ${file.name}. Falling back to extension-based validation.`,\n )\n }\n }\n\n const passesMimeTypeCheck = detected?.mime && validateMimeType(detected.mime, configMimeTypes)\n\n if (passesMimeTypeCheck && detected?.mime === 'application/pdf') {\n const isValidPDF = validatePDF(file?.data)\n if (!isValidPDF) {\n errors.push('Invalid PDF file.')\n }\n }\n\n if (detected && !passesMimeTypeCheck) {\n errors.push(`Invalid MIME type: ${detected.mime}.`)\n }\n } else {\n const isRestricted = RESTRICTED_FILE_EXT_AND_TYPES.some((type) => {\n const hasRestrictedExt = type.extensions.some((ext) => file.name.toLowerCase().endsWith(ext))\n const hasRestrictedMime = type.mimeType === file.mimetype\n return hasRestrictedExt || hasRestrictedMime\n })\n if (isRestricted) {\n errors.push(\n `File type '${file.mimetype}' not allowed ${file.name}: Restricted file type detected -- set 'allowRestrictedFileTypes' to true to skip this check for this Collection.`,\n )\n }\n }\n\n if (errors.length > 0) {\n req.payload.logger.error(errors.join(', '))\n throw new ValidationError({\n errors: [{ message: errors.join(', '), path: 'file' }],\n })\n }\n}\n"],"names":["fileTypeFromBuffer","ValidationError","validateMimeType","validatePDF","detectSvgFromXml","getFileTypeFallback","validateSvg","RESTRICTED_FILE_EXT_AND_TYPES","extensions","mimeType","checkFileRestrictions","collection","file","req","errors","upload","uploadConfig","useTempFiles","payload","config","configMimeTypes","Array","isArray","mimeTypes","allowRestrictedFileTypes","expectsDetectableType","textBasedTypes","includes","startsWith","length","detected","data","typeFromExtension","name","split","pop","mime","some","type","isSvg","ext","mimeTypeFromExtension","extIsValid","push","toLowerCase","isSafeSvg","isValidPDF","logger","warn","passesMimeTypeCheck","isRestricted","hasRestrictedExt","endsWith","hasRestrictedMime","mimetype","error","join","message","path"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/uploads/checkFileRestrictions.ts"],"sourcesContent":["import { fileTypeFromBuffer, fileTypeFromFile } from 'file-type'\nimport fs from 'fs/promises'\n\nimport type { checkFileRestrictionsParams, FileAllowList } from './types.js'\n\nimport { ValidationError } from '../errors/index.js'\nimport { validateMimeType } from '../utilities/validateMimeType.js'\nimport { validatePDF } from '../utilities/validatePDF.js'\nimport { detectSvgFromXml } from './detectSvgFromXml.js'\nimport { getFileTypeFallback } from './getFileTypeFallback.js'\nimport { validateSvg } from './validateSvg.js'\n\n/**\n * Restricted file types and their extensions.\n */\nexport const RESTRICTED_FILE_EXT_AND_TYPES: FileAllowList = [\n { extensions: ['exe', 'dll'], mimeType: 'application/x-msdownload' },\n { extensions: ['exe', 'com', 'app', 'action'], mimeType: 'application/x-executable' },\n { extensions: ['bat', 'cmd'], mimeType: 'application/x-msdos-program' },\n { extensions: ['exe', 'com'], mimeType: 'application/x-ms-dos-executable' },\n { extensions: ['dmg'], mimeType: 'application/x-apple-diskimage' },\n { extensions: ['deb'], mimeType: 'application/x-debian-package' },\n { extensions: ['rpm'], mimeType: 'application/x-redhat-package-manager' },\n { extensions: ['exe', 'dll'], mimeType: 'application/vnd.microsoft.portable-executable' },\n { extensions: ['msi'], mimeType: 'application/x-msi' },\n { extensions: ['jar', 'ear', 'war'], mimeType: 'application/java-archive' },\n { extensions: ['desktop'], mimeType: 'application/x-desktop' },\n { extensions: ['cpl'], mimeType: 'application/x-cpl' },\n { extensions: ['lnk'], mimeType: 'application/x-ms-shortcut' },\n { extensions: ['pkg'], mimeType: 'application/x-apple-installer' },\n { extensions: ['htm', 'html', 'shtml', 'xhtml'], mimeType: 'text/html' },\n { extensions: ['php', 'phtml'], mimeType: 'application/x-httpd-php' },\n { extensions: ['js', 'jse'], mimeType: 'text/javascript' },\n { extensions: ['jsp'], mimeType: 'application/x-jsp' },\n { extensions: ['py'], mimeType: 'text/x-python' },\n { extensions: ['rb'], mimeType: 'text/x-ruby' },\n { extensions: ['pl'], mimeType: 'text/x-perl' },\n { extensions: ['ps1', 'psc1', 'psd1', 'psh', 'psm1'], mimeType: 'application/x-powershell' },\n { extensions: ['vbe', 'vbs'], mimeType: 'application/x-vbscript' },\n { extensions: ['ws', 'wsc', 'wsf', 'wsh'], mimeType: 'application/x-ms-wsh' },\n { extensions: ['scr'], mimeType: 'application/x-msdownload' },\n { extensions: ['asp', 'aspx'], mimeType: 'application/x-asp' },\n { extensions: ['hta'], mimeType: 'application/x-hta' },\n { extensions: ['reg'], mimeType: 'application/x-registry' },\n { extensions: ['url'], mimeType: 'application/x-url' },\n { extensions: ['workflow'], mimeType: 'application/x-workflow' },\n { extensions: ['command'], mimeType: 'application/x-command' },\n]\n\nexport const checkFileRestrictions = async ({\n collection,\n file,\n req,\n}: checkFileRestrictionsParams): Promise<void> => {\n const errors: string[] = []\n const { upload: uploadConfig } = collection\n const configMimeTypes =\n uploadConfig &&\n typeof uploadConfig === 'object' &&\n 'mimeTypes' in uploadConfig &&\n Array.isArray(uploadConfig.mimeTypes)\n ? uploadConfig.mimeTypes\n : []\n\n const allowRestrictedFileTypes =\n uploadConfig && typeof uploadConfig === 'object' && 'allowRestrictedFileTypes' in uploadConfig\n ? (uploadConfig as { allowRestrictedFileTypes?: boolean }).allowRestrictedFileTypes\n : false\n\n const expectsDetectableType = (mimeType: string): boolean => {\n const textBasedTypes = ['/svg', 'image/svg+xml', 'image/x-xbitmap', 'image/x-xpixmap']\n\n if (textBasedTypes.includes(mimeType)) {\n return false\n }\n\n return (\n mimeType.startsWith('image/') ||\n mimeType.startsWith('video/') ||\n mimeType.startsWith('audio/') ||\n mimeType === 'application/pdf'\n )\n }\n\n // Skip validation if `allowRestrictedFileTypes` is true\n if (allowRestrictedFileTypes) {\n return\n }\n\n // For temp files, use fileTypeFromFile so large files (e.g. video) are never loaded into memory\n // just for detection. For content validation (SVG safety, PDF integrity), the full buffer is\n // loaded lazily and only when the file type actually requires it.\n const { tempFilePath } = file\n const isTempFile = !!tempFilePath && (!file.data || file.data.length === 0)\n\n // Lazily reads the full file — only reached for small text-based types (SVG, PDF).\n let _fileBuffer: Buffer | undefined\n const getFileBuffer = async (): Promise<Buffer> => {\n if (_fileBuffer) {\n return _fileBuffer\n }\n if (!isTempFile || !tempFilePath) {\n return (_fileBuffer = file.data)\n }\n try {\n _fileBuffer = await fs.readFile(tempFilePath)\n return _fileBuffer\n } catch {\n throw new ValidationError({\n errors: [{ message: 'Could not read uploaded file for validation.', path: 'file' }],\n })\n }\n }\n\n // Secondary mimetype check to assess file type from buffer\n if (configMimeTypes.length > 0) {\n let detected\n try {\n detected =\n isTempFile && tempFilePath\n ? await fileTypeFromFile(tempFilePath)\n : await fileTypeFromBuffer(file.data)\n } catch {\n throw new ValidationError({\n errors: [{ message: 'Could not read uploaded file for type detection.', path: 'file' }],\n })\n }\n const typeFromExtension = file.name.split('.').pop() || ''\n\n // Handle SVG files that are detected as XML due to <?xml declarations\n if (\n detected?.mime === 'application/xml' &&\n configMimeTypes.some(\n (type) => type.includes('image/') && (type.includes('svg') || type === 'image/*'),\n )\n ) {\n const isSvg = detectSvgFromXml(await getFileBuffer())\n if (isSvg) {\n detected = { ext: 'svg', mime: 'image/svg+xml' }\n }\n }\n\n if (!detected) {\n const mimeTypeFromExtension = getFileTypeFallback(file.name).mime\n const extIsValid = validateMimeType(mimeTypeFromExtension, configMimeTypes)\n\n if (!extIsValid) {\n errors.push(\n `File type ${mimeTypeFromExtension} (from extension ${typeFromExtension}) is not allowed.`,\n )\n } else {\n // SVG security check (text-based files not detectable by buffer)\n if (typeFromExtension.toLowerCase() === 'svg') {\n const isSafeSvg = validateSvg(await getFileBuffer())\n if (!isSafeSvg) {\n errors.push('SVG file contains potentially harmful content.')\n }\n }\n\n // PDF validation\n if (mimeTypeFromExtension === 'application/pdf') {\n const isValidPDF = validatePDF(await getFileBuffer())\n if (!isValidPDF) {\n errors.push('Invalid or corrupted PDF file.')\n }\n }\n }\n\n if (expectsDetectableType(mimeTypeFromExtension)) {\n req.payload.logger.warn(\n `File buffer returned no detectable MIME type for ${file.name}. Falling back to extension-based validation.`,\n )\n }\n }\n\n const passesMimeTypeCheck = detected?.mime && validateMimeType(detected.mime, configMimeTypes)\n\n if (passesMimeTypeCheck && detected?.mime === 'application/pdf') {\n const isValidPDF = validatePDF(await getFileBuffer())\n if (!isValidPDF) {\n errors.push('Invalid PDF file.')\n }\n }\n\n if (detected && !passesMimeTypeCheck) {\n errors.push(`Invalid MIME type: ${detected.mime}.`)\n }\n } else {\n const isRestricted = RESTRICTED_FILE_EXT_AND_TYPES.some((type) => {\n const hasRestrictedExt = type.extensions.some((ext) => file.name.toLowerCase().endsWith(ext))\n const hasRestrictedMime = type.mimeType === file.mimetype\n return hasRestrictedExt || hasRestrictedMime\n })\n if (isRestricted) {\n errors.push(\n `File type '${file.mimetype}' not allowed ${file.name}: Restricted file type detected -- set 'allowRestrictedFileTypes' to true to skip this check for this Collection.`,\n )\n }\n }\n\n if (errors.length > 0) {\n req.payload.logger.error(errors.join(', '))\n throw new ValidationError({\n errors: [{ message: errors.join(', '), path: 'file' }],\n })\n }\n}\n"],"names":["fileTypeFromBuffer","fileTypeFromFile","fs","ValidationError","validateMimeType","validatePDF","detectSvgFromXml","getFileTypeFallback","validateSvg","RESTRICTED_FILE_EXT_AND_TYPES","extensions","mimeType","checkFileRestrictions","collection","file","req","errors","upload","uploadConfig","configMimeTypes","Array","isArray","mimeTypes","allowRestrictedFileTypes","expectsDetectableType","textBasedTypes","includes","startsWith","tempFilePath","isTempFile","data","length","_fileBuffer","getFileBuffer","readFile","message","path","detected","typeFromExtension","name","split","pop","mime","some","type","isSvg","ext","mimeTypeFromExtension","extIsValid","push","toLowerCase","isSafeSvg","isValidPDF","payload","logger","warn","passesMimeTypeCheck","isRestricted","hasRestrictedExt","endsWith","hasRestrictedMime","mimetype","error","join"],"mappings":"AAAA,SAASA,kBAAkB,EAAEC,gBAAgB,QAAQ,YAAW;AAChE,OAAOC,QAAQ,cAAa;AAI5B,SAASC,eAAe,QAAQ,qBAAoB;AACpD,SAASC,gBAAgB,QAAQ,mCAAkC;AACnE,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,gBAAgB,QAAQ,wBAAuB;AACxD,SAASC,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,WAAW,QAAQ,mBAAkB;AAE9C;;CAEC,GACD,OAAO,MAAMC,gCAA+C;IAC1D;QAAEC,YAAY;YAAC;YAAO;SAAM;QAAEC,UAAU;IAA2B;IACnE;QAAED,YAAY;YAAC;YAAO;YAAO;YAAO;SAAS;QAAEC,UAAU;IAA2B;IACpF;QAAED,YAAY;YAAC;YAAO;SAAM;QAAEC,UAAU;IAA8B;IACtE;QAAED,YAAY;YAAC;YAAO;SAAM;QAAEC,UAAU;IAAkC;IAC1E;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAAgC;IACjE;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAA+B;IAChE;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAAuC;IACxE;QAAED,YAAY;YAAC;YAAO;SAAM;QAAEC,UAAU;IAAgD;IACxF;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAAoB;IACrD;QAAED,YAAY;YAAC;YAAO;YAAO;SAAM;QAAEC,UAAU;IAA2B;IAC1E;QAAED,YAAY;YAAC;SAAU;QAAEC,UAAU;IAAwB;IAC7D;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAAoB;IACrD;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAA4B;IAC7D;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAAgC;IACjE;QAAED,YAAY;YAAC;YAAO;YAAQ;YAAS;SAAQ;QAAEC,UAAU;IAAY;IACvE;QAAED,YAAY;YAAC;YAAO;SAAQ;QAAEC,UAAU;IAA0B;IACpE;QAAED,YAAY;YAAC;YAAM;SAAM;QAAEC,UAAU;IAAkB;IACzD;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAAoB;IACrD;QAAED,YAAY;YAAC;SAAK;QAAEC,UAAU;IAAgB;IAChD;QAAED,YAAY;YAAC;SAAK;QAAEC,UAAU;IAAc;IAC9C;QAAED,YAAY;YAAC;SAAK;QAAEC,UAAU;IAAc;IAC9C;QAAED,YAAY;YAAC;YAAO;YAAQ;YAAQ;YAAO;SAAO;QAAEC,UAAU;IAA2B;IAC3F;QAAED,YAAY;YAAC;YAAO;SAAM;QAAEC,UAAU;IAAyB;IACjE;QAAED,YAAY;YAAC;YAAM;YAAO;YAAO;SAAM;QAAEC,UAAU;IAAuB;IAC5E;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAA2B;IAC5D;QAAED,YAAY;YAAC;YAAO;SAAO;QAAEC,UAAU;IAAoB;IAC7D;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAAoB;IACrD;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAAyB;IAC1D;QAAED,YAAY;YAAC;SAAM;QAAEC,UAAU;IAAoB;IACrD;QAAED,YAAY;YAAC;SAAW;QAAEC,UAAU;IAAyB;IAC/D;QAAED,YAAY;YAAC;SAAU;QAAEC,UAAU;IAAwB;CAC9D,CAAA;AAED,OAAO,MAAMC,wBAAwB,OAAO,EAC1CC,UAAU,EACVC,IAAI,EACJC,GAAG,EACyB;IAC5B,MAAMC,SAAmB,EAAE;IAC3B,MAAM,EAAEC,QAAQC,YAAY,EAAE,GAAGL;IACjC,MAAMM,kBACJD,gBACA,OAAOA,iBAAiB,YACxB,eAAeA,gBACfE,MAAMC,OAAO,CAACH,aAAaI,SAAS,IAChCJ,aAAaI,SAAS,GACtB,EAAE;IAER,MAAMC,2BACJL,gBAAgB,OAAOA,iBAAiB,YAAY,8BAA8BA,eAC9E,AAACA,aAAwDK,wBAAwB,GACjF;IAEN,MAAMC,wBAAwB,CAACb;QAC7B,MAAMc,iBAAiB;YAAC;YAAQ;YAAiB;YAAmB;SAAkB;QAEtF,IAAIA,eAAeC,QAAQ,CAACf,WAAW;YACrC,OAAO;QACT;QAEA,OACEA,SAASgB,UAAU,CAAC,aACpBhB,SAASgB,UAAU,CAAC,aACpBhB,SAASgB,UAAU,CAAC,aACpBhB,aAAa;IAEjB;IAEA,wDAAwD;IACxD,IAAIY,0BAA0B;QAC5B;IACF;IAEA,gGAAgG;IAChG,6FAA6F;IAC7F,kEAAkE;IAClE,MAAM,EAAEK,YAAY,EAAE,GAAGd;IACzB,MAAMe,aAAa,CAAC,CAACD,gBAAiB,CAAA,CAACd,KAAKgB,IAAI,IAAIhB,KAAKgB,IAAI,CAACC,MAAM,KAAK,CAAA;IAEzE,mFAAmF;IACnF,IAAIC;IACJ,MAAMC,gBAAgB;QACpB,IAAID,aAAa;YACf,OAAOA;QACT;QACA,IAAI,CAACH,cAAc,CAACD,cAAc;YAChC,OAAQI,cAAclB,KAAKgB,IAAI;QACjC;QACA,IAAI;YACFE,cAAc,MAAM9B,GAAGgC,QAAQ,CAACN;YAChC,OAAOI;QACT,EAAE,OAAM;YACN,MAAM,IAAI7B,gBAAgB;gBACxBa,QAAQ;oBAAC;wBAAEmB,SAAS;wBAAgDC,MAAM;oBAAO;iBAAE;YACrF;QACF;IACF;IAEA,2DAA2D;IAC3D,IAAIjB,gBAAgBY,MAAM,GAAG,GAAG;QAC9B,IAAIM;QACJ,IAAI;YACFA,WACER,cAAcD,eACV,MAAM3B,iBAAiB2B,gBACvB,MAAM5B,mBAAmBc,KAAKgB,IAAI;QAC1C,EAAE,OAAM;YACN,MAAM,IAAI3B,gBAAgB;gBACxBa,QAAQ;oBAAC;wBAAEmB,SAAS;wBAAoDC,MAAM;oBAAO;iBAAE;YACzF;QACF;QACA,MAAME,oBAAoBxB,KAAKyB,IAAI,CAACC,KAAK,CAAC,KAAKC,GAAG,MAAM;QAExD,sEAAsE;QACtE,IACEJ,UAAUK,SAAS,qBACnBvB,gBAAgBwB,IAAI,CAClB,CAACC,OAASA,KAAKlB,QAAQ,CAAC,aAAckB,CAAAA,KAAKlB,QAAQ,CAAC,UAAUkB,SAAS,SAAQ,IAEjF;YACA,MAAMC,QAAQvC,iBAAiB,MAAM2B;YACrC,IAAIY,OAAO;gBACTR,WAAW;oBAAES,KAAK;oBAAOJ,MAAM;gBAAgB;YACjD;QACF;QAEA,IAAI,CAACL,UAAU;YACb,MAAMU,wBAAwBxC,oBAAoBO,KAAKyB,IAAI,EAAEG,IAAI;YACjE,MAAMM,aAAa5C,iBAAiB2C,uBAAuB5B;YAE3D,IAAI,CAAC6B,YAAY;gBACfhC,OAAOiC,IAAI,CACT,CAAC,UAAU,EAAEF,sBAAsB,iBAAiB,EAAET,kBAAkB,iBAAiB,CAAC;YAE9F,OAAO;gBACL,iEAAiE;gBACjE,IAAIA,kBAAkBY,WAAW,OAAO,OAAO;oBAC7C,MAAMC,YAAY3C,YAAY,MAAMyB;oBACpC,IAAI,CAACkB,WAAW;wBACdnC,OAAOiC,IAAI,CAAC;oBACd;gBACF;gBAEA,iBAAiB;gBACjB,IAAIF,0BAA0B,mBAAmB;oBAC/C,MAAMK,aAAa/C,YAAY,MAAM4B;oBACrC,IAAI,CAACmB,YAAY;wBACfpC,OAAOiC,IAAI,CAAC;oBACd;gBACF;YACF;YAEA,IAAIzB,sBAAsBuB,wBAAwB;gBAChDhC,IAAIsC,OAAO,CAACC,MAAM,CAACC,IAAI,CACrB,CAAC,iDAAiD,EAAEzC,KAAKyB,IAAI,CAAC,6CAA6C,CAAC;YAEhH;QACF;QAEA,MAAMiB,sBAAsBnB,UAAUK,QAAQtC,iBAAiBiC,SAASK,IAAI,EAAEvB;QAE9E,IAAIqC,uBAAuBnB,UAAUK,SAAS,mBAAmB;YAC/D,MAAMU,aAAa/C,YAAY,MAAM4B;YACrC,IAAI,CAACmB,YAAY;gBACfpC,OAAOiC,IAAI,CAAC;YACd;QACF;QAEA,IAAIZ,YAAY,CAACmB,qBAAqB;YACpCxC,OAAOiC,IAAI,CAAC,CAAC,mBAAmB,EAAEZ,SAASK,IAAI,CAAC,CAAC,CAAC;QACpD;IACF,OAAO;QACL,MAAMe,eAAehD,8BAA8BkC,IAAI,CAAC,CAACC;YACvD,MAAMc,mBAAmBd,KAAKlC,UAAU,CAACiC,IAAI,CAAC,CAACG,MAAQhC,KAAKyB,IAAI,CAACW,WAAW,GAAGS,QAAQ,CAACb;YACxF,MAAMc,oBAAoBhB,KAAKjC,QAAQ,KAAKG,KAAK+C,QAAQ;YACzD,OAAOH,oBAAoBE;QAC7B;QACA,IAAIH,cAAc;YAChBzC,OAAOiC,IAAI,CACT,CAAC,WAAW,EAAEnC,KAAK+C,QAAQ,CAAC,cAAc,EAAE/C,KAAKyB,IAAI,CAAC,iHAAiH,CAAC;QAE5K;IACF;IAEA,IAAIvB,OAAOe,MAAM,GAAG,GAAG;QACrBhB,IAAIsC,OAAO,CAACC,MAAM,CAACQ,KAAK,CAAC9C,OAAO+C,IAAI,CAAC;QACrC,MAAM,IAAI5D,gBAAgB;YACxBa,QAAQ;gBAAC;oBAAEmB,SAASnB,OAAO+C,IAAI,CAAC;oBAAO3B,MAAM;gBAAO;aAAE;QACxD;IACF;AACF,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"isEligibleRequest.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/isEligibleRequest.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,iBAAiB,QAAS,OAAO,KAAG,OAMhD,CAAA"}
1
+ {"version":3,"file":"isEligibleRequest.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/isEligibleRequest.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,iBAAiB,QAAS,OAAO,KAAG,OAMhD,CAAA"}
@@ -9,7 +9,8 @@ const UNACCEPTABLE_METHODS = new Set([
9
9
  'TRACE'
10
10
  ]);
11
11
  const hasBody = (req)=>{
12
- return Boolean(req.headers.get('transfer-encoding') || req.headers.get('content-length') && req.headers.get('content-length') !== '0');
12
+ const contentLength = req.headers.get('content-length');
13
+ return Boolean(req.body || req.headers.get('transfer-encoding') || contentLength && contentLength !== '0');
13
14
  };
14
15
  const hasAcceptableMethod = (req)=>!UNACCEPTABLE_METHODS.has(req.method);
15
16
  const hasAcceptableContentType = (req)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/isEligibleRequest.ts"],"sourcesContent":["// eslint-disable-next-line regexp/no-super-linear-backtracking, regexp/no-obscure-range\nconst ACCEPTABLE_CONTENT_TYPE = /multipart\\/['\"()+-_]+(?:; ?['\"()+-_]*)+$/i\nconst UNACCEPTABLE_METHODS = new Set(['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'TRACE'])\n\nconst hasBody = (req: Request): boolean => {\n return Boolean(\n req.headers.get('transfer-encoding') ||\n (req.headers.get('content-length') && req.headers.get('content-length') !== '0'),\n )\n}\n\nconst hasAcceptableMethod = (req: Request): boolean => !UNACCEPTABLE_METHODS.has(req.method)\n\nconst hasAcceptableContentType = (req: Request): boolean => {\n const contType = req.headers.get('content-type')\n return contType!.includes('boundary=') && ACCEPTABLE_CONTENT_TYPE.test(contType!)\n}\n\nexport const isEligibleRequest = (req: Request): boolean => {\n try {\n return hasBody(req) && hasAcceptableMethod(req) && hasAcceptableContentType(req)\n } catch (ignore) {\n return false\n }\n}\n"],"names":["ACCEPTABLE_CONTENT_TYPE","UNACCEPTABLE_METHODS","Set","hasBody","req","Boolean","headers","get","hasAcceptableMethod","has","method","hasAcceptableContentType","contType","includes","test","isEligibleRequest","ignore"],"mappings":"AAAA,wFAAwF;AACxF,MAAMA,0BAA0B;AAChC,MAAMC,uBAAuB,IAAIC,IAAI;IAAC;IAAW;IAAU;IAAO;IAAQ;IAAW;CAAQ;AAE7F,MAAMC,UAAU,CAACC;IACf,OAAOC,QACLD,IAAIE,OAAO,CAACC,GAAG,CAAC,wBACbH,IAAIE,OAAO,CAACC,GAAG,CAAC,qBAAqBH,IAAIE,OAAO,CAACC,GAAG,CAAC,sBAAsB;AAElF;AAEA,MAAMC,sBAAsB,CAACJ,MAA0B,CAACH,qBAAqBQ,GAAG,CAACL,IAAIM,MAAM;AAE3F,MAAMC,2BAA2B,CAACP;IAChC,MAAMQ,WAAWR,IAAIE,OAAO,CAACC,GAAG,CAAC;IACjC,OAAOK,SAAUC,QAAQ,CAAC,gBAAgBb,wBAAwBc,IAAI,CAACF;AACzE;AAEA,OAAO,MAAMG,oBAAoB,CAACX;IAChC,IAAI;QACF,OAAOD,QAAQC,QAAQI,oBAAoBJ,QAAQO,yBAAyBP;IAC9E,EAAE,OAAOY,QAAQ;QACf,OAAO;IACT;AACF,EAAC"}
1
+ {"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/isEligibleRequest.ts"],"sourcesContent":["// eslint-disable-next-line regexp/no-super-linear-backtracking, regexp/no-obscure-range\nconst ACCEPTABLE_CONTENT_TYPE = /multipart\\/['\"()+-_]+(?:; ?['\"()+-_]*)+$/i\nconst UNACCEPTABLE_METHODS = new Set(['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'TRACE'])\n\nconst hasBody = (req: Request): boolean => {\n const contentLength = req.headers.get('content-length')\n\n return Boolean(\n req.body || req.headers.get('transfer-encoding') || (contentLength && contentLength !== '0'),\n )\n}\n\nconst hasAcceptableMethod = (req: Request): boolean => !UNACCEPTABLE_METHODS.has(req.method)\n\nconst hasAcceptableContentType = (req: Request): boolean => {\n const contType = req.headers.get('content-type')\n return contType!.includes('boundary=') && ACCEPTABLE_CONTENT_TYPE.test(contType!)\n}\n\nexport const isEligibleRequest = (req: Request): boolean => {\n try {\n return hasBody(req) && hasAcceptableMethod(req) && hasAcceptableContentType(req)\n } catch (ignore) {\n return false\n }\n}\n"],"names":["ACCEPTABLE_CONTENT_TYPE","UNACCEPTABLE_METHODS","Set","hasBody","req","contentLength","headers","get","Boolean","body","hasAcceptableMethod","has","method","hasAcceptableContentType","contType","includes","test","isEligibleRequest","ignore"],"mappings":"AAAA,wFAAwF;AACxF,MAAMA,0BAA0B;AAChC,MAAMC,uBAAuB,IAAIC,IAAI;IAAC;IAAW;IAAU;IAAO;IAAQ;IAAW;CAAQ;AAE7F,MAAMC,UAAU,CAACC;IACf,MAAMC,gBAAgBD,IAAIE,OAAO,CAACC,GAAG,CAAC;IAEtC,OAAOC,QACLJ,IAAIK,IAAI,IAAIL,IAAIE,OAAO,CAACC,GAAG,CAAC,wBAAyBF,iBAAiBA,kBAAkB;AAE5F;AAEA,MAAMK,sBAAsB,CAACN,MAA0B,CAACH,qBAAqBU,GAAG,CAACP,IAAIQ,MAAM;AAE3F,MAAMC,2BAA2B,CAACT;IAChC,MAAMU,WAAWV,IAAIE,OAAO,CAACC,GAAG,CAAC;IACjC,OAAOO,SAAUC,QAAQ,CAAC,gBAAgBf,wBAAwBgB,IAAI,CAACF;AACzE;AAEA,OAAO,MAAMG,oBAAoB,CAACb;IAChC,IAAI;QACF,OAAOD,QAAQC,QAAQM,oBAAoBN,QAAQS,yBAAyBT;IAC9E,EAAE,OAAOc,QAAQ;QACf,OAAO;IACT;AACF,EAAC"}
@@ -0,0 +1,29 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { isEligibleRequest } from './isEligibleRequest.js';
3
+ describe('isEligibleRequest', ()=>{
4
+ it('should accept multipart POST requests with a body stream when content-length is absent', ()=>{
5
+ const formData = new FormData();
6
+ formData.append('file', new Blob([
7
+ 'hello world'
8
+ ], {
9
+ type: 'text/plain'
10
+ }), 'hello.txt');
11
+ const request = new Request('http://localhost/api/upload', {
12
+ body: formData,
13
+ method: 'POST'
14
+ });
15
+ expect(request.headers.get('content-length')).toBeNull();
16
+ expect(isEligibleRequest(request)).toBe(true);
17
+ });
18
+ it('should reject multipart POST requests when no body is present', ()=>{
19
+ const request = new Request('http://localhost/api/upload', {
20
+ headers: {
21
+ 'content-type': 'multipart/form-data; boundary=----test-boundary'
22
+ },
23
+ method: 'POST'
24
+ });
25
+ expect(isEligibleRequest(request)).toBe(false);
26
+ });
27
+ });
28
+
29
+ //# sourceMappingURL=isEligibleRequest.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/isEligibleRequest.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { isEligibleRequest } from './isEligibleRequest.js'\n\ndescribe('isEligibleRequest', () => {\n it('should accept multipart POST requests with a body stream when content-length is absent', () => {\n const formData = new FormData()\n formData.append('file', new Blob(['hello world'], { type: 'text/plain' }), 'hello.txt')\n\n const request = new Request('http://localhost/api/upload', {\n body: formData,\n method: 'POST',\n })\n\n expect(request.headers.get('content-length')).toBeNull()\n expect(isEligibleRequest(request)).toBe(true)\n })\n\n it('should reject multipart POST requests when no body is present', () => {\n const request = new Request('http://localhost/api/upload', {\n headers: {\n 'content-type': 'multipart/form-data; boundary=----test-boundary',\n },\n method: 'POST',\n })\n\n expect(isEligibleRequest(request)).toBe(false)\n })\n})\n"],"names":["describe","expect","it","isEligibleRequest","formData","FormData","append","Blob","type","request","Request","body","method","headers","get","toBeNull","toBe"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,iBAAiB,QAAQ,yBAAwB;AAE1DH,SAAS,qBAAqB;IAC5BE,GAAG,0FAA0F;QAC3F,MAAME,WAAW,IAAIC;QACrBD,SAASE,MAAM,CAAC,QAAQ,IAAIC,KAAK;YAAC;SAAc,EAAE;YAAEC,MAAM;QAAa,IAAI;QAE3E,MAAMC,UAAU,IAAIC,QAAQ,+BAA+B;YACzDC,MAAMP;YACNQ,QAAQ;QACV;QAEAX,OAAOQ,QAAQI,OAAO,CAACC,GAAG,CAAC,mBAAmBC,QAAQ;QACtDd,OAAOE,kBAAkBM,UAAUO,IAAI,CAAC;IAC1C;IAEAd,GAAG,iEAAiE;QAClE,MAAMO,UAAU,IAAIC,QAAQ,+BAA+B;YACzDG,SAAS;gBACP,gBAAgB;YAClB;YACAD,QAAQ;QACV;QAEAX,OAAOE,kBAAkBM,UAAUO,IAAI,CAAC;IAC1C;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"processMultipart.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/processMultipart.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;AAS5D,QAAA,MAAM,iBAAiB,eAAuC,CAAA;AAE9D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO;QACf,CAAC,iBAAiB,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAA;KACrC;CACF;AAED,KAAK,gBAAgB,GAAG,CAAC,IAAI,EAAE;IAC7B,OAAO,EAAE,yBAAyB,CAAA;IAClC,OAAO,EAAE,OAAO,CAAA;CACjB,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAA;AACzC,eAAO,MAAM,gBAAgB,EAAE,gBAwM9B,CAAA"}
1
+ {"version":3,"file":"processMultipart.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/processMultipart.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;AAS5D,QAAA,MAAM,iBAAiB,eAAuC,CAAA;AAE9D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO;QACf,CAAC,iBAAiB,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAA;KACrC;CACF;AAED,KAAK,gBAAgB,GAAG,CAAC,IAAI,EAAE;IAC7B,OAAO,EAAE,yBAAyB,CAAA;IAClC,OAAO,EAAE,OAAO,CAAA;CACjB,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAA;AACzC,eAAO,MAAM,gBAAgB,EAAE,gBAuN9B,CAAA"}
@@ -14,10 +14,16 @@ export const processMultipart = async ({ options, request })=>{
14
14
  let filesCompleted = 0;
15
15
  let allFilesHaveResolved;
16
16
  let failedResolvingFiles;
17
+ let busboyFinishedResolve;
18
+ let busboyFinishedReject;
17
19
  const allFilesComplete = new Promise((res, rej)=>{
18
20
  allFilesHaveResolved = res;
19
21
  failedResolvingFiles = rej;
20
22
  });
23
+ const busboyFinished = new Promise((resolve, reject)=>{
24
+ busboyFinishedResolve = resolve;
25
+ busboyFinishedReject = reject;
26
+ });
21
27
  const result = {
22
28
  fields: undefined,
23
29
  files: undefined
@@ -136,16 +142,18 @@ export const processMultipart = async ({ options, request })=>{
136
142
  debugLog(options, `Error waiting for file write promises: ${err}`);
137
143
  }
138
144
  }
139
- return result;
145
+ busboyFinishedResolve();
140
146
  });
141
147
  busboy.on('error', (err = new APIError('Busboy error parsing multipart request', httpStatus.BAD_REQUEST))=>{
142
148
  debugLog(options, `Busboy error`);
143
- throw err;
149
+ const busboyError = err instanceof Error ? err : new APIError('Busboy error parsing multipart request', httpStatus.BAD_REQUEST);
150
+ busboyFinishedReject(busboyError);
144
151
  });
145
152
  while(parsingRequest){
146
153
  const { done, value } = await reader.read();
147
154
  if (done) {
148
155
  parsingRequest = false;
156
+ busboy.end();
149
157
  }
150
158
  if (value && !shouldAbortProccessing) {
151
159
  busboy.write(value);
@@ -156,6 +164,7 @@ export const processMultipart = async ({ options, request })=>{
156
164
  throw e;
157
165
  });
158
166
  }
167
+ await busboyFinished;
159
168
  return result;
160
169
  };
161
170