@payloadcms/plugin-import-export 4.0.0-internal.5b1e7cd → 4.0.0-internal.5e065b3

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 (194) hide show
  1. package/dist/components/CollectionField/index.d.ts +3 -2
  2. package/dist/components/CollectionField/index.d.ts.map +1 -1
  3. package/dist/components/CollectionField/index.js.map +1 -1
  4. package/dist/components/ExportListMenuItem/index.d.ts.map +1 -1
  5. package/dist/components/ExportListMenuItem/index.js +14 -12
  6. package/dist/components/ExportListMenuItem/index.js.map +1 -1
  7. package/dist/components/ExportPreview/index.css +52 -0
  8. package/dist/components/ExportPreview/index.d.ts +1 -1
  9. package/dist/components/ExportPreview/index.d.ts.map +1 -1
  10. package/dist/components/ExportPreview/index.js +12 -2
  11. package/dist/components/ExportPreview/index.js.map +1 -1
  12. package/dist/components/FieldsToExport/index.d.ts +3 -2
  13. package/dist/components/FieldsToExport/index.d.ts.map +1 -1
  14. package/dist/components/FieldsToExport/index.js +18 -15
  15. package/dist/components/FieldsToExport/index.js.map +1 -1
  16. package/dist/components/FieldsToExport/reduceFields.d.ts +6 -0
  17. package/dist/components/FieldsToExport/reduceFields.d.ts.map +1 -1
  18. package/dist/components/FieldsToExport/reduceFields.js +4 -0
  19. package/dist/components/FieldsToExport/reduceFields.js.map +1 -1
  20. package/dist/components/FormatField/index.d.ts +3 -2
  21. package/dist/components/FormatField/index.d.ts.map +1 -1
  22. package/dist/components/FormatField/index.js +6 -3
  23. package/dist/components/FormatField/index.js.map +1 -1
  24. package/dist/components/ImportListMenuItem/index.d.ts.map +1 -1
  25. package/dist/components/ImportListMenuItem/index.js +14 -12
  26. package/dist/components/ImportListMenuItem/index.js.map +1 -1
  27. package/dist/components/ImportPreview/index.css +45 -0
  28. package/dist/components/ImportPreview/index.d.ts +1 -1
  29. package/dist/components/ImportPreview/index.d.ts.map +1 -1
  30. package/dist/components/ImportPreview/index.js +44 -11
  31. package/dist/components/ImportPreview/index.js.map +1 -1
  32. package/dist/components/LimitField/index.d.ts +3 -2
  33. package/dist/components/LimitField/index.d.ts.map +1 -1
  34. package/dist/components/LimitField/index.js.map +1 -1
  35. package/dist/components/LocaleField/index.d.ts +3 -2
  36. package/dist/components/LocaleField/index.d.ts.map +1 -1
  37. package/dist/components/LocaleField/index.js.map +1 -1
  38. package/dist/components/Page/index.d.ts +4 -3
  39. package/dist/components/Page/index.d.ts.map +1 -1
  40. package/dist/components/Page/index.js +1 -1
  41. package/dist/components/Page/index.js.map +1 -1
  42. package/dist/components/RelationshipCell/getRelationshipGroupKey.d.ts +7 -0
  43. package/dist/components/RelationshipCell/getRelationshipGroupKey.d.ts.map +1 -0
  44. package/dist/components/RelationshipCell/getRelationshipGroupKey.js +3 -0
  45. package/dist/components/RelationshipCell/getRelationshipGroupKey.js.map +1 -0
  46. package/dist/components/RelationshipCell/getRelationshipGroups.d.ts +43 -0
  47. package/dist/components/RelationshipCell/getRelationshipGroups.d.ts.map +1 -0
  48. package/dist/components/RelationshipCell/getRelationshipGroups.js +109 -0
  49. package/dist/components/RelationshipCell/getRelationshipGroups.js.map +1 -0
  50. package/dist/components/RelationshipCell/index.css +30 -0
  51. package/dist/components/RelationshipCell/index.d.ts +15 -0
  52. package/dist/components/RelationshipCell/index.d.ts.map +1 -0
  53. package/dist/components/RelationshipCell/index.js +57 -0
  54. package/dist/components/RelationshipCell/index.js.map +1 -0
  55. package/dist/components/SortBy/index.css +9 -0
  56. package/dist/components/SortBy/index.d.ts +4 -3
  57. package/dist/components/SortBy/index.d.ts.map +1 -1
  58. package/dist/components/SortBy/index.js +1 -2
  59. package/dist/components/SortBy/index.js.map +1 -1
  60. package/dist/components/SortOrder/index.css +9 -0
  61. package/dist/components/SortOrder/index.d.ts +4 -3
  62. package/dist/components/SortOrder/index.d.ts.map +1 -1
  63. package/dist/components/SortOrder/index.js +1 -2
  64. package/dist/components/SortOrder/index.js.map +1 -1
  65. package/dist/export/batchProcessor.d.ts +12 -3
  66. package/dist/export/batchProcessor.d.ts.map +1 -1
  67. package/dist/export/batchProcessor.js +61 -15
  68. package/dist/export/batchProcessor.js.map +1 -1
  69. package/dist/export/createExport.d.ts +4 -2
  70. package/dist/export/createExport.d.ts.map +1 -1
  71. package/dist/export/createExport.js +105 -22
  72. package/dist/export/createExport.js.map +1 -1
  73. package/dist/export/getCreateExportCollectionTask.d.ts.map +1 -1
  74. package/dist/export/getCreateExportCollectionTask.js +11 -0
  75. package/dist/export/getCreateExportCollectionTask.js.map +1 -1
  76. package/dist/export/getExportCollection.d.ts.map +1 -1
  77. package/dist/export/getExportCollection.js +9 -4
  78. package/dist/export/getExportCollection.js.map +1 -1
  79. package/dist/export/handleDownload.d.ts.map +1 -1
  80. package/dist/export/handleDownload.js +7 -3
  81. package/dist/export/handleDownload.js.map +1 -1
  82. package/dist/export/handlePreview.d.ts.map +1 -1
  83. package/dist/export/handlePreview.js +60 -16
  84. package/dist/export/handlePreview.js.map +1 -1
  85. package/dist/exports/types.d.ts +1 -1
  86. package/dist/exports/types.d.ts.map +1 -1
  87. package/dist/exports/types.js.map +1 -1
  88. package/dist/import/batchProcessor.d.ts +17 -4
  89. package/dist/import/batchProcessor.d.ts.map +1 -1
  90. package/dist/import/batchProcessor.js +63 -34
  91. package/dist/import/batchProcessor.js.map +1 -1
  92. package/dist/import/createImport.d.ts +3 -11
  93. package/dist/import/createImport.d.ts.map +1 -1
  94. package/dist/import/createImport.js +42 -54
  95. package/dist/import/createImport.js.map +1 -1
  96. package/dist/import/getCreateImportCollectionTask.d.ts.map +1 -1
  97. package/dist/import/getCreateImportCollectionTask.js +5 -2
  98. package/dist/import/getCreateImportCollectionTask.js.map +1 -1
  99. package/dist/import/getImportCollection.d.ts.map +1 -1
  100. package/dist/import/getImportCollection.js +6 -4
  101. package/dist/import/getImportCollection.js.map +1 -1
  102. package/dist/import/handlePreview.d.ts.map +1 -1
  103. package/dist/import/handlePreview.js +37 -7
  104. package/dist/import/handlePreview.js.map +1 -1
  105. package/dist/index.d.ts +51 -7
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +36 -8
  108. package/dist/index.js.map +1 -1
  109. package/dist/translations/languages/en.d.ts.map +1 -1
  110. package/dist/types.d.ts +205 -42
  111. package/dist/types.d.ts.map +1 -1
  112. package/dist/types.js.map +1 -1
  113. package/dist/utilities/applyFieldHooks.d.ts +22 -0
  114. package/dist/utilities/applyFieldHooks.d.ts.map +1 -0
  115. package/dist/utilities/applyFieldHooks.js +117 -0
  116. package/dist/utilities/applyFieldHooks.js.map +1 -0
  117. package/dist/utilities/collectDisabledFieldPaths.d.ts.map +1 -1
  118. package/dist/utilities/collectDisabledFieldPaths.js +1 -1
  119. package/dist/utilities/collectDisabledFieldPaths.js.map +1 -1
  120. package/dist/utilities/flattenObject.d.ts +8 -6
  121. package/dist/utilities/flattenObject.d.ts.map +1 -1
  122. package/dist/utilities/flattenObject.js +85 -75
  123. package/dist/utilities/flattenObject.js.map +1 -1
  124. package/dist/utilities/flattenedFields.d.ts +21 -0
  125. package/dist/utilities/flattenedFields.d.ts.map +1 -0
  126. package/dist/utilities/flattenedFields.js +37 -0
  127. package/dist/utilities/flattenedFields.js.map +1 -0
  128. package/dist/utilities/getExportFieldFunctions.d.ts +5 -5
  129. package/dist/utilities/getExportFieldFunctions.d.ts.map +1 -1
  130. package/dist/utilities/getExportFieldFunctions.js +122 -99
  131. package/dist/utilities/getExportFieldFunctions.js.map +1 -1
  132. package/dist/utilities/getFileFromDoc.js +3 -3
  133. package/dist/utilities/getFileFromDoc.js.map +1 -1
  134. package/dist/utilities/getImportFieldFunctions.d.ts +5 -5
  135. package/dist/utilities/getImportFieldFunctions.d.ts.map +1 -1
  136. package/dist/utilities/getImportFieldFunctions.js +95 -103
  137. package/dist/utilities/getImportFieldFunctions.js.map +1 -1
  138. package/dist/utilities/getSchemaColumns.d.ts +1 -1
  139. package/dist/utilities/getSchemaColumns.js +2 -2
  140. package/dist/utilities/getSchemaColumns.js.map +1 -1
  141. package/dist/utilities/getSelect.d.ts.map +1 -1
  142. package/dist/utilities/getSelect.js +11 -3
  143. package/dist/utilities/getSelect.js.map +1 -1
  144. package/dist/utilities/getSubmittedFormValues.d.ts +12 -0
  145. package/dist/utilities/getSubmittedFormValues.d.ts.map +1 -0
  146. package/dist/utilities/getSubmittedFormValues.js +24 -0
  147. package/dist/utilities/getSubmittedFormValues.js.map +1 -0
  148. package/dist/utilities/isPlainObject.d.ts +2 -0
  149. package/dist/utilities/isPlainObject.d.ts.map +1 -0
  150. package/dist/utilities/isPlainObject.js +3 -0
  151. package/dist/utilities/isPlainObject.js.map +1 -0
  152. package/dist/utilities/polymorphicRel.d.ts +14 -0
  153. package/dist/utilities/polymorphicRel.d.ts.map +1 -0
  154. package/dist/utilities/polymorphicRel.js +17 -0
  155. package/dist/utilities/polymorphicRel.js.map +1 -0
  156. package/dist/utilities/processRichTextField.d.ts.map +1 -1
  157. package/dist/utilities/processRichTextField.js +7 -0
  158. package/dist/utilities/processRichTextField.js.map +1 -1
  159. package/dist/utilities/removeDisabledFields.js.map +1 -1
  160. package/dist/utilities/setNestedValue.d.ts +2 -1
  161. package/dist/utilities/setNestedValue.d.ts.map +1 -1
  162. package/dist/utilities/setNestedValue.js +65 -32
  163. package/dist/utilities/setNestedValue.js.map +1 -1
  164. package/dist/utilities/sortHelpers.d.ts +1 -1
  165. package/dist/utilities/unflattenObject.d.ts +4 -3
  166. package/dist/utilities/unflattenObject.d.ts.map +1 -1
  167. package/dist/utilities/unflattenObject.js +69 -170
  168. package/dist/utilities/unflattenObject.js.map +1 -1
  169. package/dist/utilities/unflattenPostProcess.d.ts +11 -0
  170. package/dist/utilities/unflattenPostProcess.d.ts.map +1 -0
  171. package/dist/utilities/unflattenPostProcess.js +174 -0
  172. package/dist/utilities/unflattenPostProcess.js.map +1 -0
  173. package/license.md +1 -1
  174. package/package.json +9 -9
  175. package/dist/components/ExportPreview/index.scss +0 -48
  176. package/dist/components/FieldsToExport/index.scss +0 -0
  177. package/dist/components/FieldsToExport/reduceFields.spec.js +0 -239
  178. package/dist/components/FieldsToExport/reduceFields.spec.js.map +0 -1
  179. package/dist/components/ImportPreview/index.scss +0 -41
  180. package/dist/components/SortBy/index.scss +0 -3
  181. package/dist/components/SortOrder/index.scss +0 -3
  182. package/dist/utilities/buildDisabledFieldRegex.spec.js +0 -64
  183. package/dist/utilities/buildDisabledFieldRegex.spec.js.map +0 -1
  184. package/dist/utilities/fieldToRegex.spec.js +0 -151
  185. package/dist/utilities/fieldToRegex.spec.js.map +0 -1
  186. package/dist/utilities/filterToSelectedFields.spec.js +0 -204
  187. package/dist/utilities/filterToSelectedFields.spec.js.map +0 -1
  188. package/dist/utilities/getSchemaColumns.spec.js +0 -157
  189. package/dist/utilities/getSchemaColumns.spec.js.map +0 -1
  190. package/dist/utilities/parseCSV.spec.js +0 -195
  191. package/dist/utilities/parseCSV.spec.js.map +0 -1
  192. package/dist/utilities/unflattenObject.spec.js +0 -680
  193. package/dist/utilities/unflattenObject.spec.js.map +0 -1
  194. /package/dist/components/Page/{index.scss → index.css} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/export/getExportCollection.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionBeforeOperationHook,\n CollectionConfig,\n Config,\n} from 'payload'\n\nimport type { ExportConfig, ImportExportPluginConfig, Limit } from '../types.js'\nimport type { Export } from './createExport.js'\n\nimport { resolveLimit } from '../utilities/resolveLimit.js'\nimport { createExport } from './createExport.js'\nimport { getFields } from './getFields.js'\nimport { handleDownload } from './handleDownload.js'\nimport { handlePreview } from './handlePreview.js'\n\nconst FALLBACK_BATCH_SIZE = 100\n\nexport const getExportCollection = ({\n collectionSlugs,\n config,\n exportConfig,\n pluginConfig,\n}: {\n /**\n * Collection slugs that this export collection supports.\n */\n collectionSlugs: string[]\n config: Config\n exportConfig?: ExportConfig\n pluginConfig: ImportExportPluginConfig\n}): CollectionConfig => {\n const beforeOperation: CollectionBeforeOperationHook[] = []\n const afterChange: CollectionAfterChangeHook[] = []\n\n const disableDownload = exportConfig?.disableDownload ?? false\n const disableSave = exportConfig?.disableSave ?? false\n const format = exportConfig?.format\n\n const collection: CollectionConfig = {\n slug: 'exports',\n access: {\n update: () => false,\n },\n admin: {\n components: {\n edit: {\n SaveButton: '@payloadcms/plugin-import-export/rsc#ExportSaveButton',\n },\n },\n custom: {\n disableDownload,\n disableSave,\n format,\n 'plugin-import-export': {\n collectionSlugs,\n },\n },\n disableCopyToLocale: true,\n group: false,\n useAsTitle: 'name',\n },\n disableDuplicate: true,\n endpoints: [\n {\n handler: (req) => handleDownload(req, pluginConfig.debug),\n method: 'post',\n path: '/download',\n },\n {\n handler: handlePreview,\n method: 'post',\n path: '/export-preview',\n },\n ],\n fields: getFields({ collectionSlugs, config, format }),\n hooks: {\n afterChange,\n beforeOperation,\n },\n lockDocuments: false,\n upload: {\n filesRequiredOnCreate: false,\n hideFileInputOnCreate: true,\n hideRemoveFile: true,\n },\n }\n\n // Synchronous export hook - runs when target collection has disableJobsQueue enabled\n beforeOperation.push(async ({ args, collection: collectionConfig, operation, req }) => {\n if (operation !== 'create') {\n return\n }\n\n const exportData = args.data as Export\n const targetCollection = req.payload.collections[exportData.collectionSlug]\n const targetPluginConfig = targetCollection?.config.custom?.['plugin-import-export']\n\n // Check if this target collection should use sync mode\n // Fall back to exportConfig (for custom collections with overrideCollection)\n const disableJobsQueue =\n targetPluginConfig?.exportDisableJobsQueue ?? exportConfig?.disableJobsQueue ?? false\n if (!disableJobsQueue) {\n return\n }\n\n const { user } = req\n const debug = pluginConfig.debug\n\n const exportLimitConfig: Limit | undefined = targetPluginConfig?.exportLimit\n const maxLimit = await resolveLimit({\n limit: exportLimitConfig,\n req,\n })\n\n const batchSize =\n targetPluginConfig?.exportBatchSize ??\n exportConfig?.batchSize ??\n pluginConfig.batchSize ??\n FALLBACK_BATCH_SIZE\n\n await createExport({\n ...exportData,\n batchSize,\n debug,\n exportCollection: collectionConfig.slug,\n maxLimit,\n req,\n userCollection: user?.collection || user?.user?.collection,\n userID: user?.id || user?.user?.id,\n })\n })\n\n afterChange.push(async ({ collection: collectionConfig, doc, operation, req }) => {\n if (operation !== 'create') {\n return\n }\n\n const targetCollection = req.payload.collections[doc.collectionSlug]\n const targetPluginConfig = targetCollection?.config.custom?.['plugin-import-export']\n const disableJobsQueue =\n targetPluginConfig?.exportDisableJobsQueue ?? exportConfig?.disableJobsQueue ?? false\n if (disableJobsQueue) {\n return\n }\n\n const { user } = req\n\n // Get max limit from the target collection's config\n // For job-based exports, we resolve the limit now since function limits\n // cannot be serialized. This means dynamic limits are resolved at queue time.\n const exportLimitConfig: Limit | undefined = targetPluginConfig?.exportLimit\n const maxLimit = await resolveLimit({\n limit: exportLimitConfig,\n req,\n })\n\n const batchSize =\n targetPluginConfig?.exportBatchSize ??\n exportConfig?.batchSize ??\n pluginConfig.batchSize ??\n FALLBACK_BATCH_SIZE\n\n const input: Export = {\n id: doc.id,\n name: doc.name,\n batchSize,\n collectionSlug: doc.collectionSlug,\n drafts: doc.drafts,\n exportCollection: collectionConfig.slug,\n fields: doc.fields,\n format: doc.format,\n limit: doc.limit,\n locale: doc.locale,\n maxLimit,\n page: doc.page,\n sort: doc.sort,\n userCollection: user?.collection || user?.user?.collection,\n userID: user?.id || user?.user?.id,\n where: doc.where,\n }\n\n await req.payload.jobs.queue({\n input,\n task: 'createCollectionExport',\n })\n })\n\n return collection\n}\n"],"names":["resolveLimit","createExport","getFields","handleDownload","handlePreview","FALLBACK_BATCH_SIZE","getExportCollection","collectionSlugs","config","exportConfig","pluginConfig","beforeOperation","afterChange","disableDownload","disableSave","format","collection","slug","access","update","admin","components","edit","SaveButton","custom","disableCopyToLocale","group","useAsTitle","disableDuplicate","endpoints","handler","req","debug","method","path","fields","hooks","lockDocuments","upload","filesRequiredOnCreate","hideFileInputOnCreate","hideRemoveFile","push","args","collectionConfig","operation","exportData","data","targetCollection","payload","collections","collectionSlug","targetPluginConfig","disableJobsQueue","exportDisableJobsQueue","user","exportLimitConfig","exportLimit","maxLimit","limit","batchSize","exportBatchSize","exportCollection","userCollection","userID","id","doc","input","name","drafts","locale","page","sort","where","jobs","queue","task"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/export/getExportCollection.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionBeforeOperationHook,\n CollectionConfig,\n Config,\n} from 'payload'\n\nimport type { ExportConfig, ImportExportPluginConfig, Limit } from '../types.js'\nimport type { Export } from './createExport.js'\n\nimport { getSubmittedFormValues } from '../utilities/getSubmittedFormValues.js'\nimport { resolveLimit } from '../utilities/resolveLimit.js'\nimport { createExport } from './createExport.js'\nimport { getFields } from './getFields.js'\nimport { handleDownload } from './handleDownload.js'\nimport { handlePreview } from './handlePreview.js'\n\nconst FALLBACK_BATCH_SIZE = 100\n\nexport const getExportCollection = ({\n collectionSlugs,\n config,\n exportConfig,\n pluginConfig,\n}: {\n /**\n * Collection slugs that this export collection supports.\n */\n collectionSlugs: string[]\n config: Config\n exportConfig?: ExportConfig\n pluginConfig: ImportExportPluginConfig\n}): CollectionConfig => {\n const beforeOperation: CollectionBeforeOperationHook[] = []\n const afterChange: CollectionAfterChangeHook[] = []\n\n const disableDownload = exportConfig?.disableDownload ?? false\n const disableSave = exportConfig?.disableSave ?? false\n const format = exportConfig?.format\n\n const collection: CollectionConfig = {\n slug: 'exports',\n access: {\n update: () => false,\n },\n admin: {\n components: {\n edit: {\n SaveButton: '@payloadcms/plugin-import-export/rsc#ExportSaveButton',\n },\n },\n custom: {\n disableDownload,\n disableSave,\n format,\n 'plugin-import-export': {\n collectionSlugs,\n },\n },\n disableCopyToLocale: true,\n group: false,\n useAsTitle: 'name',\n },\n disableDuplicate: true,\n endpoints: [\n {\n handler: (req) => handleDownload(req, pluginConfig.debug),\n method: 'post',\n path: '/download',\n },\n {\n handler: handlePreview,\n method: 'post',\n path: '/export-preview',\n },\n ],\n fields: getFields({ collectionSlugs, config, format }),\n hooks: {\n afterChange,\n beforeOperation,\n },\n lockDocuments: false,\n upload: {\n filesRequiredOnCreate: false,\n hideFileInputOnCreate: true,\n hideRemoveFile: true,\n },\n }\n\n // Synchronous export hook - runs when target collection has disableJobsQueue enabled\n beforeOperation.push(async ({ args, collection: collectionConfig, operation, req }) => {\n if (operation !== 'create') {\n return\n }\n\n const exportData = args.data as Export\n const targetCollection = req.payload.collections[exportData.collectionSlug]\n const targetPluginConfig = targetCollection?.config.custom?.['plugin-import-export']\n\n // Check if this target collection should use sync mode\n // Fall back to exportConfig (for custom collections with overrideCollection)\n const disableJobsQueue =\n targetPluginConfig?.exportDisableJobsQueue ?? exportConfig?.disableJobsQueue ?? false\n if (!disableJobsQueue) {\n return\n }\n\n const { user } = req\n const debug = pluginConfig.debug\n\n const exportLimitConfig: Limit | undefined = targetPluginConfig?.exportLimit\n const maxLimit = await resolveLimit({\n limit: exportLimitConfig,\n req,\n })\n\n const batchSize =\n targetPluginConfig?.exportBatchSize ??\n exportConfig?.batchSize ??\n pluginConfig.batchSize ??\n FALLBACK_BATCH_SIZE\n\n await createExport({\n ...exportData,\n batchSize,\n debug,\n exportCollection: collectionConfig.slug,\n exportDoc: getSubmittedFormValues({ formData: exportData }),\n maxLimit,\n req,\n userCollection: user?.collection,\n userID: user?.id,\n })\n })\n\n afterChange.push(async ({ collection: collectionConfig, doc, operation, req }) => {\n if (operation !== 'create') {\n return\n }\n\n const targetCollection = req.payload.collections[doc.collectionSlug]\n const targetPluginConfig = targetCollection?.config.custom?.['plugin-import-export']\n const disableJobsQueue =\n targetPluginConfig?.exportDisableJobsQueue ?? exportConfig?.disableJobsQueue ?? false\n if (disableJobsQueue) {\n return\n }\n\n const { user } = req\n\n // Get max limit from the target collection's config\n // For job-based exports, we resolve the limit now since function limits\n // cannot be serialized. This means dynamic limits are resolved at queue time.\n const exportLimitConfig: Limit | undefined = targetPluginConfig?.exportLimit\n const maxLimit = await resolveLimit({\n limit: exportLimitConfig,\n req,\n })\n\n const batchSize =\n targetPluginConfig?.exportBatchSize ??\n exportConfig?.batchSize ??\n pluginConfig.batchSize ??\n FALLBACK_BATCH_SIZE\n\n const input: Export = {\n id: doc.id,\n name: doc.name,\n batchSize,\n collectionSlug: doc.collectionSlug,\n drafts: doc.drafts,\n exportCollection: collectionConfig.slug,\n fields: doc.fields,\n format: doc.format,\n limit: doc.limit,\n locale: doc.locale,\n maxLimit,\n page: doc.page,\n sort: doc.sort,\n userCollection: user?.collection,\n userID: user?.id,\n where: doc.where,\n }\n\n await req.payload.jobs.queue({\n input,\n overrideAccess: true,\n task: 'createCollectionExport',\n })\n })\n\n return collection\n}\n"],"names":["getSubmittedFormValues","resolveLimit","createExport","getFields","handleDownload","handlePreview","FALLBACK_BATCH_SIZE","getExportCollection","collectionSlugs","config","exportConfig","pluginConfig","beforeOperation","afterChange","disableDownload","disableSave","format","collection","slug","access","update","admin","components","edit","SaveButton","custom","disableCopyToLocale","group","useAsTitle","disableDuplicate","endpoints","handler","req","debug","method","path","fields","hooks","lockDocuments","upload","filesRequiredOnCreate","hideFileInputOnCreate","hideRemoveFile","push","args","collectionConfig","operation","exportData","data","targetCollection","payload","collections","collectionSlug","targetPluginConfig","disableJobsQueue","exportDisableJobsQueue","user","exportLimitConfig","exportLimit","maxLimit","limit","batchSize","exportBatchSize","exportCollection","exportDoc","formData","userCollection","userID","id","doc","input","name","drafts","locale","page","sort","where","jobs","queue","overrideAccess","task"],"mappings":"AAUA,SAASA,sBAAsB,QAAQ,yCAAwC;AAC/E,SAASC,YAAY,QAAQ,+BAA8B;AAC3D,SAASC,YAAY,QAAQ,oBAAmB;AAChD,SAASC,SAAS,QAAQ,iBAAgB;AAC1C,SAASC,cAAc,QAAQ,sBAAqB;AACpD,SAASC,aAAa,QAAQ,qBAAoB;AAElD,MAAMC,sBAAsB;AAE5B,OAAO,MAAMC,sBAAsB,CAAC,EAClCC,eAAe,EACfC,MAAM,EACNC,YAAY,EACZC,YAAY,EASb;IACC,MAAMC,kBAAmD,EAAE;IAC3D,MAAMC,cAA2C,EAAE;IAEnD,MAAMC,kBAAkBJ,cAAcI,mBAAmB;IACzD,MAAMC,cAAcL,cAAcK,eAAe;IACjD,MAAMC,SAASN,cAAcM;IAE7B,MAAMC,aAA+B;QACnCC,MAAM;QACNC,QAAQ;YACNC,QAAQ,IAAM;QAChB;QACAC,OAAO;YACLC,YAAY;gBACVC,MAAM;oBACJC,YAAY;gBACd;YACF;YACAC,QAAQ;gBACNX;gBACAC;gBACAC;gBACA,wBAAwB;oBACtBR;gBACF;YACF;YACAkB,qBAAqB;YACrBC,OAAO;YACPC,YAAY;QACd;QACAC,kBAAkB;QAClBC,WAAW;YACT;gBACEC,SAAS,CAACC,MAAQ5B,eAAe4B,KAAKrB,aAAasB,KAAK;gBACxDC,QAAQ;gBACRC,MAAM;YACR;YACA;gBACEJ,SAAS1B;gBACT6B,QAAQ;gBACRC,MAAM;YACR;SACD;QACDC,QAAQjC,UAAU;YAAEK;YAAiBC;YAAQO;QAAO;QACpDqB,OAAO;YACLxB;YACAD;QACF;QACA0B,eAAe;QACfC,QAAQ;YACNC,uBAAuB;YACvBC,uBAAuB;YACvBC,gBAAgB;QAClB;IACF;IAEA,qFAAqF;IACrF9B,gBAAgB+B,IAAI,CAAC,OAAO,EAAEC,IAAI,EAAE3B,YAAY4B,gBAAgB,EAAEC,SAAS,EAAEd,GAAG,EAAE;QAChF,IAAIc,cAAc,UAAU;YAC1B;QACF;QAEA,MAAMC,aAAaH,KAAKI,IAAI;QAC5B,MAAMC,mBAAmBjB,IAAIkB,OAAO,CAACC,WAAW,CAACJ,WAAWK,cAAc,CAAC;QAC3E,MAAMC,qBAAqBJ,kBAAkBxC,OAAOgB,QAAQ,CAAC,uBAAuB;QAEpF,uDAAuD;QACvD,6EAA6E;QAC7E,MAAM6B,mBACJD,oBAAoBE,0BAA0B7C,cAAc4C,oBAAoB;QAClF,IAAI,CAACA,kBAAkB;YACrB;QACF;QAEA,MAAM,EAAEE,IAAI,EAAE,GAAGxB;QACjB,MAAMC,QAAQtB,aAAasB,KAAK;QAEhC,MAAMwB,oBAAuCJ,oBAAoBK;QACjE,MAAMC,WAAW,MAAM1D,aAAa;YAClC2D,OAAOH;YACPzB;QACF;QAEA,MAAM6B,YACJR,oBAAoBS,mBACpBpD,cAAcmD,aACdlD,aAAakD,SAAS,IACtBvD;QAEF,MAAMJ,aAAa;YACjB,GAAG6C,UAAU;YACbc;YACA5B;YACA8B,kBAAkBlB,iBAAiB3B,IAAI;YACvC8C,WAAWhE,uBAAuB;gBAAEiE,UAAUlB;YAAW;YACzDY;YACA3B;YACAkC,gBAAgBV,MAAMvC;YACtBkD,QAAQX,MAAMY;QAChB;IACF;IAEAvD,YAAY8B,IAAI,CAAC,OAAO,EAAE1B,YAAY4B,gBAAgB,EAAEwB,GAAG,EAAEvB,SAAS,EAAEd,GAAG,EAAE;QAC3E,IAAIc,cAAc,UAAU;YAC1B;QACF;QAEA,MAAMG,mBAAmBjB,IAAIkB,OAAO,CAACC,WAAW,CAACkB,IAAIjB,cAAc,CAAC;QACpE,MAAMC,qBAAqBJ,kBAAkBxC,OAAOgB,QAAQ,CAAC,uBAAuB;QACpF,MAAM6B,mBACJD,oBAAoBE,0BAA0B7C,cAAc4C,oBAAoB;QAClF,IAAIA,kBAAkB;YACpB;QACF;QAEA,MAAM,EAAEE,IAAI,EAAE,GAAGxB;QAEjB,oDAAoD;QACpD,wEAAwE;QACxE,8EAA8E;QAC9E,MAAMyB,oBAAuCJ,oBAAoBK;QACjE,MAAMC,WAAW,MAAM1D,aAAa;YAClC2D,OAAOH;YACPzB;QACF;QAEA,MAAM6B,YACJR,oBAAoBS,mBACpBpD,cAAcmD,aACdlD,aAAakD,SAAS,IACtBvD;QAEF,MAAMgE,QAAgB;YACpBF,IAAIC,IAAID,EAAE;YACVG,MAAMF,IAAIE,IAAI;YACdV;YACAT,gBAAgBiB,IAAIjB,cAAc;YAClCoB,QAAQH,IAAIG,MAAM;YAClBT,kBAAkBlB,iBAAiB3B,IAAI;YACvCkB,QAAQiC,IAAIjC,MAAM;YAClBpB,QAAQqD,IAAIrD,MAAM;YAClB4C,OAAOS,IAAIT,KAAK;YAChBa,QAAQJ,IAAII,MAAM;YAClBd;YACAe,MAAML,IAAIK,IAAI;YACdC,MAAMN,IAAIM,IAAI;YACdT,gBAAgBV,MAAMvC;YACtBkD,QAAQX,MAAMY;YACdQ,OAAOP,IAAIO,KAAK;QAClB;QAEA,MAAM5C,IAAIkB,OAAO,CAAC2B,IAAI,CAACC,KAAK,CAAC;YAC3BR;YACAS,gBAAgB;YAChBC,MAAM;QACR;IACF;IAEA,OAAO/D;AACT,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"handleDownload.d.ts","sourceRoot":"","sources":["../../src/export/handleDownload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAO7C,eAAO,MAAM,cAAc,QAAe,cAAc,uCA2DvD,CAAA"}
1
+ {"version":3,"file":"handleDownload.d.ts","sourceRoot":"","sources":["../../src/export/handleDownload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAU7C,eAAO,MAAM,cAAc,QAAe,cAAc,uCA6DvD,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { APIError } from 'payload';
2
+ import { getSubmittedFormValues } from '../utilities/getSubmittedFormValues.js';
2
3
  import { resolveLimit } from '../utilities/resolveLimit.js';
3
4
  import { createExport } from './createExport.js';
4
5
  export const handleDownload = async (req, debug = false)=>{
@@ -28,15 +29,18 @@ export const handleDownload = async (req, debug = false)=>{
28
29
  });
29
30
  }
30
31
  const { user } = req;
31
- body.data.userID = user?.id || user?.user?.id;
32
- body.data.userCollection = user?.collection || user?.user?.collection;
32
+ const exportDoc = getSubmittedFormValues({
33
+ formData: body.data
34
+ });
33
35
  const res = await createExport({
34
36
  ...body.data,
35
37
  debug,
36
38
  download: true,
39
+ exportDoc,
37
40
  maxLimit,
38
41
  req,
39
- user: req.user
42
+ userCollection: user?.collection,
43
+ userID: user?.id
40
44
  });
41
45
  return res;
42
46
  } catch (err) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/export/handleDownload.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport { APIError } from 'payload'\n\nimport { resolveLimit } from '../utilities/resolveLimit.js'\nimport { createExport } from './createExport.js'\n\nexport const handleDownload = async (req: PayloadRequest, debug = false) => {\n try {\n let body\n\n if (typeof req?.json === 'function') {\n body = await req.json()\n }\n\n if (!body || !body.data) {\n throw new APIError('Request data is required.')\n }\n\n const { collectionSlug, format } = body.data || {}\n\n req.payload.logger.info(`Download request received ${collectionSlug}`)\n\n const targetCollection = req.payload.collections[collectionSlug]\n let maxLimit: number | undefined\n\n if (targetCollection) {\n const adminPluginConfig = targetCollection.config.admin?.custom?.['plugin-import-export']\n const pluginConfig = targetCollection.config.custom?.['plugin-import-export']\n\n const forcedFormat = adminPluginConfig?.exportFormat\n if (forcedFormat && format && format !== forcedFormat) {\n throw new APIError(\n `Export format '${format}' is not supported for collection '${collectionSlug}'. Only '${forcedFormat}' format is allowed.`,\n )\n }\n\n // Resolve max limit from the collection config\n maxLimit = await resolveLimit({\n limit: pluginConfig?.exportLimit,\n req,\n })\n }\n\n const { user } = req\n\n body.data.userID = user?.id || user?.user?.id\n body.data.userCollection = user?.collection || user?.user?.collection\n\n const res = await createExport({\n ...body.data,\n debug,\n download: true,\n maxLimit,\n req,\n user: req.user,\n })\n\n return res as Response\n } catch (err) {\n // Return JSON for front-end toast\n return new Response(\n JSON.stringify({ errors: [{ message: (err as Error).message || 'Something went wrong' }] }),\n { headers: { 'Content-Type': 'application/json' }, status: 400 },\n )\n }\n}\n"],"names":["APIError","resolveLimit","createExport","handleDownload","req","debug","body","json","data","collectionSlug","format","payload","logger","info","targetCollection","collections","maxLimit","adminPluginConfig","config","admin","custom","pluginConfig","forcedFormat","exportFormat","limit","exportLimit","user","userID","id","userCollection","collection","res","download","err","Response","JSON","stringify","errors","message","headers","status"],"mappings":"AAEA,SAASA,QAAQ,QAAQ,UAAS;AAElC,SAASC,YAAY,QAAQ,+BAA8B;AAC3D,SAASC,YAAY,QAAQ,oBAAmB;AAEhD,OAAO,MAAMC,iBAAiB,OAAOC,KAAqBC,QAAQ,KAAK;IACrE,IAAI;QACF,IAAIC;QAEJ,IAAI,OAAOF,KAAKG,SAAS,YAAY;YACnCD,OAAO,MAAMF,IAAIG,IAAI;QACvB;QAEA,IAAI,CAACD,QAAQ,CAACA,KAAKE,IAAI,EAAE;YACvB,MAAM,IAAIR,SAAS;QACrB;QAEA,MAAM,EAAES,cAAc,EAAEC,MAAM,EAAE,GAAGJ,KAAKE,IAAI,IAAI,CAAC;QAEjDJ,IAAIO,OAAO,CAACC,MAAM,CAACC,IAAI,CAAC,CAAC,0BAA0B,EAAEJ,gBAAgB;QAErE,MAAMK,mBAAmBV,IAAIO,OAAO,CAACI,WAAW,CAACN,eAAe;QAChE,IAAIO;QAEJ,IAAIF,kBAAkB;YACpB,MAAMG,oBAAoBH,iBAAiBI,MAAM,CAACC,KAAK,EAAEC,QAAQ,CAAC,uBAAuB;YACzF,MAAMC,eAAeP,iBAAiBI,MAAM,CAACE,MAAM,EAAE,CAAC,uBAAuB;YAE7E,MAAME,eAAeL,mBAAmBM;YACxC,IAAID,gBAAgBZ,UAAUA,WAAWY,cAAc;gBACrD,MAAM,IAAItB,SACR,CAAC,eAAe,EAAEU,OAAO,mCAAmC,EAAED,eAAe,SAAS,EAAEa,aAAa,oBAAoB,CAAC;YAE9H;YAEA,+CAA+C;YAC/CN,WAAW,MAAMf,aAAa;gBAC5BuB,OAAOH,cAAcI;gBACrBrB;YACF;QACF;QAEA,MAAM,EAAEsB,IAAI,EAAE,GAAGtB;QAEjBE,KAAKE,IAAI,CAACmB,MAAM,GAAGD,MAAME,MAAMF,MAAMA,MAAME;QAC3CtB,KAAKE,IAAI,CAACqB,cAAc,GAAGH,MAAMI,cAAcJ,MAAMA,MAAMI;QAE3D,MAAMC,MAAM,MAAM7B,aAAa;YAC7B,GAAGI,KAAKE,IAAI;YACZH;YACA2B,UAAU;YACVhB;YACAZ;YACAsB,MAAMtB,IAAIsB,IAAI;QAChB;QAEA,OAAOK;IACT,EAAE,OAAOE,KAAK;QACZ,kCAAkC;QAClC,OAAO,IAAIC,SACTC,KAAKC,SAAS,CAAC;YAAEC,QAAQ;gBAAC;oBAAEC,SAAS,AAACL,IAAcK,OAAO,IAAI;gBAAuB;aAAE;QAAC,IACzF;YAAEC,SAAS;gBAAE,gBAAgB;YAAmB;YAAGC,QAAQ;QAAI;IAEnE;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/export/handleDownload.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport { APIError } from 'payload'\n\nimport type { ExportDoc } from '../types.js'\n\nimport { getSubmittedFormValues } from '../utilities/getSubmittedFormValues.js'\nimport { resolveLimit } from '../utilities/resolveLimit.js'\nimport { createExport } from './createExport.js'\n\nexport const handleDownload = async (req: PayloadRequest, debug = false) => {\n try {\n let body\n\n if (typeof req?.json === 'function') {\n body = await req.json()\n }\n\n if (!body || !body.data) {\n throw new APIError('Request data is required.')\n }\n\n const { collectionSlug, format } = body.data || {}\n\n req.payload.logger.info(`Download request received ${collectionSlug}`)\n\n const targetCollection = req.payload.collections[collectionSlug]\n let maxLimit: number | undefined\n\n if (targetCollection) {\n const adminPluginConfig = targetCollection.config.admin?.custom?.['plugin-import-export']\n const pluginConfig = targetCollection.config.custom?.['plugin-import-export']\n\n const forcedFormat = adminPluginConfig?.exportFormat\n if (forcedFormat && format && format !== forcedFormat) {\n throw new APIError(\n `Export format '${format}' is not supported for collection '${collectionSlug}'. Only '${forcedFormat}' format is allowed.`,\n )\n }\n\n // Resolve max limit from the collection config\n maxLimit = await resolveLimit({\n limit: pluginConfig?.exportLimit,\n req,\n })\n }\n\n const { user } = req\n const exportDoc = getSubmittedFormValues({\n formData: body.data as Record<string, unknown>,\n }) as ExportDoc\n\n const res = await createExport({\n ...body.data,\n debug,\n download: true,\n exportDoc,\n maxLimit,\n req,\n userCollection: user?.collection,\n userID: user?.id,\n })\n\n return res as Response\n } catch (err) {\n // Return JSON for front-end toast\n return new Response(\n JSON.stringify({ errors: [{ message: (err as Error).message || 'Something went wrong' }] }),\n { headers: { 'Content-Type': 'application/json' }, status: 400 },\n )\n }\n}\n"],"names":["APIError","getSubmittedFormValues","resolveLimit","createExport","handleDownload","req","debug","body","json","data","collectionSlug","format","payload","logger","info","targetCollection","collections","maxLimit","adminPluginConfig","config","admin","custom","pluginConfig","forcedFormat","exportFormat","limit","exportLimit","user","exportDoc","formData","res","download","userCollection","collection","userID","id","err","Response","JSON","stringify","errors","message","headers","status"],"mappings":"AAEA,SAASA,QAAQ,QAAQ,UAAS;AAIlC,SAASC,sBAAsB,QAAQ,yCAAwC;AAC/E,SAASC,YAAY,QAAQ,+BAA8B;AAC3D,SAASC,YAAY,QAAQ,oBAAmB;AAEhD,OAAO,MAAMC,iBAAiB,OAAOC,KAAqBC,QAAQ,KAAK;IACrE,IAAI;QACF,IAAIC;QAEJ,IAAI,OAAOF,KAAKG,SAAS,YAAY;YACnCD,OAAO,MAAMF,IAAIG,IAAI;QACvB;QAEA,IAAI,CAACD,QAAQ,CAACA,KAAKE,IAAI,EAAE;YACvB,MAAM,IAAIT,SAAS;QACrB;QAEA,MAAM,EAAEU,cAAc,EAAEC,MAAM,EAAE,GAAGJ,KAAKE,IAAI,IAAI,CAAC;QAEjDJ,IAAIO,OAAO,CAACC,MAAM,CAACC,IAAI,CAAC,CAAC,0BAA0B,EAAEJ,gBAAgB;QAErE,MAAMK,mBAAmBV,IAAIO,OAAO,CAACI,WAAW,CAACN,eAAe;QAChE,IAAIO;QAEJ,IAAIF,kBAAkB;YACpB,MAAMG,oBAAoBH,iBAAiBI,MAAM,CAACC,KAAK,EAAEC,QAAQ,CAAC,uBAAuB;YACzF,MAAMC,eAAeP,iBAAiBI,MAAM,CAACE,MAAM,EAAE,CAAC,uBAAuB;YAE7E,MAAME,eAAeL,mBAAmBM;YACxC,IAAID,gBAAgBZ,UAAUA,WAAWY,cAAc;gBACrD,MAAM,IAAIvB,SACR,CAAC,eAAe,EAAEW,OAAO,mCAAmC,EAAED,eAAe,SAAS,EAAEa,aAAa,oBAAoB,CAAC;YAE9H;YAEA,+CAA+C;YAC/CN,WAAW,MAAMf,aAAa;gBAC5BuB,OAAOH,cAAcI;gBACrBrB;YACF;QACF;QAEA,MAAM,EAAEsB,IAAI,EAAE,GAAGtB;QACjB,MAAMuB,YAAY3B,uBAAuB;YACvC4B,UAAUtB,KAAKE,IAAI;QACrB;QAEA,MAAMqB,MAAM,MAAM3B,aAAa;YAC7B,GAAGI,KAAKE,IAAI;YACZH;YACAyB,UAAU;YACVH;YACAX;YACAZ;YACA2B,gBAAgBL,MAAMM;YACtBC,QAAQP,MAAMQ;QAChB;QAEA,OAAOL;IACT,EAAE,OAAOM,KAAK;QACZ,kCAAkC;QAClC,OAAO,IAAIC,SACTC,KAAKC,SAAS,CAAC;YAAEC,QAAQ;gBAAC;oBAAEC,SAAS,AAACL,IAAcK,OAAO,IAAI;gBAAuB;aAAE;QAAC,IACzF;YAAEC,SAAS;gBAAE,gBAAgB;YAAmB;YAAGC,QAAQ;QAAI;IAEnE;AACF,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"handlePreview.d.ts","sourceRoot":"","sources":["../../src/export/handlePreview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,cAAc,EAAS,MAAM,SAAS,CAAA;AAsBpE,eAAO,MAAM,aAAa,QAAe,cAAc,KAAG,OAAO,CAAC,QAAQ,CAsPzE,CAAA"}
1
+ {"version":3,"file":"handlePreview.d.ts","sourceRoot":"","sources":["../../src/export/handlePreview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,SAAS,CAAA;AAqD1D,eAAO,MAAM,aAAa,QAAe,cAAc,KAAG,OAAO,CAAC,QAAQ,CA2RzE,CAAA"}
@@ -1,20 +1,39 @@
1
1
  import { addDataAndFileToRequest } from 'payload';
2
2
  import { getObjectDotNotation } from 'payload/shared';
3
3
  import { DEFAULT_PREVIEW_LIMIT, MAX_PREVIEW_LIMIT, MIN_PREVIEW_LIMIT, MIN_PREVIEW_PAGE } from '../constants.js';
4
+ import { applyFieldHooks } from '../utilities/applyFieldHooks.js';
4
5
  import { flattenObject } from '../utilities/flattenObject.js';
5
6
  import { getExportFieldFunctions } from '../utilities/getExportFieldFunctions.js';
6
7
  import { getFlattenedFieldKeys } from '../utilities/getFlattenedFieldKeys.js';
7
8
  import { getSchemaColumns, mergeColumns } from '../utilities/getSchemaColumns.js';
8
9
  import { getSelect } from '../utilities/getSelect.js';
10
+ import { getSubmittedFormValues } from '../utilities/getSubmittedFormValues.js';
9
11
  import { removeDisabledFields } from '../utilities/removeDisabledFields.js';
10
12
  import { resolveLimit } from '../utilities/resolveLimit.js';
11
13
  import { setNestedValue } from '../utilities/setNestedValue.js';
14
+ const applyExportBeforeHook = async ({ data, exportDoc, format, hook, originalDocs, req })=>{
15
+ if (!hook || data.length === 0) {
16
+ return data;
17
+ }
18
+ return hook({
19
+ batchNumber: 1,
20
+ data,
21
+ exportDoc,
22
+ format,
23
+ originalData: originalDocs,
24
+ req,
25
+ totalBatches: 1
26
+ });
27
+ };
12
28
  export const handlePreview = async (req)=>{
13
29
  await addDataAndFileToRequest(req);
14
- const { collectionSlug, draft: draftFromReq, fields, limit: exportLimit, locale, previewLimit: rawPreviewLimit = DEFAULT_PREVIEW_LIMIT, previewPage: rawPreviewPage = 1, sort, where: whereFromReq = {} } = req.data;
30
+ const { collectionSlug, draft: draftFromReq, fields, formData, limit: exportLimit, locale, previewLimit: rawPreviewLimit = DEFAULT_PREVIEW_LIMIT, previewPage: rawPreviewPage = 1, sort, where: whereFromReq = {} } = req.data;
15
31
  // Validate and clamp pagination values to safe bounds
16
32
  const previewLimit = Math.max(MIN_PREVIEW_LIMIT, Math.min(rawPreviewLimit, MAX_PREVIEW_LIMIT));
17
33
  const previewPage = Math.max(MIN_PREVIEW_PAGE, rawPreviewPage);
34
+ const exportDoc = getSubmittedFormValues({
35
+ formData: formData ?? {}
36
+ });
18
37
  const targetCollection = req.payload.collections[collectionSlug];
19
38
  if (!targetCollection) {
20
39
  return Response.json({
@@ -123,22 +142,31 @@ export const handlePreview = async (req)=>{
123
142
  }
124
143
  // Transform docs based on format
125
144
  let transformed;
145
+ const exportFieldHooks = getExportFieldFunctions({
146
+ fields: targetCollection.config.flattenedFields
147
+ });
148
+ const exportHooks = targetCollection.config.custom?.['plugin-import-export']?.exportHooks;
126
149
  if (isCSV) {
127
- const toCSVFunctions = getExportFieldFunctions({
128
- fields: targetCollection.config.fields
129
- });
130
- const possibleKeys = getFlattenedFieldKeys(targetCollection.config.fields, '', {
150
+ const possibleKeys = getFlattenedFieldKeys(targetCollection.config.flattenedFields, '', {
131
151
  localeCodes
132
152
  });
133
- // Flatten docs without padding yet. This preserves the exact keys produced by toCSV hooks,
153
+ // Flatten docs without padding yet. This preserves the exact keys produced by beforeExport hooks,
134
154
  // allowing mergeColumns to detect which schema columns were replaced with derived ones.
135
155
  transformed = docs.map((doc)=>flattenObject({
136
- doc,
156
+ data: doc,
157
+ exportFieldHooks,
137
158
  fields,
138
- toCSVFunctions
159
+ format: 'csv',
160
+ req
139
161
  }));
140
- // Merge schema columns with data-discovered columns (e.g., derived columns from toCSV)
141
- // This ensures the preview headers match what the actual export will produce
162
+ transformed = await applyExportBeforeHook({
163
+ data: transformed,
164
+ exportDoc,
165
+ format: 'csv',
166
+ hook: exportHooks?.before,
167
+ originalDocs: docs,
168
+ req
169
+ });
142
170
  if (schemaColumns && transformed.length > 0) {
143
171
  const dataColumns = [];
144
172
  const seenCols = new Set();
@@ -150,7 +178,8 @@ export const handlePreview = async (req)=>{
150
178
  }
151
179
  }
152
180
  }
153
- columns = mergeColumns(schemaColumns, dataColumns);
181
+ const mergedColumns = mergeColumns(schemaColumns, dataColumns);
182
+ columns = Boolean(exportHooks?.before) && transformed.length > 0 ? mergedColumns.filter((col)=>dataColumns.includes(col)) : mergedColumns;
154
183
  }
155
184
  // Pad rows with null for missing columns (uses merged columns, not raw schema)
156
185
  if (!fields || fields.length === 0) {
@@ -165,22 +194,37 @@ export const handlePreview = async (req)=>{
165
194
  }
166
195
  } else {
167
196
  transformed = docs.map((doc)=>{
168
- let output = {
169
- ...doc
170
- };
171
- // Remove disabled fields first
197
+ // Apply field-level export hooks for JSON format
198
+ let output = applyFieldHooks({
199
+ type: 'beforeExport',
200
+ data: doc,
201
+ fieldHooks: exportFieldHooks,
202
+ fields: targetCollection.config.flattenedFields,
203
+ format: 'json',
204
+ operation: 'export',
205
+ req
206
+ });
207
+ // Remove disabled fields
172
208
  output = removeDisabledFields(output, disabledFields);
173
209
  // Then trim to selected fields only (if fields are provided)
174
210
  if (Array.isArray(fields) && fields.length > 0) {
175
211
  const trimmed = {};
176
212
  for (const key of fields){
177
213
  const value = getObjectDotNotation(output, key);
178
- setNestedValue(trimmed, key, value ?? null);
214
+ setNestedValue(trimmed, key, value ?? null, output);
179
215
  }
180
216
  output = trimmed;
181
217
  }
182
218
  return output;
183
219
  });
220
+ transformed = await applyExportBeforeHook({
221
+ data: transformed,
222
+ exportDoc,
223
+ format: 'json',
224
+ hook: exportHooks?.before,
225
+ originalDocs: docs,
226
+ req
227
+ });
184
228
  }
185
229
  const hasNextPage = previewPage < previewTotalPages;
186
230
  const hasPrevPage = previewPage > 1;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/export/handlePreview.ts"],"sourcesContent":["import type { FlattenedField, PayloadRequest, Where } from 'payload'\n\nimport { addDataAndFileToRequest } from 'payload'\nimport { getObjectDotNotation } from 'payload/shared'\n\nimport type { ExportPreviewResponse } from '../types.js'\n\nimport {\n DEFAULT_PREVIEW_LIMIT,\n MAX_PREVIEW_LIMIT,\n MIN_PREVIEW_LIMIT,\n MIN_PREVIEW_PAGE,\n} from '../constants.js'\nimport { flattenObject } from '../utilities/flattenObject.js'\nimport { getExportFieldFunctions } from '../utilities/getExportFieldFunctions.js'\nimport { getFlattenedFieldKeys } from '../utilities/getFlattenedFieldKeys.js'\nimport { getSchemaColumns, mergeColumns } from '../utilities/getSchemaColumns.js'\nimport { getSelect } from '../utilities/getSelect.js'\nimport { removeDisabledFields } from '../utilities/removeDisabledFields.js'\nimport { resolveLimit } from '../utilities/resolveLimit.js'\nimport { setNestedValue } from '../utilities/setNestedValue.js'\n\nexport const handlePreview = async (req: PayloadRequest): Promise<Response> => {\n await addDataAndFileToRequest(req)\n\n const {\n collectionSlug,\n draft: draftFromReq,\n fields,\n limit: exportLimit,\n locale,\n previewLimit: rawPreviewLimit = DEFAULT_PREVIEW_LIMIT,\n previewPage: rawPreviewPage = 1,\n sort,\n where: whereFromReq = {},\n } = req.data as {\n collectionSlug: string\n draft?: 'no' | 'yes'\n fields?: string[]\n format?: 'csv' | 'json'\n limit?: number\n locale?: string\n previewLimit?: number\n previewPage?: number\n sort?: any\n where?: any\n }\n\n // Validate and clamp pagination values to safe bounds\n const previewLimit = Math.max(MIN_PREVIEW_LIMIT, Math.min(rawPreviewLimit, MAX_PREVIEW_LIMIT))\n const previewPage = Math.max(MIN_PREVIEW_PAGE, rawPreviewPage)\n\n const targetCollection = req.payload.collections[collectionSlug]\n if (!targetCollection) {\n return Response.json(\n { error: `Collection with slug ${collectionSlug} not found` },\n { status: 400 },\n )\n }\n\n const pluginConfig = targetCollection.config.custom?.['plugin-import-export']\n const maxLimit = await resolveLimit({\n limit: pluginConfig?.exportLimit,\n req,\n })\n\n const select = Array.isArray(fields) && fields.length > 0 ? getSelect(fields) : undefined\n const draft = draftFromReq === 'yes'\n const collectionHasVersions = Boolean(targetCollection.config.versions)\n\n // Only filter by _status for versioned collections\n const publishedWhere: Where = collectionHasVersions ? { _status: { equals: 'published' } } : {}\n\n const where: Where = {\n and: [whereFromReq, draft ? {} : publishedWhere],\n }\n\n // Count total docs matching export criteria\n const countResult = await req.payload.count({\n collection: collectionSlug,\n overrideAccess: false,\n req,\n where,\n })\n\n const totalMatchingDocs = countResult.totalDocs\n\n // Calculate actual export count (respecting both export limit and max limit)\n let effectiveLimit = totalMatchingDocs\n\n // Apply user's export limit if provided\n if (exportLimit && exportLimit > 0) {\n effectiveLimit = Math.min(effectiveLimit, exportLimit)\n }\n\n // Apply max limit if configured\n if (typeof maxLimit === 'number' && maxLimit > 0) {\n effectiveLimit = Math.min(effectiveLimit, maxLimit)\n }\n\n const exportTotalDocs = effectiveLimit\n\n // Calculate preview pagination that respects export limit\n // Preview should only show docs that will actually be exported\n const previewStartIndex = (previewPage - 1) * previewLimit\n\n // Calculate pagination info based on export limit (not raw DB results)\n const previewTotalPages = exportTotalDocs === 0 ? 0 : Math.ceil(exportTotalDocs / previewLimit)\n\n const isCSV = req?.data?.format === 'csv'\n\n // Get locale codes for locale expansion when locale='all'\n const localeCodes =\n locale === 'all' && req.payload.config.localization\n ? req.payload.config.localization.localeCodes\n : undefined\n\n // Get disabled fields configuration\n const disabledFields =\n targetCollection.config.admin?.custom?.['plugin-import-export']?.disabledFields ?? []\n\n // Compute schema-based columns for CSV (provides base ordering and handles empty exports)\n const schemaColumns = isCSV\n ? getSchemaColumns({\n collectionConfig: targetCollection.config,\n disabledFields,\n fields,\n locale: locale ?? undefined,\n localeCodes,\n })\n : undefined\n\n // columns will be finalized after data is available (merged with data-discovered columns)\n let columns = schemaColumns\n\n // If we're beyond the effective limit (considering both user limit and maxLimit), return empty docs\n if (exportTotalDocs > 0 && previewStartIndex >= exportTotalDocs) {\n const response: ExportPreviewResponse = {\n columns,\n docs: [],\n exportTotalDocs,\n hasNextPage: false,\n hasPrevPage: previewPage > 1,\n limit: previewLimit,\n maxLimit,\n page: previewPage,\n totalDocs: exportTotalDocs,\n totalPages: previewTotalPages,\n }\n return Response.json(response)\n }\n\n // Fetch preview page with full previewLimit to maintain consistent pagination offsets\n // We'll trim the results afterwards if needed to respect export limit\n const result = await req.payload.find({\n collection: collectionSlug,\n depth: 1,\n draft,\n limit: previewLimit,\n locale,\n overrideAccess: false,\n page: previewPage,\n req,\n select,\n sort,\n where,\n })\n\n // Trim docs to respect effective limit boundary (user limit clamped by maxLimit)\n let docs = result.docs\n if (exportTotalDocs > 0) {\n const remainingInExport = exportTotalDocs - previewStartIndex\n if (remainingInExport < docs.length) {\n docs = docs.slice(0, remainingInExport)\n }\n }\n\n // Transform docs based on format\n let transformed: Record<string, unknown>[]\n\n if (isCSV) {\n const toCSVFunctions = getExportFieldFunctions({\n fields: targetCollection.config.fields as FlattenedField[],\n })\n\n const possibleKeys = getFlattenedFieldKeys(\n targetCollection.config.fields as FlattenedField[],\n '',\n { localeCodes },\n )\n\n // Flatten docs without padding yet. This preserves the exact keys produced by toCSV hooks,\n // allowing mergeColumns to detect which schema columns were replaced with derived ones.\n transformed = docs.map((doc) =>\n flattenObject({\n doc,\n fields,\n toCSVFunctions,\n }),\n )\n\n // Merge schema columns with data-discovered columns (e.g., derived columns from toCSV)\n // This ensures the preview headers match what the actual export will produce\n if (schemaColumns && transformed.length > 0) {\n const dataColumns: string[] = []\n const seenCols = new Set<string>()\n for (const row of transformed) {\n for (const key of Object.keys(row)) {\n if (!seenCols.has(key)) {\n seenCols.add(key)\n dataColumns.push(key)\n }\n }\n }\n columns = mergeColumns(schemaColumns, dataColumns)\n }\n\n // Pad rows with null for missing columns (uses merged columns, not raw schema)\n if (!fields || fields.length === 0) {\n const paddingKeys = columns ?? possibleKeys\n for (const row of transformed) {\n for (const key of paddingKeys) {\n if (!(key in row)) {\n row[key] = null\n }\n }\n }\n }\n } else {\n transformed = docs.map((doc) => {\n let output: Record<string, unknown> = { ...doc }\n\n // Remove disabled fields first\n output = removeDisabledFields(output, disabledFields)\n\n // Then trim to selected fields only (if fields are provided)\n if (Array.isArray(fields) && fields.length > 0) {\n const trimmed: Record<string, unknown> = {}\n\n for (const key of fields) {\n const value = getObjectDotNotation(output, key)\n setNestedValue(trimmed, key, value ?? null)\n }\n\n output = trimmed\n }\n\n return output\n })\n }\n\n const hasNextPage = previewPage < previewTotalPages\n const hasPrevPage = previewPage > 1\n\n const response: ExportPreviewResponse = {\n columns,\n docs: transformed,\n exportTotalDocs,\n hasNextPage,\n hasPrevPage,\n limit: previewLimit,\n maxLimit,\n page: previewPage,\n totalDocs: exportTotalDocs,\n totalPages: previewTotalPages,\n }\n\n return Response.json(response)\n}\n"],"names":["addDataAndFileToRequest","getObjectDotNotation","DEFAULT_PREVIEW_LIMIT","MAX_PREVIEW_LIMIT","MIN_PREVIEW_LIMIT","MIN_PREVIEW_PAGE","flattenObject","getExportFieldFunctions","getFlattenedFieldKeys","getSchemaColumns","mergeColumns","getSelect","removeDisabledFields","resolveLimit","setNestedValue","handlePreview","req","collectionSlug","draft","draftFromReq","fields","limit","exportLimit","locale","previewLimit","rawPreviewLimit","previewPage","rawPreviewPage","sort","where","whereFromReq","data","Math","max","min","targetCollection","payload","collections","Response","json","error","status","pluginConfig","config","custom","maxLimit","select","Array","isArray","length","undefined","collectionHasVersions","Boolean","versions","publishedWhere","_status","equals","and","countResult","count","collection","overrideAccess","totalMatchingDocs","totalDocs","effectiveLimit","exportTotalDocs","previewStartIndex","previewTotalPages","ceil","isCSV","format","localeCodes","localization","disabledFields","admin","schemaColumns","collectionConfig","columns","response","docs","hasNextPage","hasPrevPage","page","totalPages","result","find","depth","remainingInExport","slice","transformed","toCSVFunctions","possibleKeys","map","doc","dataColumns","seenCols","Set","row","key","Object","keys","has","add","push","paddingKeys","output","trimmed","value"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/export/handlePreview.ts"],"sourcesContent":["import type { PayloadRequest, Sort, Where } from 'payload'\n\nimport { addDataAndFileToRequest } from 'payload'\nimport { getObjectDotNotation } from 'payload/shared'\n\nimport type { ExportBeforeHook, ExportDoc, ExportPreviewResponse } from '../types.js'\n\nimport {\n DEFAULT_PREVIEW_LIMIT,\n MAX_PREVIEW_LIMIT,\n MIN_PREVIEW_LIMIT,\n MIN_PREVIEW_PAGE,\n} from '../constants.js'\nimport { applyFieldHooks } from '../utilities/applyFieldHooks.js'\nimport { flattenObject } from '../utilities/flattenObject.js'\nimport { getExportFieldFunctions } from '../utilities/getExportFieldFunctions.js'\nimport { getFlattenedFieldKeys } from '../utilities/getFlattenedFieldKeys.js'\nimport { getSchemaColumns, mergeColumns } from '../utilities/getSchemaColumns.js'\nimport { getSelect } from '../utilities/getSelect.js'\nimport { getSubmittedFormValues } from '../utilities/getSubmittedFormValues.js'\nimport { removeDisabledFields } from '../utilities/removeDisabledFields.js'\nimport { resolveLimit } from '../utilities/resolveLimit.js'\nimport { setNestedValue } from '../utilities/setNestedValue.js'\n\nconst applyExportBeforeHook = async ({\n data,\n exportDoc,\n format,\n hook,\n originalDocs,\n req,\n}: {\n data: Record<string, unknown>[]\n exportDoc: ExportDoc\n format: 'csv' | 'json' | ({} & string)\n hook: ExportBeforeHook | undefined\n originalDocs: unknown[]\n req: PayloadRequest\n}): Promise<Record<string, unknown>[]> => {\n if (!hook || data.length === 0) {\n return data\n }\n return hook({\n batchNumber: 1,\n data,\n exportDoc,\n format,\n originalData: originalDocs as Record<string, unknown>[],\n req,\n totalBatches: 1,\n })\n}\n\nexport const handlePreview = async (req: PayloadRequest): Promise<Response> => {\n await addDataAndFileToRequest(req)\n\n const {\n collectionSlug,\n draft: draftFromReq,\n fields,\n formData,\n limit: exportLimit,\n locale,\n previewLimit: rawPreviewLimit = DEFAULT_PREVIEW_LIMIT,\n previewPage: rawPreviewPage = 1,\n sort,\n where: whereFromReq = {},\n } = req.data as {\n collectionSlug: string\n draft?: 'no' | 'yes'\n fields?: string[]\n format?: 'csv' | 'json'\n formData?: Record<string, unknown>\n limit?: number\n locale?: string\n previewLimit?: number\n previewPage?: number\n sort?: Sort\n where?: Where\n }\n\n // Validate and clamp pagination values to safe bounds\n const previewLimit = Math.max(MIN_PREVIEW_LIMIT, Math.min(rawPreviewLimit, MAX_PREVIEW_LIMIT))\n const previewPage = Math.max(MIN_PREVIEW_PAGE, rawPreviewPage)\n\n const exportDoc = getSubmittedFormValues({\n formData: formData ?? {},\n }) as ExportDoc\n\n const targetCollection = req.payload.collections[collectionSlug]\n if (!targetCollection) {\n return Response.json(\n { error: `Collection with slug ${collectionSlug} not found` },\n { status: 400 },\n )\n }\n\n const pluginConfig = targetCollection.config.custom?.['plugin-import-export']\n const maxLimit = await resolveLimit({\n limit: pluginConfig?.exportLimit,\n req,\n })\n\n const select = Array.isArray(fields) && fields.length > 0 ? getSelect(fields) : undefined\n const draft = draftFromReq === 'yes'\n const collectionHasVersions = Boolean(targetCollection.config.versions)\n\n // Only filter by _status for versioned collections\n const publishedWhere: Where = collectionHasVersions ? { _status: { equals: 'published' } } : {}\n\n const where: Where = {\n and: [whereFromReq, draft ? {} : publishedWhere],\n }\n\n // Count total docs matching export criteria\n const countResult = await req.payload.count({\n collection: collectionSlug,\n overrideAccess: false,\n req,\n where,\n })\n\n const totalMatchingDocs = countResult.totalDocs\n\n // Calculate actual export count (respecting both export limit and max limit)\n let effectiveLimit = totalMatchingDocs\n\n // Apply user's export limit if provided\n if (exportLimit && exportLimit > 0) {\n effectiveLimit = Math.min(effectiveLimit, exportLimit)\n }\n\n // Apply max limit if configured\n if (typeof maxLimit === 'number' && maxLimit > 0) {\n effectiveLimit = Math.min(effectiveLimit, maxLimit)\n }\n\n const exportTotalDocs = effectiveLimit\n\n // Calculate preview pagination that respects export limit\n // Preview should only show docs that will actually be exported\n const previewStartIndex = (previewPage - 1) * previewLimit\n\n // Calculate pagination info based on export limit (not raw DB results)\n const previewTotalPages = exportTotalDocs === 0 ? 0 : Math.ceil(exportTotalDocs / previewLimit)\n\n const isCSV = req?.data?.format === 'csv'\n\n // Get locale codes for locale expansion when locale='all'\n const localeCodes =\n locale === 'all' && req.payload.config.localization\n ? req.payload.config.localization.localeCodes\n : undefined\n\n // Get disabled fields configuration\n const disabledFields =\n targetCollection.config.admin?.custom?.['plugin-import-export']?.disabledFields ?? []\n\n // Compute schema-based columns for CSV (provides base ordering and handles empty exports)\n const schemaColumns = isCSV\n ? getSchemaColumns({\n collectionConfig: targetCollection.config,\n disabledFields,\n fields,\n locale: locale ?? undefined,\n localeCodes,\n })\n : undefined\n\n // columns will be finalized after data is available (merged with data-discovered columns)\n let columns = schemaColumns\n\n // If we're beyond the effective limit (considering both user limit and maxLimit), return empty docs\n if (exportTotalDocs > 0 && previewStartIndex >= exportTotalDocs) {\n const response: ExportPreviewResponse = {\n columns,\n docs: [],\n exportTotalDocs,\n hasNextPage: false,\n hasPrevPage: previewPage > 1,\n limit: previewLimit,\n maxLimit,\n page: previewPage,\n totalDocs: exportTotalDocs,\n totalPages: previewTotalPages,\n }\n return Response.json(response)\n }\n\n // Fetch preview page with full previewLimit to maintain consistent pagination offsets\n // We'll trim the results afterwards if needed to respect export limit\n const result = await req.payload.find({\n collection: collectionSlug,\n depth: 1,\n draft,\n limit: previewLimit,\n locale,\n overrideAccess: false,\n page: previewPage,\n req,\n select,\n sort,\n where,\n })\n\n // Trim docs to respect effective limit boundary (user limit clamped by maxLimit)\n let docs = result.docs\n if (exportTotalDocs > 0) {\n const remainingInExport = exportTotalDocs - previewStartIndex\n if (remainingInExport < docs.length) {\n docs = docs.slice(0, remainingInExport)\n }\n }\n\n // Transform docs based on format\n let transformed: Record<string, unknown>[]\n\n const exportFieldHooks = getExportFieldFunctions({\n fields: targetCollection.config.flattenedFields,\n })\n\n const exportHooks = targetCollection.config.custom?.['plugin-import-export']?.exportHooks\n\n if (isCSV) {\n const possibleKeys = getFlattenedFieldKeys(targetCollection.config.flattenedFields, '', {\n localeCodes,\n })\n\n // Flatten docs without padding yet. This preserves the exact keys produced by beforeExport hooks,\n // allowing mergeColumns to detect which schema columns were replaced with derived ones.\n transformed = docs.map((doc) =>\n flattenObject({\n data: doc,\n exportFieldHooks,\n fields,\n format: 'csv',\n req,\n }),\n )\n\n transformed = await applyExportBeforeHook({\n data: transformed,\n exportDoc,\n format: 'csv',\n hook: exportHooks?.before,\n originalDocs: docs,\n req,\n })\n\n if (schemaColumns && transformed.length > 0) {\n const dataColumns: string[] = []\n const seenCols = new Set<string>()\n for (const row of transformed) {\n for (const key of Object.keys(row)) {\n if (!seenCols.has(key)) {\n seenCols.add(key)\n dataColumns.push(key)\n }\n }\n }\n const mergedColumns = mergeColumns(schemaColumns, dataColumns)\n columns =\n Boolean(exportHooks?.before) && transformed.length > 0\n ? mergedColumns.filter((col) => dataColumns.includes(col))\n : mergedColumns\n }\n\n // Pad rows with null for missing columns (uses merged columns, not raw schema)\n if (!fields || fields.length === 0) {\n const paddingKeys = columns ?? possibleKeys\n for (const row of transformed) {\n for (const key of paddingKeys) {\n if (!(key in row)) {\n row[key] = null\n }\n }\n }\n }\n } else {\n transformed = docs.map((doc) => {\n // Apply field-level export hooks for JSON format\n let output: Record<string, unknown> = applyFieldHooks({\n type: 'beforeExport',\n data: doc as Record<string, unknown>,\n fieldHooks: exportFieldHooks,\n fields: targetCollection.config.flattenedFields,\n format: 'json',\n operation: 'export',\n req,\n })\n\n // Remove disabled fields\n output = removeDisabledFields(output, disabledFields)\n\n // Then trim to selected fields only (if fields are provided)\n if (Array.isArray(fields) && fields.length > 0) {\n const trimmed: Record<string, unknown> = {}\n\n for (const key of fields) {\n const value = getObjectDotNotation(output, key)\n setNestedValue(trimmed, key, value ?? null, output)\n }\n\n output = trimmed\n }\n\n return output\n })\n\n transformed = await applyExportBeforeHook({\n data: transformed,\n exportDoc,\n format: 'json',\n hook: exportHooks?.before,\n originalDocs: docs,\n req,\n })\n }\n\n const hasNextPage = previewPage < previewTotalPages\n const hasPrevPage = previewPage > 1\n\n const response: ExportPreviewResponse = {\n columns,\n docs: transformed,\n exportTotalDocs,\n hasNextPage,\n hasPrevPage,\n limit: previewLimit,\n maxLimit,\n page: previewPage,\n totalDocs: exportTotalDocs,\n totalPages: previewTotalPages,\n }\n\n return Response.json(response)\n}\n"],"names":["addDataAndFileToRequest","getObjectDotNotation","DEFAULT_PREVIEW_LIMIT","MAX_PREVIEW_LIMIT","MIN_PREVIEW_LIMIT","MIN_PREVIEW_PAGE","applyFieldHooks","flattenObject","getExportFieldFunctions","getFlattenedFieldKeys","getSchemaColumns","mergeColumns","getSelect","getSubmittedFormValues","removeDisabledFields","resolveLimit","setNestedValue","applyExportBeforeHook","data","exportDoc","format","hook","originalDocs","req","length","batchNumber","originalData","totalBatches","handlePreview","collectionSlug","draft","draftFromReq","fields","formData","limit","exportLimit","locale","previewLimit","rawPreviewLimit","previewPage","rawPreviewPage","sort","where","whereFromReq","Math","max","min","targetCollection","payload","collections","Response","json","error","status","pluginConfig","config","custom","maxLimit","select","Array","isArray","undefined","collectionHasVersions","Boolean","versions","publishedWhere","_status","equals","and","countResult","count","collection","overrideAccess","totalMatchingDocs","totalDocs","effectiveLimit","exportTotalDocs","previewStartIndex","previewTotalPages","ceil","isCSV","localeCodes","localization","disabledFields","admin","schemaColumns","collectionConfig","columns","response","docs","hasNextPage","hasPrevPage","page","totalPages","result","find","depth","remainingInExport","slice","transformed","exportFieldHooks","flattenedFields","exportHooks","possibleKeys","map","doc","before","dataColumns","seenCols","Set","row","key","Object","keys","has","add","push","mergedColumns","filter","col","includes","paddingKeys","output","type","fieldHooks","operation","trimmed","value"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export type { ImportExportPluginConfig, Limit, LimitFunction, ToCSVFunction } from '../types.js';
1
+ export type { ExportAfterHook, ExportBeforeHook, ExportDoc, FieldBeforeExportHook, FieldBeforeImportHook, ImportAfterHook, ImportBeforeHook, ImportDoc, ImportExportPluginConfig, ImportResult, Limit, LimitFunction, } from '../types.js';
2
2
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/exports/types.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,wBAAwB,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/exports/types.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,wBAAwB,EACxB,YAAY,EACZ,KAAK,EACL,aAAa,GACd,MAAM,aAAa,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/exports/types.ts"],"sourcesContent":["export type { ImportExportPluginConfig, Limit, LimitFunction, ToCSVFunction } from '../types.js'\n"],"names":[],"mappings":"AAAA,WAAgG"}
1
+ {"version":3,"sources":["../../src/exports/types.ts"],"sourcesContent":["export type {\n ExportAfterHook,\n ExportBeforeHook,\n ExportDoc,\n FieldBeforeExportHook,\n FieldBeforeImportHook,\n ImportAfterHook,\n ImportBeforeHook,\n ImportDoc,\n ImportExportPluginConfig,\n ImportResult,\n Limit,\n LimitFunction,\n} from '../types.js'\n"],"names":[],"mappings":"AAAA,WAaoB"}
@@ -1,5 +1,6 @@
1
- import type { PayloadRequest, TypedUser } from 'payload';
2
- import type { ImportMode, ImportResult } from './createImport.js';
1
+ import type { PayloadRequest, User } from 'payload';
2
+ import type { ImportAfterHook, ImportBeforeHook, ImportDoc, ImportResult } from '../types.js';
3
+ import type { ImportMode } from './createImport.js';
3
4
  import { type BatchError } from '../utilities/useBatchProcessor.js';
4
5
  /**
5
6
  * Import-specific batch processor options
@@ -34,11 +35,23 @@ export interface ImportBatchResult {
34
35
  */
35
36
  export interface ImportProcessOptions {
36
37
  collectionSlug: string;
37
- documents: Record<string, unknown>[];
38
+ docs: Record<string, unknown>[];
39
+ /** Export format — passed through to hook args */
40
+ format?: 'csv' | 'json';
41
+ /** Lifecycle hooks for this import operation */
42
+ hooks?: {
43
+ after?: ImportAfterHook;
44
+ before?: ImportBeforeHook;
45
+ };
46
+ importDoc: ImportDoc;
38
47
  importMode: ImportMode;
39
48
  matchField?: string;
49
+ /** Raw parsed rows before unflattening — used as originalData in hooks */
50
+ originalDocs?: Record<string, unknown>[];
40
51
  req: PayloadRequest;
41
- user?: TypedUser;
52
+ /** Total number of batches (pre-computed for hook args) */
53
+ totalBatches?: number;
54
+ user?: User;
42
55
  }
43
56
  export declare function createImportBatchProcessor(options?: ImportBatchProcessorOptions): {
44
57
  processImport: (processOptions: ImportProcessOptions) => Promise<ImportResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"batchProcessor.d.ts","sourceRoot":"","sources":["../../src/import/batchProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAIxD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEjE,OAAO,EACL,KAAK,UAAU,EAIhB,MAAM,mCAAmC,CAAA;AAE1C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oBAAoB,CAAC,EAAE,OAAO,GAAG,WAAW,CAAA;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAA;IAC1B,UAAU,EAAE,KAAK,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjC,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;QACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAChC,CAAC,CAAA;CACH;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IACpC,UAAU,EAAE,UAAU,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,GAAG,EAAE,cAAc,CAAA;IACnB,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAuiBD,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,2BAAgC;oCAMrC,oBAAoB,KAAG,OAAO,CAAC,YAAY,CAAC;EA2D1F"}
1
+ {"version":3,"file":"batchProcessor.d.ts","sourceRoot":"","sources":["../../src/import/batchProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAInD,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC7F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEnD,OAAO,EACL,KAAK,UAAU,EAIhB,MAAM,mCAAmC,CAAA;AAE1C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oBAAoB,CAAC,EAAE,OAAO,GAAG,WAAW,CAAA;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAA;IAC1B,UAAU,EAAE,KAAK,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjC,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;QACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAChC,CAAC,CAAA;CACH;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAC/B,kDAAkD;IAClD,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACvB,gDAAgD;IAChD,KAAK,CAAC,EAAE;QACN,KAAK,CAAC,EAAE,eAAe,CAAA;QACvB,MAAM,CAAC,EAAE,gBAAgB,CAAA;KAC1B,CAAA;IACD,SAAS,EAAE,SAAS,CAAA;IACpB,UAAU,EAAE,UAAU,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IACxC,GAAG,EAAE,cAAc,CAAA;IACnB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,IAAI,CAAC,EAAE,IAAI,CAAA;CACZ;AA8hBD,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,2BAAgC;oCAMrC,oBAAoB,KAAG,OAAO,CAAC,YAAY,CAAC;EAmH1F"}
@@ -1,4 +1,4 @@
1
- import { isolateObjectProperty } from 'payload';
1
+ import { getDataLoader, isolateObjectProperty } from 'payload';
2
2
  import { categorizeError, createBatches, extractErrorMessage } from '../utilities/useBatchProcessor.js';
3
3
  /**
4
4
  * Separates multi-locale data from a document for sequential locale updates.
@@ -71,13 +71,18 @@ import { categorizeError, createBatches, extractErrorMessage } from '../utilitie
71
71
  failed: [],
72
72
  successful: []
73
73
  };
74
- // Create a request proxy that isolates the transactionID property, then clear it.
75
- // This is critical because if a nested operation fails (e.g., Forbidden due to access control),
76
- // Payload's error handling calls killTransaction(req), which would kill the parent's transaction
77
- // if we shared the same transaction. By isolating and clearing transactionID, each nested
78
- // operation either uses no transaction or starts its own, independent of the parent.
79
- const req = isolateObjectProperty(reqFromArgs, 'transactionID');
74
+ // Isolate + clear `transactionID` so a failing nested op (e.g. Forbidden) kills its own
75
+ // transaction, not the parent's, on `killTransaction`.
76
+ // Also isolate `payloadDataLoader`: the shared loader mutates the parent's `req.transactionID`
77
+ // while batching relationship population (`batchAndLoadDocs`), so populating a nested doc's
78
+ // relationship (e.g. authorship `createdBy`/`updatedBy`) would leak the nested transaction onto
79
+ // the parent. A fresh loader keeps each request's transaction isolated.
80
+ const req = isolateObjectProperty(reqFromArgs, [
81
+ 'payloadDataLoader',
82
+ 'transactionID'
83
+ ]);
80
84
  req.transactionID = undefined;
85
+ req.payloadDataLoader = getDataLoader(req);
81
86
  const collectionEntry = req.payload.collections[collectionSlug];
82
87
  const collectionConfig = collectionEntry?.config;
83
88
  const collectionHasVersions = Boolean(collectionConfig?.versions);
@@ -140,25 +145,22 @@ import { categorizeError, createBatches, extractErrorMessage } from '../utilitie
140
145
  req: defaultLocaleReq,
141
146
  user
142
147
  });
143
- // Update for other locales
144
148
  if (savedDocument && Object.keys(localeUpdates).length > 0) {
145
149
  for (const [locale, localeData] of Object.entries(localeUpdates)){
146
150
  try {
147
- const localeReq = {
148
- ...req,
149
- locale
150
- };
151
151
  await req.payload.update({
152
152
  id: savedDocument.id,
153
153
  collection: collectionSlug,
154
154
  data: localeData,
155
155
  draft: collectionHasVersions ? false : undefined,
156
156
  overrideAccess: false,
157
- req: localeReq,
157
+ req: {
158
+ ...req,
159
+ locale
160
+ },
158
161
  user
159
162
  });
160
163
  } catch (error) {
161
- // Log but don't fail the entire import if a locale update fails
162
164
  req.payload.logger.error({
163
165
  err: error,
164
166
  msg: `Failed to update locale ${locale} for document ${String(savedDocument.id)}`
@@ -280,27 +282,22 @@ import { categorizeError, createBatches, extractErrorMessage } from '../utilitie
280
282
  req: defaultLocaleReq,
281
283
  user
282
284
  });
283
- // Update for other locales
284
285
  if (savedDocument && Object.keys(localeUpdates).length > 0) {
285
286
  for (const [locale, localeData] of Object.entries(localeUpdates)){
286
287
  try {
287
- // Clone the request with the specific locale
288
- const localeReq = {
289
- ...req,
290
- locale
291
- };
292
288
  await req.payload.update({
293
289
  id: existingDoc.id,
294
290
  collection: collectionSlug,
295
291
  data: localeData,
296
292
  depth: 0,
297
- // Don't specify draft - this creates a new draft for versioned collections
298
293
  overrideAccess: false,
299
- req: localeReq,
294
+ req: {
295
+ ...req,
296
+ locale
297
+ },
300
298
  user
301
299
  });
302
300
  } catch (error) {
303
- // Log but don't fail the entire import if a locale update fails
304
301
  req.payload.logger.error({
305
302
  err: error,
306
303
  msg: `Failed to update locale ${locale} for document ${String(existingDoc.id)}`
@@ -390,25 +387,22 @@ import { categorizeError, createBatches, extractErrorMessage } from '../utilitie
390
387
  req: defaultLocaleReq,
391
388
  user
392
389
  });
393
- // Update for other locales
394
390
  if (savedDocument && Object.keys(localeUpdates).length > 0) {
395
391
  for (const [locale, localeData] of Object.entries(localeUpdates)){
396
392
  try {
397
- // Clone the request with the specific locale
398
- const localeReq = {
399
- ...req,
400
- locale
401
- };
402
393
  await req.payload.update({
403
394
  id: savedDocument.id,
404
395
  collection: collectionSlug,
405
396
  data: localeData,
406
397
  draft: collectionHasVersions ? false : undefined,
407
398
  overrideAccess: false,
408
- req: localeReq
399
+ req: {
400
+ ...req,
401
+ locale
402
+ },
403
+ user
409
404
  });
410
405
  } catch (error) {
411
- // Log but don't fail the entire import if a locale update fails
412
406
  req.payload.logger.error({
413
407
  err: error,
414
408
  msg: `Failed to update locale ${locale} for document ${String(savedDocument.id)}`
@@ -497,8 +491,9 @@ export function createImportBatchProcessor(options = {}) {
497
491
  defaultVersionStatus: options.defaultVersionStatus ?? 'published'
498
492
  };
499
493
  const processImport = async (processOptions)=>{
500
- const { collectionSlug, documents, importMode, matchField, req, user } = processOptions;
494
+ const { collectionSlug, docs: documents, format = 'csv', hooks, importDoc, importMode, matchField, originalDocs: originalDocs, req, totalBatches: totalBatchesFromOptions, user } = processOptions;
501
495
  const batches = createBatches(documents, processorOptions.batchSize);
496
+ const totalBatches = totalBatchesFromOptions ?? batches.length;
502
497
  const result = {
503
498
  errors: [],
504
499
  imported: 0,
@@ -510,8 +505,20 @@ export function createImportBatchProcessor(options = {}) {
510
505
  if (!currentBatch) {
511
506
  continue;
512
507
  }
508
+ const batchNumber = i + 1;
509
+ const batchStart = i * processorOptions.batchSize;
510
+ const originalBatch = originalDocs ? originalDocs.slice(batchStart, batchStart + currentBatch.length) : currentBatch;
511
+ const batchToProcess = hooks?.before && currentBatch.length > 0 ? await hooks.before({
512
+ batchNumber,
513
+ data: currentBatch,
514
+ format,
515
+ importDoc,
516
+ originalData: originalBatch,
517
+ req,
518
+ totalBatches
519
+ }) : currentBatch;
513
520
  const batchResult = await processImportBatch({
514
- batch: currentBatch,
521
+ batch: batchToProcess,
515
522
  batchIndex: i,
516
523
  collectionSlug,
517
524
  importMode,
@@ -520,18 +527,23 @@ export function createImportBatchProcessor(options = {}) {
520
527
  req,
521
528
  user
522
529
  });
523
- // Update results
530
+ let batchImported = 0;
531
+ let batchUpdated = 0;
524
532
  for (const success of batchResult.successful){
525
533
  if (success.operation === 'created') {
526
534
  result.imported++;
535
+ batchImported++;
527
536
  } else if (success.operation === 'updated') {
528
537
  result.updated++;
538
+ batchUpdated++;
529
539
  } else {
530
540
  // Fallback
531
541
  if (importMode === 'create') {
532
542
  result.imported++;
543
+ batchImported++;
533
544
  } else {
534
545
  result.updated++;
546
+ batchUpdated++;
535
547
  }
536
548
  }
537
549
  }
@@ -542,6 +554,23 @@ export function createImportBatchProcessor(options = {}) {
542
554
  index: error.rowNumber - 1
543
555
  });
544
556
  }
557
+ if (hooks?.after) {
558
+ const batchHookResult = {
559
+ errors: batchResult.failed.length > 0 ? result.errors.slice(-batchResult.failed.length) : [],
560
+ imported: batchImported,
561
+ total: batchToProcess.length,
562
+ updated: batchUpdated
563
+ };
564
+ await hooks.after({
565
+ batchNumber,
566
+ format,
567
+ importDoc,
568
+ originalData: originalBatch,
569
+ req,
570
+ result: batchHookResult,
571
+ totalBatches
572
+ });
573
+ }
545
574
  }
546
575
  return result;
547
576
  };