@payloadcms/plugin-import-export 3.84.1 → 3.85.0

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 (90) hide show
  1. package/dist/export/batchProcessor.d.ts +9 -1
  2. package/dist/export/batchProcessor.d.ts.map +1 -1
  3. package/dist/export/batchProcessor.js +57 -15
  4. package/dist/export/batchProcessor.js.map +1 -1
  5. package/dist/export/createExport.d.ts.map +1 -1
  6. package/dist/export/createExport.js +98 -20
  7. package/dist/export/createExport.js.map +1 -1
  8. package/dist/export/handlePreview.d.ts.map +1 -1
  9. package/dist/export/handlePreview.js +38 -13
  10. package/dist/export/handlePreview.js.map +1 -1
  11. package/dist/exports/types.d.ts +1 -1
  12. package/dist/exports/types.d.ts.map +1 -1
  13. package/dist/exports/types.js.map +1 -1
  14. package/dist/import/batchProcessor.d.ts +14 -2
  15. package/dist/import/batchProcessor.d.ts.map +1 -1
  16. package/dist/import/batchProcessor.js +49 -27
  17. package/dist/import/batchProcessor.js.map +1 -1
  18. package/dist/import/createImport.d.ts +1 -10
  19. package/dist/import/createImport.d.ts.map +1 -1
  20. package/dist/import/createImport.js +33 -52
  21. package/dist/import/createImport.js.map +1 -1
  22. package/dist/import/handlePreview.d.ts.map +1 -1
  23. package/dist/import/handlePreview.js +32 -6
  24. package/dist/import/handlePreview.js.map +1 -1
  25. package/dist/index.d.ts +58 -3
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +18 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/types.d.ts +218 -39
  30. package/dist/types.d.ts.map +1 -1
  31. package/dist/types.js.map +1 -1
  32. package/dist/utilities/applyFieldHooks.d.ts +23 -0
  33. package/dist/utilities/applyFieldHooks.d.ts.map +1 -0
  34. package/dist/utilities/applyFieldHooks.js +118 -0
  35. package/dist/utilities/applyFieldHooks.js.map +1 -0
  36. package/dist/utilities/applyFieldHooks.spec.js +205 -0
  37. package/dist/utilities/applyFieldHooks.spec.js.map +1 -0
  38. package/dist/utilities/collectDisabledFieldPaths.d.ts.map +1 -1
  39. package/dist/utilities/collectDisabledFieldPaths.js +1 -1
  40. package/dist/utilities/collectDisabledFieldPaths.js.map +1 -1
  41. package/dist/utilities/flattenObject.d.ts +8 -6
  42. package/dist/utilities/flattenObject.d.ts.map +1 -1
  43. package/dist/utilities/flattenObject.js +95 -75
  44. package/dist/utilities/flattenObject.js.map +1 -1
  45. package/dist/utilities/flattenObject.spec.js +158 -0
  46. package/dist/utilities/flattenObject.spec.js.map +1 -0
  47. package/dist/utilities/flattenedFields.d.ts +21 -0
  48. package/dist/utilities/flattenedFields.d.ts.map +1 -0
  49. package/dist/utilities/flattenedFields.js +34 -0
  50. package/dist/utilities/flattenedFields.js.map +1 -0
  51. package/dist/utilities/getExportFieldFunctions.d.ts +5 -5
  52. package/dist/utilities/getExportFieldFunctions.d.ts.map +1 -1
  53. package/dist/utilities/getExportFieldFunctions.js +92 -98
  54. package/dist/utilities/getExportFieldFunctions.js.map +1 -1
  55. package/dist/utilities/getExportFieldFunctions.spec.js +50 -0
  56. package/dist/utilities/getExportFieldFunctions.spec.js.map +1 -0
  57. package/dist/utilities/getImportFieldFunctions.d.ts +5 -5
  58. package/dist/utilities/getImportFieldFunctions.d.ts.map +1 -1
  59. package/dist/utilities/getImportFieldFunctions.js +103 -103
  60. package/dist/utilities/getImportFieldFunctions.js.map +1 -1
  61. package/dist/utilities/getImportFieldFunctions.spec.js +167 -0
  62. package/dist/utilities/getImportFieldFunctions.spec.js.map +1 -0
  63. package/dist/utilities/isPlainObject.d.ts +2 -0
  64. package/dist/utilities/isPlainObject.d.ts.map +1 -0
  65. package/dist/utilities/isPlainObject.js +3 -0
  66. package/dist/utilities/isPlainObject.js.map +1 -0
  67. package/dist/utilities/legacyHookDispatch.spec.js +227 -0
  68. package/dist/utilities/legacyHookDispatch.spec.js.map +1 -0
  69. package/dist/utilities/polymorphicRel.d.ts +14 -0
  70. package/dist/utilities/polymorphicRel.d.ts.map +1 -0
  71. package/dist/utilities/polymorphicRel.js +17 -0
  72. package/dist/utilities/polymorphicRel.js.map +1 -0
  73. package/dist/utilities/processRichTextField.js.map +1 -1
  74. package/dist/utilities/removeDisabledFields.js.map +1 -1
  75. package/dist/utilities/setNestedValue.d.ts.map +1 -1
  76. package/dist/utilities/setNestedValue.js +10 -8
  77. package/dist/utilities/setNestedValue.js.map +1 -1
  78. package/dist/utilities/siblingDoc.spec.js +278 -0
  79. package/dist/utilities/siblingDoc.spec.js.map +1 -0
  80. package/dist/utilities/unflattenObject.d.ts +4 -3
  81. package/dist/utilities/unflattenObject.d.ts.map +1 -1
  82. package/dist/utilities/unflattenObject.js +57 -169
  83. package/dist/utilities/unflattenObject.js.map +1 -1
  84. package/dist/utilities/unflattenObject.spec.js +33 -0
  85. package/dist/utilities/unflattenObject.spec.js.map +1 -1
  86. package/dist/utilities/unflattenPostProcess.d.ts +11 -0
  87. package/dist/utilities/unflattenPostProcess.d.ts.map +1 -0
  88. package/dist/utilities/unflattenPostProcess.js +148 -0
  89. package/dist/utilities/unflattenPostProcess.js.map +1 -0
  90. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/export/createExport.ts"],"sourcesContent":["/* eslint-disable perfectionist/sort-objects */\nimport type { PayloadRequest, Sort, TypedUser, Where } from 'payload'\n\nimport { stringify } from 'csv-stringify/sync'\nimport { APIError } from 'payload'\nimport { Readable } from 'stream'\n\nimport { buildDisabledFieldRegex } from '../utilities/buildDisabledFieldRegex.js'\nimport { flattenObject } from '../utilities/flattenObject.js'\nimport { getExportFieldFunctions } from '../utilities/getExportFieldFunctions.js'\nimport { getFilename } from '../utilities/getFilename.js'\nimport { getSchemaColumns, mergeColumns } from '../utilities/getSchemaColumns.js'\nimport { getSelect } from '../utilities/getSelect.js'\nimport { validateLimitValue } from '../utilities/validateLimitValue.js'\nimport { createExportBatchProcessor, type ExportFindArgs } from './batchProcessor.js'\n\nexport type Export = {\n /**\n * Number of documents to process in each batch during export\n * @default 100\n */\n batchSize?: number\n collectionSlug: string\n /**\n * If true, enables debug logging\n */\n debug?: boolean\n drafts?: 'no' | 'yes'\n exportCollection: string\n fields?: string[]\n format: 'csv' | 'json'\n globals?: string[]\n id: number | string\n limit?: number\n locale?: string\n /**\n * Maximum number of documents that can be exported in a single operation.\n * This value has already been resolved from the plugin config.\n */\n maxLimit?: number\n name: string\n page?: number\n sort?: Sort\n userCollection: string\n userID: number | string\n where?: Where\n}\n\nexport type CreateExportArgs = {\n /**\n * If true, stream the file instead of saving it\n */\n download?: boolean\n req: PayloadRequest\n} & Export\n\nexport const createExport = async (args: CreateExportArgs) => {\n const {\n id,\n name: nameArg,\n batchSize = 100,\n collectionSlug,\n debug = false,\n download,\n drafts: draftsFromInput,\n exportCollection,\n fields,\n format,\n limit: incomingLimit,\n maxLimit,\n locale: localeFromInput,\n page,\n req,\n sort,\n userCollection,\n userID,\n where: whereFromInput = {},\n } = args\n const { locale: localeFromReq, payload } = req\n\n if (debug) {\n req.payload.logger.debug({\n msg: '[createExport] Starting export process',\n exportDocId: id,\n exportName: nameArg,\n collectionSlug,\n exportCollection,\n draft: draftsFromInput,\n fields,\n format,\n })\n }\n\n const locale = localeFromInput ?? localeFromReq\n const collectionConfig = payload.config.collections.find(({ slug }) => slug === collectionSlug)\n\n if (!collectionConfig) {\n throw new APIError(`Collection with slug ${collectionSlug} not found.`)\n }\n\n let user: TypedUser | undefined\n\n if (userCollection && userID) {\n user = (await req.payload.findByID({\n id: userID,\n collection: userCollection,\n overrideAccess: true,\n })) as TypedUser\n }\n\n if (!user && req.user) {\n user = req?.user?.id ? req.user : req?.user?.user\n }\n\n if (!user) {\n throw new APIError('User authentication is required to create exports.')\n }\n\n const draft = draftsFromInput === 'yes'\n const hasVersions = Boolean(collectionConfig.versions)\n\n // Only filter by _status for versioned collections\n const publishedWhere: Where = hasVersions ? { _status: { equals: 'published' } } : {}\n\n const where: Where = {\n and: [whereFromInput, draft ? {} : publishedWhere],\n }\n\n const baseName = nameArg ?? getFilename()\n const name = `${baseName}-${collectionSlug}.${format}`\n const isCSV = format === 'csv'\n const select = Array.isArray(fields) && fields.length > 0 ? getSelect(fields) : undefined\n\n if (debug) {\n req.payload.logger.debug({ message: 'Export configuration:', name, isCSV, locale })\n }\n\n // Determine maximum export documents:\n // 1. If maxLimit is defined, it sets the absolute ceiling\n // 2. User's limit is applied but clamped to maxLimit if it exceeds it\n let maxExportDocuments: number | undefined\n\n if (typeof maxLimit === 'number' && maxLimit > 0) {\n if (typeof incomingLimit === 'number' && incomingLimit > 0) {\n // User provided a limit - clamp it to maxLimit\n maxExportDocuments = Math.min(incomingLimit, maxLimit)\n } else {\n // No user limit - use maxLimit as the ceiling\n maxExportDocuments = maxLimit\n }\n } else {\n // No maxLimit - use user's limit if provided\n maxExportDocuments =\n typeof incomingLimit === 'number' && incomingLimit > 0 ? incomingLimit : undefined\n }\n\n // Try to count documents - if access is denied, treat as 0 documents\n let totalDocs = 0\n let accessDenied = false\n try {\n const countResult = await payload.count({\n collection: collectionSlug,\n user,\n locale,\n overrideAccess: false,\n })\n totalDocs = countResult.totalDocs\n } catch (error) {\n // Access denied - user can't read from this collection\n // We'll create an empty export file\n accessDenied = true\n if (debug) {\n req.payload.logger.debug({\n message: 'Access denied for collection, creating empty export',\n collectionSlug,\n })\n }\n }\n\n const totalPages = Math.max(1, Math.ceil(totalDocs / batchSize))\n const requestedPage = page || 1\n const adjustedPage = requestedPage > totalPages ? 1 : requestedPage\n\n const findArgs = {\n collection: collectionSlug,\n depth: 1,\n draft,\n limit: batchSize,\n locale,\n overrideAccess: false,\n page: 0,\n select,\n sort,\n user,\n where,\n }\n\n if (debug) {\n req.payload.logger.debug({ message: 'Find arguments:', findArgs })\n }\n\n const toCSVFunctions = getExportFieldFunctions({\n fields: collectionConfig.flattenedFields,\n })\n\n const disabledFields =\n collectionConfig.admin?.custom?.['plugin-import-export']?.disabledFields ?? []\n\n const disabledMatchers = disabledFields.map(buildDisabledFieldRegex)\n\n const filterDisabledCSV = (row: Record<string, unknown>): Record<string, unknown> => {\n const filtered: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(row)) {\n const isDisabled = disabledMatchers.some((matcher) => matcher.test(key))\n if (!isDisabled) {\n filtered[key] = value\n }\n }\n\n return filtered\n }\n\n const filterDisabledJSON = (doc: any, parentPath = ''): any => {\n if (Array.isArray(doc)) {\n return doc.map((item) => filterDisabledJSON(item, parentPath))\n }\n\n if (typeof doc !== 'object' || doc === null) {\n return doc\n }\n\n const filtered: Record<string, any> = {}\n for (const [key, value] of Object.entries(doc)) {\n const currentPath = parentPath ? `${parentPath}.${key}` : key\n\n // Only remove if this exact path is disabled\n const isDisabled = disabledFields.includes(currentPath)\n\n if (!isDisabled) {\n filtered[key] = filterDisabledJSON(value, currentPath)\n }\n }\n\n return filtered\n }\n\n if (download) {\n const limitErrorMsg = validateLimitValue(incomingLimit, req.t)\n if (limitErrorMsg) {\n throw new APIError(limitErrorMsg)\n }\n\n // Get schema-based columns first (provides base ordering and handles empty exports)\n let schemaColumns: string[] = []\n if (isCSV) {\n const localeCodes =\n locale === 'all' && payload.config.localization\n ? payload.config.localization.localeCodes\n : undefined\n\n schemaColumns = getSchemaColumns({\n collectionConfig,\n disabledFields,\n fields,\n locale,\n localeCodes,\n })\n\n if (debug) {\n req.payload.logger.debug({\n columnCount: schemaColumns.length,\n msg: 'Schema-based column inference complete',\n })\n }\n }\n\n // allColumns will be finalized after first batch (schema + data columns merged)\n let allColumns: string[] = []\n let columnsFinalized = false\n\n const encoder = new TextEncoder()\n let isFirstBatch = true\n let currentBatchPage = adjustedPage\n let fetched = 0\n const maxDocs =\n typeof maxExportDocuments === 'number' ? maxExportDocuments : Number.POSITIVE_INFINITY\n\n const stream = new Readable({\n async read() {\n const remaining = Math.max(0, maxDocs - fetched)\n\n if (remaining === 0) {\n if (!isCSV) {\n // If first batch with no remaining, output empty array; otherwise just close\n this.push(encoder.encode(isFirstBatch ? '[]' : ']'))\n }\n this.push(null)\n return\n }\n\n const result = await payload.find({\n ...findArgs,\n page: currentBatchPage,\n limit: Math.min(batchSize, remaining),\n })\n\n if (debug) {\n req.payload.logger.debug(\n `Streaming batch ${currentBatchPage} with ${result.docs.length} docs`,\n )\n }\n\n if (result.docs.length === 0) {\n // Close JSON array properly if JSON\n if (!isCSV) {\n // If first batch with no docs, output empty array; otherwise just close\n this.push(encoder.encode(isFirstBatch ? '[]' : ']'))\n }\n this.push(null)\n return\n }\n\n if (isCSV) {\n // --- CSV Streaming ---\n const batchRows = result.docs.map((doc) =>\n filterDisabledCSV(\n flattenObject({\n doc,\n fields,\n toCSVFunctions,\n }),\n ),\n )\n\n // On first batch, discover additional columns from data and merge with schema\n if (!columnsFinalized) {\n const dataColumns: string[] = []\n const seenCols = new Set<string>()\n for (const row of batchRows) {\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 // Merge schema columns with data-discovered columns\n allColumns = mergeColumns(schemaColumns, dataColumns)\n columnsFinalized = true\n\n if (debug) {\n req.payload.logger.debug({\n dataColumnsCount: dataColumns.length,\n finalColumnsCount: allColumns.length,\n msg: 'Merged schema and data columns',\n })\n }\n }\n\n const paddedRows = batchRows.map((row) => {\n const fullRow: Record<string, unknown> = {}\n for (const col of allColumns) {\n fullRow[col] = row[col] ?? ''\n }\n return fullRow\n })\n\n const csvString = stringify(paddedRows, {\n bom: isFirstBatch,\n header: isFirstBatch,\n columns: allColumns,\n })\n\n this.push(encoder.encode(csvString))\n } else {\n // --- JSON Streaming ---\n const batchRows = result.docs.map((doc) => filterDisabledJSON(doc))\n\n // Convert each filtered/flattened row into JSON string\n const batchJSON = batchRows.map((row) => JSON.stringify(row)).join(',')\n\n if (isFirstBatch) {\n this.push(encoder.encode('[' + batchJSON))\n } else {\n this.push(encoder.encode(',' + batchJSON))\n }\n }\n\n fetched += result.docs.length\n isFirstBatch = false\n currentBatchPage += 1\n\n if (!result.hasNextPage || fetched >= maxDocs) {\n if (debug) {\n req.payload.logger.debug('Stream complete - no more pages')\n }\n if (!isCSV) {\n this.push(encoder.encode(']'))\n }\n this.push(null) // End the stream\n }\n },\n })\n\n return new Response(Readable.toWeb(stream) as ReadableStream, {\n headers: {\n 'Content-Disposition': `attachment; filename=\"${name}\"`,\n 'Content-Type': isCSV ? 'text/csv; charset=utf-8' : 'application/json',\n },\n })\n }\n\n // Non-download path (buffered export)\n if (debug) {\n req.payload.logger.debug('Starting file generation')\n }\n\n // Create export batch processor\n const processor = createExportBatchProcessor({ batchSize, debug })\n\n // Transform function based on format\n const transformDoc = (doc: unknown) =>\n isCSV\n ? filterDisabledCSV(\n flattenObject({\n doc,\n fields,\n toCSVFunctions,\n }),\n )\n : filterDisabledJSON(doc)\n\n // Skip fetching if access was denied - we'll create an empty export\n let exportResult = {\n columns: [] as string[],\n docs: [] as Record<string, unknown>[],\n fetchedCount: 0,\n }\n\n if (!accessDenied) {\n exportResult = await processor.processExport({\n collectionSlug,\n findArgs: findArgs as ExportFindArgs,\n format,\n maxDocs:\n typeof maxExportDocuments === 'number' ? maxExportDocuments : Number.POSITIVE_INFINITY,\n req,\n startPage: adjustedPage,\n transformDoc,\n })\n }\n\n const { columns: dataColumns, docs: rows } = exportResult\n const outputData: string[] = []\n\n // Prepare final output\n if (isCSV) {\n // Get schema-based columns for consistent ordering\n const localeCodes =\n locale === 'all' && payload.config.localization\n ? payload.config.localization.localeCodes\n : undefined\n\n const schemaColumns = getSchemaColumns({\n collectionConfig,\n disabledFields,\n fields,\n locale,\n localeCodes,\n })\n\n // Merge schema columns with data-discovered columns\n // Schema provides ordering, data provides additional columns (e.g., array indices > 0)\n const finalColumns = mergeColumns(schemaColumns, dataColumns)\n\n const paddedRows = rows.map((row) => {\n const fullRow: Record<string, unknown> = {}\n for (const col of finalColumns) {\n fullRow[col] = row[col] ?? ''\n }\n return fullRow\n })\n\n // Always output CSV with header, even if empty\n outputData.push(\n stringify(paddedRows, {\n bom: true,\n header: true,\n columns: finalColumns,\n }),\n )\n } else {\n // JSON format\n outputData.push(rows.map((doc) => JSON.stringify(doc)).join(',\\n'))\n }\n\n // Ensure we always have valid content for the file\n // For JSON, empty exports produce \"[]\"\n // For CSV, if completely empty (no columns, no rows), produce at least a newline to ensure file creation\n const content = format === 'json' ? `[${outputData.join(',')}]` : outputData.join('')\n const buffer = Buffer.from(content.length > 0 ? content : '\\n')\n if (debug) {\n req.payload.logger.debug(`${format} file generation complete`)\n }\n\n if (!id) {\n if (debug) {\n req.payload.logger.debug('Creating new export file')\n }\n req.file = {\n name,\n data: buffer,\n mimetype: isCSV ? 'text/csv; charset=utf-8' : 'application/json',\n size: buffer.length,\n }\n } else {\n if (debug) {\n req.payload.logger.debug({\n msg: '[createExport] Updating export document with file',\n exportDocId: id,\n exportCollection,\n fileName: name,\n fileSize: buffer.length,\n mimeType: isCSV ? 'text/csv; charset=utf-8' : 'application/json',\n })\n }\n try {\n await req.payload.update({\n id,\n collection: exportCollection,\n data: {},\n file: {\n name,\n data: buffer,\n mimetype: isCSV ? 'text/csv; charset=utf-8' : 'application/json',\n size: buffer.length,\n },\n // Override access only here so that we can be sure the export collection itself is updated as expected\n overrideAccess: true,\n req,\n })\n } catch (error) {\n const errorDetails =\n error instanceof Error\n ? {\n message: error.message,\n name: error.name,\n stack: error.stack,\n // @ts-expect-error - data might exist on Payload errors\n data: error.data,\n }\n : error\n req.payload.logger.error({\n msg: '[createExport] Failed to update export document with file',\n err: errorDetails,\n exportDocId: id,\n exportCollection,\n fileName: name,\n })\n throw error\n }\n }\n if (debug) {\n req.payload.logger.debug('Export process completed successfully')\n }\n}\n"],"names":["stringify","APIError","Readable","buildDisabledFieldRegex","flattenObject","getExportFieldFunctions","getFilename","getSchemaColumns","mergeColumns","getSelect","validateLimitValue","createExportBatchProcessor","createExport","args","id","name","nameArg","batchSize","collectionSlug","debug","download","drafts","draftsFromInput","exportCollection","fields","format","limit","incomingLimit","maxLimit","locale","localeFromInput","page","req","sort","userCollection","userID","where","whereFromInput","localeFromReq","payload","logger","msg","exportDocId","exportName","draft","collectionConfig","config","collections","find","slug","user","findByID","collection","overrideAccess","hasVersions","Boolean","versions","publishedWhere","_status","equals","and","baseName","isCSV","select","Array","isArray","length","undefined","message","maxExportDocuments","Math","min","totalDocs","accessDenied","countResult","count","error","totalPages","max","ceil","requestedPage","adjustedPage","findArgs","depth","toCSVFunctions","flattenedFields","disabledFields","admin","custom","disabledMatchers","map","filterDisabledCSV","row","filtered","key","value","Object","entries","isDisabled","some","matcher","test","filterDisabledJSON","doc","parentPath","item","currentPath","includes","limitErrorMsg","t","schemaColumns","localeCodes","localization","columnCount","allColumns","columnsFinalized","encoder","TextEncoder","isFirstBatch","currentBatchPage","fetched","maxDocs","Number","POSITIVE_INFINITY","stream","read","remaining","push","encode","result","docs","batchRows","dataColumns","seenCols","Set","keys","has","add","dataColumnsCount","finalColumnsCount","paddedRows","fullRow","col","csvString","bom","header","columns","batchJSON","JSON","join","hasNextPage","Response","toWeb","headers","processor","transformDoc","exportResult","fetchedCount","processExport","startPage","rows","outputData","finalColumns","content","buffer","Buffer","from","file","data","mimetype","size","fileName","fileSize","mimeType","update","errorDetails","Error","stack","err"],"mappings":"AAAA,6CAA6C,GAG7C,SAASA,SAAS,QAAQ,qBAAoB;AAC9C,SAASC,QAAQ,QAAQ,UAAS;AAClC,SAASC,QAAQ,QAAQ,SAAQ;AAEjC,SAASC,uBAAuB,QAAQ,0CAAyC;AACjF,SAASC,aAAa,QAAQ,gCAA+B;AAC7D,SAASC,uBAAuB,QAAQ,0CAAyC;AACjF,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,gBAAgB,EAAEC,YAAY,QAAQ,mCAAkC;AACjF,SAASC,SAAS,QAAQ,4BAA2B;AACrD,SAASC,kBAAkB,QAAQ,qCAAoC;AACvE,SAASC,0BAA0B,QAA6B,sBAAqB;AA0CrF,OAAO,MAAMC,eAAe,OAAOC;IACjC,MAAM,EACJC,EAAE,EACFC,MAAMC,OAAO,EACbC,YAAY,GAAG,EACfC,cAAc,EACdC,QAAQ,KAAK,EACbC,QAAQ,EACRC,QAAQC,eAAe,EACvBC,gBAAgB,EAChBC,MAAM,EACNC,MAAM,EACNC,OAAOC,aAAa,EACpBC,QAAQ,EACRC,QAAQC,eAAe,EACvBC,IAAI,EACJC,GAAG,EACHC,IAAI,EACJC,cAAc,EACdC,MAAM,EACNC,OAAOC,iBAAiB,CAAC,CAAC,EAC3B,GAAGxB;IACJ,MAAM,EAAEgB,QAAQS,aAAa,EAAEC,OAAO,EAAE,GAAGP;IAE3C,IAAIb,OAAO;QACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;YACvBsB,KAAK;YACLC,aAAa5B;YACb6B,YAAY3B;YACZE;YACAK;YACAqB,OAAOtB;YACPE;YACAC;QACF;IACF;IAEA,MAAMI,SAASC,mBAAmBQ;IAClC,MAAMO,mBAAmBN,QAAQO,MAAM,CAACC,WAAW,CAACC,IAAI,CAAC,CAAC,EAAEC,IAAI,EAAE,GAAKA,SAAS/B;IAEhF,IAAI,CAAC2B,kBAAkB;QACrB,MAAM,IAAI5C,SAAS,CAAC,qBAAqB,EAAEiB,eAAe,WAAW,CAAC;IACxE;IAEA,IAAIgC;IAEJ,IAAIhB,kBAAkBC,QAAQ;QAC5Be,OAAQ,MAAMlB,IAAIO,OAAO,CAACY,QAAQ,CAAC;YACjCrC,IAAIqB;YACJiB,YAAYlB;YACZmB,gBAAgB;QAClB;IACF;IAEA,IAAI,CAACH,QAAQlB,IAAIkB,IAAI,EAAE;QACrBA,OAAOlB,KAAKkB,MAAMpC,KAAKkB,IAAIkB,IAAI,GAAGlB,KAAKkB,MAAMA;IAC/C;IAEA,IAAI,CAACA,MAAM;QACT,MAAM,IAAIjD,SAAS;IACrB;IAEA,MAAM2C,QAAQtB,oBAAoB;IAClC,MAAMgC,cAAcC,QAAQV,iBAAiBW,QAAQ;IAErD,mDAAmD;IACnD,MAAMC,iBAAwBH,cAAc;QAAEI,SAAS;YAAEC,QAAQ;QAAY;IAAE,IAAI,CAAC;IAEpF,MAAMvB,QAAe;QACnBwB,KAAK;YAACvB;YAAgBO,QAAQ,CAAC,IAAIa;SAAe;IACpD;IAEA,MAAMI,WAAW7C,WAAWV;IAC5B,MAAMS,OAAO,GAAG8C,SAAS,CAAC,EAAE3C,eAAe,CAAC,EAAEO,QAAQ;IACtD,MAAMqC,QAAQrC,WAAW;IACzB,MAAMsC,SAASC,MAAMC,OAAO,CAACzC,WAAWA,OAAO0C,MAAM,GAAG,IAAIzD,UAAUe,UAAU2C;IAEhF,IAAIhD,OAAO;QACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;YAAEiD,SAAS;YAAyBrD;YAAM+C;YAAOjC;QAAO;IACnF;IAEA,sCAAsC;IACtC,0DAA0D;IAC1D,sEAAsE;IACtE,IAAIwC;IAEJ,IAAI,OAAOzC,aAAa,YAAYA,WAAW,GAAG;QAChD,IAAI,OAAOD,kBAAkB,YAAYA,gBAAgB,GAAG;YAC1D,+CAA+C;YAC/C0C,qBAAqBC,KAAKC,GAAG,CAAC5C,eAAeC;QAC/C,OAAO;YACL,8CAA8C;YAC9CyC,qBAAqBzC;QACvB;IACF,OAAO;QACL,6CAA6C;QAC7CyC,qBACE,OAAO1C,kBAAkB,YAAYA,gBAAgB,IAAIA,gBAAgBwC;IAC7E;IAEA,qEAAqE;IACrE,IAAIK,YAAY;IAChB,IAAIC,eAAe;IACnB,IAAI;QACF,MAAMC,cAAc,MAAMnC,QAAQoC,KAAK,CAAC;YACtCvB,YAAYlC;YACZgC;YACArB;YACAwB,gBAAgB;QAClB;QACAmB,YAAYE,YAAYF,SAAS;IACnC,EAAE,OAAOI,OAAO;QACd,uDAAuD;QACvD,oCAAoC;QACpCH,eAAe;QACf,IAAItD,OAAO;YACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;gBACvBiD,SAAS;gBACTlD;YACF;QACF;IACF;IAEA,MAAM2D,aAAaP,KAAKQ,GAAG,CAAC,GAAGR,KAAKS,IAAI,CAACP,YAAYvD;IACrD,MAAM+D,gBAAgBjD,QAAQ;IAC9B,MAAMkD,eAAeD,gBAAgBH,aAAa,IAAIG;IAEtD,MAAME,WAAW;QACf9B,YAAYlC;QACZiE,OAAO;QACPvC;QACAlB,OAAOT;QACPY;QACAwB,gBAAgB;QAChBtB,MAAM;QACNgC;QACA9B;QACAiB;QACAd;IACF;IAEA,IAAIjB,OAAO;QACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;YAAEiD,SAAS;YAAmBc;QAAS;IAClE;IAEA,MAAME,iBAAiB/E,wBAAwB;QAC7CmB,QAAQqB,iBAAiBwC,eAAe;IAC1C;IAEA,MAAMC,iBACJzC,iBAAiB0C,KAAK,EAAEC,QAAQ,CAAC,uBAAuB,EAAEF,kBAAkB,EAAE;IAEhF,MAAMG,mBAAmBH,eAAeI,GAAG,CAACvF;IAE5C,MAAMwF,oBAAoB,CAACC;QACzB,MAAMC,WAAoC,CAAC;QAE3C,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACL,KAAM;YAC9C,MAAMM,aAAaT,iBAAiBU,IAAI,CAAC,CAACC,UAAYA,QAAQC,IAAI,CAACP;YACnE,IAAI,CAACI,YAAY;gBACfL,QAAQ,CAACC,IAAI,GAAGC;YAClB;QACF;QAEA,OAAOF;IACT;IAEA,MAAMS,qBAAqB,CAACC,KAAUC,aAAa,EAAE;QACnD,IAAIxC,MAAMC,OAAO,CAACsC,MAAM;YACtB,OAAOA,IAAIb,GAAG,CAAC,CAACe,OAASH,mBAAmBG,MAAMD;QACpD;QAEA,IAAI,OAAOD,QAAQ,YAAYA,QAAQ,MAAM;YAC3C,OAAOA;QACT;QAEA,MAAMV,WAAgC,CAAC;QACvC,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACM,KAAM;YAC9C,MAAMG,cAAcF,aAAa,GAAGA,WAAW,CAAC,EAAEV,KAAK,GAAGA;YAE1D,6CAA6C;YAC7C,MAAMI,aAAaZ,eAAeqB,QAAQ,CAACD;YAE3C,IAAI,CAACR,YAAY;gBACfL,QAAQ,CAACC,IAAI,GAAGQ,mBAAmBP,OAAOW;YAC5C;QACF;QAEA,OAAOb;IACT;IAEA,IAAIzE,UAAU;QACZ,MAAMwF,gBAAgBlG,mBAAmBiB,eAAeK,IAAI6E,CAAC;QAC7D,IAAID,eAAe;YACjB,MAAM,IAAI3G,SAAS2G;QACrB;QAEA,oFAAoF;QACpF,IAAIE,gBAA0B,EAAE;QAChC,IAAIhD,OAAO;YACT,MAAMiD,cACJlF,WAAW,SAASU,QAAQO,MAAM,CAACkE,YAAY,GAC3CzE,QAAQO,MAAM,CAACkE,YAAY,CAACD,WAAW,GACvC5C;YAEN2C,gBAAgBvG,iBAAiB;gBAC/BsC;gBACAyC;gBACA9D;gBACAK;gBACAkF;YACF;YAEA,IAAI5F,OAAO;gBACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;oBACvB8F,aAAaH,cAAc5C,MAAM;oBACjCzB,KAAK;gBACP;YACF;QACF;QAEA,gFAAgF;QAChF,IAAIyE,aAAuB,EAAE;QAC7B,IAAIC,mBAAmB;QAEvB,MAAMC,UAAU,IAAIC;QACpB,IAAIC,eAAe;QACnB,IAAIC,mBAAmBtC;QACvB,IAAIuC,UAAU;QACd,MAAMC,UACJ,OAAOpD,uBAAuB,WAAWA,qBAAqBqD,OAAOC,iBAAiB;QAExF,MAAMC,SAAS,IAAI1H,SAAS;YAC1B,MAAM2H;gBACJ,MAAMC,YAAYxD,KAAKQ,GAAG,CAAC,GAAG2C,UAAUD;gBAExC,IAAIM,cAAc,GAAG;oBACnB,IAAI,CAAChE,OAAO;wBACV,6EAA6E;wBAC7E,IAAI,CAACiE,IAAI,CAACX,QAAQY,MAAM,CAACV,eAAe,OAAO;oBACjD;oBACA,IAAI,CAACS,IAAI,CAAC;oBACV;gBACF;gBAEA,MAAME,SAAS,MAAM1F,QAAQS,IAAI,CAAC;oBAChC,GAAGkC,QAAQ;oBACXnD,MAAMwF;oBACN7F,OAAO4C,KAAKC,GAAG,CAACtD,WAAW6G;gBAC7B;gBAEA,IAAI3G,OAAO;oBACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CACtB,CAAC,gBAAgB,EAAEoG,iBAAiB,MAAM,EAAEU,OAAOC,IAAI,CAAChE,MAAM,CAAC,KAAK,CAAC;gBAEzE;gBAEA,IAAI+D,OAAOC,IAAI,CAAChE,MAAM,KAAK,GAAG;oBAC5B,oCAAoC;oBACpC,IAAI,CAACJ,OAAO;wBACV,wEAAwE;wBACxE,IAAI,CAACiE,IAAI,CAACX,QAAQY,MAAM,CAACV,eAAe,OAAO;oBACjD;oBACA,IAAI,CAACS,IAAI,CAAC;oBACV;gBACF;gBAEA,IAAIjE,OAAO;oBACT,wBAAwB;oBACxB,MAAMqE,YAAYF,OAAOC,IAAI,CAACxC,GAAG,CAAC,CAACa,MACjCZ,kBACEvF,cAAc;4BACZmG;4BACA/E;4BACA4D;wBACF;oBAIJ,8EAA8E;oBAC9E,IAAI,CAAC+B,kBAAkB;wBACrB,MAAMiB,cAAwB,EAAE;wBAChC,MAAMC,WAAW,IAAIC;wBACrB,KAAK,MAAM1C,OAAOuC,UAAW;4BAC3B,KAAK,MAAMrC,OAAOE,OAAOuC,IAAI,CAAC3C,KAAM;gCAClC,IAAI,CAACyC,SAASG,GAAG,CAAC1C,MAAM;oCACtBuC,SAASI,GAAG,CAAC3C;oCACbsC,YAAYL,IAAI,CAACjC;gCACnB;4BACF;wBACF;wBACA,oDAAoD;wBACpDoB,aAAa1G,aAAasG,eAAesB;wBACzCjB,mBAAmB;wBAEnB,IAAIhG,OAAO;4BACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;gCACvBuH,kBAAkBN,YAAYlE,MAAM;gCACpCyE,mBAAmBzB,WAAWhD,MAAM;gCACpCzB,KAAK;4BACP;wBACF;oBACF;oBAEA,MAAMmG,aAAaT,UAAUzC,GAAG,CAAC,CAACE;wBAChC,MAAMiD,UAAmC,CAAC;wBAC1C,KAAK,MAAMC,OAAO5B,WAAY;4BAC5B2B,OAAO,CAACC,IAAI,GAAGlD,GAAG,CAACkD,IAAI,IAAI;wBAC7B;wBACA,OAAOD;oBACT;oBAEA,MAAME,YAAY/I,UAAU4I,YAAY;wBACtCI,KAAK1B;wBACL2B,QAAQ3B;wBACR4B,SAAShC;oBACX;oBAEA,IAAI,CAACa,IAAI,CAACX,QAAQY,MAAM,CAACe;gBAC3B,OAAO;oBACL,yBAAyB;oBACzB,MAAMZ,YAAYF,OAAOC,IAAI,CAACxC,GAAG,CAAC,CAACa,MAAQD,mBAAmBC;oBAE9D,uDAAuD;oBACvD,MAAM4C,YAAYhB,UAAUzC,GAAG,CAAC,CAACE,MAAQwD,KAAKpJ,SAAS,CAAC4F,MAAMyD,IAAI,CAAC;oBAEnE,IAAI/B,cAAc;wBAChB,IAAI,CAACS,IAAI,CAACX,QAAQY,MAAM,CAAC,MAAMmB;oBACjC,OAAO;wBACL,IAAI,CAACpB,IAAI,CAACX,QAAQY,MAAM,CAAC,MAAMmB;oBACjC;gBACF;gBAEA3B,WAAWS,OAAOC,IAAI,CAAChE,MAAM;gBAC7BoD,eAAe;gBACfC,oBAAoB;gBAEpB,IAAI,CAACU,OAAOqB,WAAW,IAAI9B,WAAWC,SAAS;oBAC7C,IAAItG,OAAO;wBACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;oBAC3B;oBACA,IAAI,CAAC2C,OAAO;wBACV,IAAI,CAACiE,IAAI,CAACX,QAAQY,MAAM,CAAC;oBAC3B;oBACA,IAAI,CAACD,IAAI,CAAC,OAAM,iBAAiB;gBACnC;YACF;QACF;QAEA,OAAO,IAAIwB,SAASrJ,SAASsJ,KAAK,CAAC5B,SAA2B;YAC5D6B,SAAS;gBACP,uBAAuB,CAAC,sBAAsB,EAAE1I,KAAK,CAAC,CAAC;gBACvD,gBAAgB+C,QAAQ,4BAA4B;YACtD;QACF;IACF;IAEA,sCAAsC;IACtC,IAAI3C,OAAO;QACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;IAC3B;IAEA,gCAAgC;IAChC,MAAMuI,YAAY/I,2BAA2B;QAAEM;QAAWE;IAAM;IAEhE,qCAAqC;IACrC,MAAMwI,eAAe,CAACpD,MACpBzC,QACI6B,kBACEvF,cAAc;YACZmG;YACA/E;YACA4D;QACF,MAEFkB,mBAAmBC;IAEzB,oEAAoE;IACpE,IAAIqD,eAAe;QACjBV,SAAS,EAAE;QACXhB,MAAM,EAAE;QACR2B,cAAc;IAChB;IAEA,IAAI,CAACpF,cAAc;QACjBmF,eAAe,MAAMF,UAAUI,aAAa,CAAC;YAC3C5I;YACAgE,UAAUA;YACVzD;YACAgG,SACE,OAAOpD,uBAAuB,WAAWA,qBAAqBqD,OAAOC,iBAAiB;YACxF3F;YACA+H,WAAW9E;YACX0E;QACF;IACF;IAEA,MAAM,EAAET,SAASd,WAAW,EAAEF,MAAM8B,IAAI,EAAE,GAAGJ;IAC7C,MAAMK,aAAuB,EAAE;IAE/B,uBAAuB;IACvB,IAAInG,OAAO;QACT,mDAAmD;QACnD,MAAMiD,cACJlF,WAAW,SAASU,QAAQO,MAAM,CAACkE,YAAY,GAC3CzE,QAAQO,MAAM,CAACkE,YAAY,CAACD,WAAW,GACvC5C;QAEN,MAAM2C,gBAAgBvG,iBAAiB;YACrCsC;YACAyC;YACA9D;YACAK;YACAkF;QACF;QAEA,oDAAoD;QACpD,uFAAuF;QACvF,MAAMmD,eAAe1J,aAAasG,eAAesB;QAEjD,MAAMQ,aAAaoB,KAAKtE,GAAG,CAAC,CAACE;YAC3B,MAAMiD,UAAmC,CAAC;YAC1C,KAAK,MAAMC,OAAOoB,aAAc;gBAC9BrB,OAAO,CAACC,IAAI,GAAGlD,GAAG,CAACkD,IAAI,IAAI;YAC7B;YACA,OAAOD;QACT;QAEA,+CAA+C;QAC/CoB,WAAWlC,IAAI,CACb/H,UAAU4I,YAAY;YACpBI,KAAK;YACLC,QAAQ;YACRC,SAASgB;QACX;IAEJ,OAAO;QACL,cAAc;QACdD,WAAWlC,IAAI,CAACiC,KAAKtE,GAAG,CAAC,CAACa,MAAQ6C,KAAKpJ,SAAS,CAACuG,MAAM8C,IAAI,CAAC;IAC9D;IAEA,mDAAmD;IACnD,uCAAuC;IACvC,yGAAyG;IACzG,MAAMc,UAAU1I,WAAW,SAAS,CAAC,CAAC,EAAEwI,WAAWZ,IAAI,CAAC,KAAK,CAAC,CAAC,GAAGY,WAAWZ,IAAI,CAAC;IAClF,MAAMe,SAASC,OAAOC,IAAI,CAACH,QAAQjG,MAAM,GAAG,IAAIiG,UAAU;IAC1D,IAAIhJ,OAAO;QACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC,GAAGM,OAAO,yBAAyB,CAAC;IAC/D;IAEA,IAAI,CAACX,IAAI;QACP,IAAIK,OAAO;YACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;QAC3B;QACAa,IAAIuI,IAAI,GAAG;YACTxJ;YACAyJ,MAAMJ;YACNK,UAAU3G,QAAQ,4BAA4B;YAC9C4G,MAAMN,OAAOlG,MAAM;QACrB;IACF,OAAO;QACL,IAAI/C,OAAO;YACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;gBACvBsB,KAAK;gBACLC,aAAa5B;gBACbS;gBACAoJ,UAAU5J;gBACV6J,UAAUR,OAAOlG,MAAM;gBACvB2G,UAAU/G,QAAQ,4BAA4B;YAChD;QACF;QACA,IAAI;YACF,MAAM9B,IAAIO,OAAO,CAACuI,MAAM,CAAC;gBACvBhK;gBACAsC,YAAY7B;gBACZiJ,MAAM,CAAC;gBACPD,MAAM;oBACJxJ;oBACAyJ,MAAMJ;oBACNK,UAAU3G,QAAQ,4BAA4B;oBAC9C4G,MAAMN,OAAOlG,MAAM;gBACrB;gBACA,uGAAuG;gBACvGb,gBAAgB;gBAChBrB;YACF;QACF,EAAE,OAAO4C,OAAO;YACd,MAAMmG,eACJnG,iBAAiBoG,QACb;gBACE5G,SAASQ,MAAMR,OAAO;gBACtBrD,MAAM6D,MAAM7D,IAAI;gBAChBkK,OAAOrG,MAAMqG,KAAK;gBAClB,wDAAwD;gBACxDT,MAAM5F,MAAM4F,IAAI;YAClB,IACA5F;YACN5C,IAAIO,OAAO,CAACC,MAAM,CAACoC,KAAK,CAAC;gBACvBnC,KAAK;gBACLyI,KAAKH;gBACLrI,aAAa5B;gBACbS;gBACAoJ,UAAU5J;YACZ;YACA,MAAM6D;QACR;IACF;IACA,IAAIzD,OAAO;QACTa,IAAIO,OAAO,CAACC,MAAM,CAACrB,KAAK,CAAC;IAC3B;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/export/createExport.ts"],"sourcesContent":["/* eslint-disable perfectionist/sort-objects */\nimport type { PayloadRequest, Sort, TypedUser, Where } from 'payload'\n\nimport { stringify } from 'csv-stringify/sync'\nimport { APIError } from 'payload'\nimport { Readable } from 'stream'\n\nimport { applyFieldHooks } from '../utilities/applyFieldHooks.js'\nimport { buildDisabledFieldRegex } from '../utilities/buildDisabledFieldRegex.js'\nimport { flattenObject } from '../utilities/flattenObject.js'\nimport { getExportFieldFunctions } from '../utilities/getExportFieldFunctions.js'\nimport { getFilename } from '../utilities/getFilename.js'\nimport { getSchemaColumns, mergeColumns } from '../utilities/getSchemaColumns.js'\nimport { getSelect } from '../utilities/getSelect.js'\nimport { validateLimitValue } from '../utilities/validateLimitValue.js'\nimport { createExportBatchProcessor, type ExportFindArgs } from './batchProcessor.js'\n\nexport type Export = {\n /**\n * Number of documents to process in each batch during export\n * @default 100\n */\n batchSize?: number\n collectionSlug: string\n /**\n * If true, enables debug logging\n */\n debug?: boolean\n drafts?: 'no' | 'yes'\n exportCollection: string\n fields?: string[]\n format: 'csv' | 'json'\n globals?: string[]\n id: number | string\n limit?: number\n locale?: string\n /**\n * Maximum number of documents that can be exported in a single operation.\n * This value has already been resolved from the plugin config.\n */\n maxLimit?: number\n name: string\n page?: number\n sort?: Sort\n userCollection: string\n userID: number | string\n where?: Where\n}\n\nexport type CreateExportArgs = {\n /**\n * If true, stream the file instead of saving it\n */\n download?: boolean\n req: PayloadRequest\n} & Export\n\nexport const createExport = async (args: CreateExportArgs) => {\n const {\n id,\n name: nameArg,\n batchSize = 100,\n collectionSlug,\n debug = false,\n download,\n drafts: draftsFromInput,\n exportCollection,\n fields,\n format,\n limit: incomingLimit,\n maxLimit,\n locale: localeFromInput,\n page,\n req,\n sort,\n userCollection,\n userID,\n where: whereFromInput = {},\n } = args\n const { locale: localeFromReq, payload } = req\n\n if (debug) {\n req.payload.logger.debug({\n msg: '[createExport] Starting export process',\n exportDocId: id,\n exportName: nameArg,\n collectionSlug,\n exportCollection,\n draft: draftsFromInput,\n fields,\n format,\n })\n }\n\n const locale = localeFromInput ?? localeFromReq\n const collectionConfig = payload.config.collections.find(({ slug }) => slug === collectionSlug)\n\n if (!collectionConfig) {\n throw new APIError(`Collection with slug ${collectionSlug} not found.`)\n }\n\n let user: TypedUser | undefined\n\n if (userCollection && userID) {\n user = (await req.payload.findByID({\n id: userID,\n collection: userCollection,\n overrideAccess: true,\n })) as TypedUser\n }\n\n if (!user && req.user) {\n user = req?.user?.id ? req.user : req?.user?.user\n }\n\n if (!user) {\n throw new APIError('User authentication is required to create exports.')\n }\n\n const draft = draftsFromInput === 'yes'\n const hasVersions = Boolean(collectionConfig.versions)\n\n // Only filter by _status for versioned collections\n const publishedWhere: Where = hasVersions ? { _status: { equals: 'published' } } : {}\n\n const where: Where = {\n and: [whereFromInput, draft ? {} : publishedWhere],\n }\n\n const baseName = nameArg ?? getFilename()\n const name = `${baseName}-${collectionSlug}.${format}`\n const isCSV = format === 'csv'\n const select = Array.isArray(fields) && fields.length > 0 ? getSelect(fields) : undefined\n\n if (debug) {\n req.payload.logger.debug({ isCSV, locale, msg: 'Export configuration:', name })\n }\n\n // Determine maximum export documents:\n // 1. If maxLimit is defined, it sets the absolute ceiling\n // 2. User's limit is applied but clamped to maxLimit if it exceeds it\n let maxExportDocuments: number | undefined\n\n if (typeof maxLimit === 'number' && maxLimit > 0) {\n if (typeof incomingLimit === 'number' && incomingLimit > 0) {\n // User provided a limit - clamp it to maxLimit\n maxExportDocuments = Math.min(incomingLimit, maxLimit)\n } else {\n // No user limit - use maxLimit as the ceiling\n maxExportDocuments = maxLimit\n }\n } else {\n // No maxLimit - use user's limit if provided\n maxExportDocuments =\n typeof incomingLimit === 'number' && incomingLimit > 0 ? incomingLimit : undefined\n }\n\n // Try to count documents - if access is denied, treat as 0 documents\n let totalDocs = 0\n let accessDenied = false\n try {\n const countResult = await payload.count({\n collection: collectionSlug,\n user,\n locale,\n overrideAccess: false,\n })\n totalDocs = countResult.totalDocs\n } catch (error) {\n // Access denied - user can't read from this collection\n // We'll create an empty export file\n accessDenied = true\n if (debug) {\n req.payload.logger.debug({\n collectionSlug,\n msg: 'Access denied for collection, creating empty export',\n })\n }\n }\n\n const totalPages = Math.max(1, Math.ceil(totalDocs / batchSize))\n const requestedPage = page || 1\n const adjustedPage = requestedPage > totalPages ? 1 : requestedPage\n\n const findArgs = {\n collection: collectionSlug,\n depth: 1,\n draft,\n limit: batchSize,\n locale,\n overrideAccess: false,\n page: 0,\n select,\n sort,\n user,\n where,\n }\n\n if (debug) {\n req.payload.logger.debug({ findArgs, msg: 'Find arguments:' })\n }\n\n const exportFieldHooks = getExportFieldFunctions({\n fields: collectionConfig.flattenedFields,\n })\n\n const exportHooks = collectionConfig.custom?.['plugin-import-export']?.exportHooks\n\n const disabledFields =\n collectionConfig.admin?.custom?.['plugin-import-export']?.disabledFields ?? []\n\n const disabledMatchers = disabledFields.map(buildDisabledFieldRegex)\n\n const filterDisabledCSV = (row: Record<string, unknown>): Record<string, unknown> => {\n const filtered: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(row)) {\n const isDisabled = disabledMatchers.some((matcher) => matcher.test(key))\n if (!isDisabled) {\n filtered[key] = value\n }\n }\n\n return filtered\n }\n\n const filterDisabledJSON = (doc: unknown, parentPath = ''): unknown => {\n if (Array.isArray(doc)) {\n return doc.map((item) => filterDisabledJSON(item, parentPath))\n }\n\n if (typeof doc !== 'object' || doc === null) {\n return doc\n }\n\n const filtered: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(doc as Record<string, unknown>)) {\n const currentPath = parentPath ? `${parentPath}.${key}` : key\n\n // Only remove if this exact path is disabled\n const isDisabled = disabledFields.includes(currentPath)\n\n if (!isDisabled) {\n filtered[key] = filterDisabledJSON(value, currentPath)\n }\n }\n\n return filtered\n }\n\n if (download) {\n const limitErrorMsg = validateLimitValue(incomingLimit, req.t)\n if (limitErrorMsg) {\n throw new APIError(limitErrorMsg)\n }\n\n // Get schema-based columns first (provides base ordering and handles empty exports)\n let schemaColumns: string[] = []\n if (isCSV) {\n const localeCodes =\n locale === 'all' && payload.config.localization\n ? payload.config.localization.localeCodes\n : undefined\n\n schemaColumns = getSchemaColumns({\n collectionConfig,\n disabledFields,\n fields,\n locale,\n localeCodes,\n })\n\n if (debug) {\n req.payload.logger.debug({\n columnCount: schemaColumns.length,\n msg: 'Schema-based column inference complete',\n })\n }\n }\n\n // allColumns will be finalized after first batch (schema + data columns merged)\n let allColumns: string[] = []\n let columnsFinalized = false\n\n const encoder = new TextEncoder()\n let isFirstBatch = true\n let currentBatchPage = adjustedPage\n let fetched = 0\n const maxDocs =\n typeof maxExportDocuments === 'number' ? maxExportDocuments : Number.POSITIVE_INFINITY\n\n const effectiveStreamDocs =\n typeof maxExportDocuments === 'number' ? Math.min(totalDocs, maxExportDocuments) : totalDocs\n const totalBatches = effectiveStreamDocs > 0 ? Math.ceil(effectiveStreamDocs / batchSize) : 1\n let streamBatchNumber = 0\n\n const stream = new Readable({\n async read() {\n const remaining = Math.max(0, maxDocs - fetched)\n\n if (remaining === 0) {\n if (!isCSV) {\n // If first batch with no remaining, output empty array; otherwise just close\n this.push(encoder.encode(isFirstBatch ? '[]' : ']'))\n }\n this.push(null)\n return\n }\n\n const result = await payload.find({\n ...findArgs,\n page: currentBatchPage,\n limit: Math.min(batchSize, remaining),\n })\n\n if (debug) {\n req.payload.logger.debug(\n `Streaming batch ${currentBatchPage} with ${result.docs.length} docs`,\n )\n }\n\n if (result.docs.length === 0) {\n // Close JSON array properly if JSON\n if (!isCSV) {\n // If first batch with no docs, output empty array; otherwise just close\n this.push(encoder.encode(isFirstBatch ? '[]' : ']'))\n }\n this.push(null)\n return\n }\n\n streamBatchNumber++\n\n if (isCSV) {\n // --- CSV Streaming ---\n const batchRows = result.docs.map((doc) =>\n filterDisabledCSV(\n flattenObject({\n data: doc as Record<string, unknown>,\n fields,\n format,\n exportFieldHooks,\n req,\n }),\n ),\n )\n\n const originalDocs = result.docs as Record<string, unknown>[]\n let batchRowsToWrite = batchRows\n if (exportHooks?.before && batchRows.length > 0) {\n batchRowsToWrite = await exportHooks.before({\n batchNumber: streamBatchNumber,\n data: batchRows,\n format,\n originalData: originalDocs,\n req,\n totalBatches,\n })\n }\n\n // On first batch, discover additional columns from data and merge with schema\n if (!columnsFinalized) {\n const dataColumns: string[] = []\n const seenCols = new Set<string>()\n for (const row of batchRowsToWrite) {\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 // Merge schema columns with data-discovered columns.\n // When a before hook is active and rows exist, restrict to columns actually present\n // in the data so that the hook can remove fields by not returning them.\n const mergedColumns = mergeColumns(schemaColumns, dataColumns)\n allColumns =\n Boolean(exportHooks?.before) && batchRowsToWrite.length > 0\n ? mergedColumns.filter((col) => dataColumns.includes(col))\n : mergedColumns\n columnsFinalized = true\n\n if (debug) {\n req.payload.logger.debug({\n dataColumnsCount: dataColumns.length,\n finalColumnsCount: allColumns.length,\n msg: 'Merged schema and data columns',\n })\n }\n }\n\n const paddedRows = batchRowsToWrite.map((row) => {\n const fullRow: Record<string, unknown> = {}\n for (const col of allColumns) {\n fullRow[col] = row[col] ?? ''\n }\n return fullRow\n })\n\n const csvString = stringify(paddedRows, {\n bom: isFirstBatch,\n header: isFirstBatch,\n columns: allColumns,\n })\n\n this.push(encoder.encode(csvString))\n\n if (exportHooks?.after && batchRowsToWrite.length > 0) {\n await exportHooks.after({\n batchNumber: streamBatchNumber,\n data: batchRowsToWrite,\n format,\n originalData: originalDocs,\n req,\n totalBatches,\n })\n }\n } else {\n // --- JSON Streaming ---\n const batchRows = result.docs.map(\n (doc) =>\n filterDisabledJSON(\n applyFieldHooks({\n data: doc as Record<string, unknown>,\n fieldHooks: exportFieldHooks,\n fields: collectionConfig.flattenedFields,\n format,\n operation: 'export',\n req,\n type: 'beforeExport',\n }),\n ) as Record<string, unknown>,\n )\n\n const originalDocs = result.docs as Record<string, unknown>[]\n let batchRowsToWrite = batchRows\n if (exportHooks?.before && batchRows.length > 0) {\n batchRowsToWrite = await exportHooks.before({\n batchNumber: streamBatchNumber,\n data: batchRows,\n format,\n originalData: originalDocs,\n req,\n totalBatches,\n })\n }\n\n // Convert each filtered/flattened row into JSON string\n const batchJSON = batchRowsToWrite.map((row) => JSON.stringify(row)).join(',')\n\n if (isFirstBatch) {\n this.push(encoder.encode('[' + batchJSON))\n } else {\n this.push(encoder.encode(',' + batchJSON))\n }\n\n if (exportHooks?.after && batchRowsToWrite.length > 0) {\n await exportHooks.after({\n batchNumber: streamBatchNumber,\n data: batchRowsToWrite,\n format,\n originalData: originalDocs,\n req,\n totalBatches,\n })\n }\n }\n\n fetched += result.docs.length\n isFirstBatch = false\n currentBatchPage += 1\n\n if (!result.hasNextPage || fetched >= maxDocs) {\n if (debug) {\n req.payload.logger.debug('Stream complete - no more pages')\n }\n if (!isCSV) {\n this.push(encoder.encode(']'))\n }\n this.push(null) // End the stream\n }\n },\n })\n\n return new Response(Readable.toWeb(stream) as ReadableStream, {\n headers: {\n 'Content-Disposition': `attachment; filename=\"${name}\"`,\n 'Content-Type': isCSV ? 'text/csv; charset=utf-8' : 'application/json',\n },\n })\n }\n\n // Non-download path (buffered export)\n if (debug) {\n req.payload.logger.debug('Starting file generation')\n }\n\n // Create export batch processor\n const processor = createExportBatchProcessor({ batchSize, debug })\n\n // Transform function based on format\n const transformDoc = (doc: unknown) =>\n isCSV\n ? filterDisabledCSV(\n flattenObject({\n data: doc as Record<string, unknown>,\n fields,\n format,\n exportFieldHooks,\n req,\n }),\n )\n : (filterDisabledJSON(\n applyFieldHooks({\n data: doc as Record<string, unknown>,\n fieldHooks: exportFieldHooks,\n fields: collectionConfig.flattenedFields,\n format,\n operation: 'export',\n req,\n type: 'beforeExport',\n }),\n ) as Record<string, unknown>)\n\n // Skip fetching if access was denied - we'll create an empty export\n let exportResult = {\n columns: [] as string[],\n docs: [] as Record<string, unknown>[],\n fetchedCount: 0,\n }\n\n if (!accessDenied) {\n exportResult = await processor.processExport({\n collectionSlug,\n findArgs: findArgs as ExportFindArgs,\n format,\n hooks: exportHooks,\n maxDocs:\n typeof maxExportDocuments === 'number' ? maxExportDocuments : Number.POSITIVE_INFINITY,\n req,\n startPage: adjustedPage,\n totalDocs,\n transformDoc,\n })\n }\n\n const { columns: dataColumns, docs: rows } = exportResult\n const outputData: string[] = []\n\n // Prepare final output\n if (isCSV) {\n // Get schema-based columns for consistent ordering\n const localeCodes =\n locale === 'all' && payload.config.localization\n ? payload.config.localization.localeCodes\n : undefined\n\n const schemaColumns = getSchemaColumns({\n collectionConfig,\n disabledFields,\n fields,\n locale,\n localeCodes,\n })\n\n // Merge schema columns with data-discovered columns\n // Schema provides ordering, data provides additional columns (e.g., array indices > 0)\n // When a before hook is active and rows exist, restrict to columns actually present in the data\n // so that the hook can remove fields by not returning them\n const mergedColumns = mergeColumns(schemaColumns, dataColumns)\n const finalColumns =\n Boolean(exportHooks?.before) && rows.length > 0\n ? mergedColumns.filter((col) => dataColumns.includes(col))\n : mergedColumns\n\n const paddedRows = rows.map((row) => {\n const fullRow: Record<string, unknown> = {}\n for (const col of finalColumns) {\n fullRow[col] = row[col] ?? ''\n }\n return fullRow\n })\n\n // Always output CSV with header, even if empty\n outputData.push(\n stringify(paddedRows, {\n bom: true,\n header: true,\n columns: finalColumns,\n }),\n )\n } else {\n // JSON format\n outputData.push(rows.map((doc) => JSON.stringify(doc)).join(',\\n'))\n }\n\n // Ensure we always have valid content for the file\n // For JSON, empty exports produce \"[]\"\n // For CSV, if completely empty (no columns, no rows), produce at least a newline to ensure file creation\n const content = format === 'json' ? `[${outputData.join(',')}]` : outputData.join('')\n const buffer = Buffer.from(content.length > 0 ? content : '\\n')\n if (debug) {\n req.payload.logger.debug(`${format} file generation complete`)\n }\n\n if (!id) {\n if (debug) {\n req.payload.logger.debug('Creating new export file')\n }\n req.file = {\n name,\n data: buffer,\n mimetype: isCSV ? 'text/csv; charset=utf-8' : 'application/json',\n size: buffer.length,\n }\n } else {\n if (debug) {\n req.payload.logger.debug({\n msg: '[createExport] Updating export document with file',\n exportDocId: id,\n exportCollection,\n fileName: name,\n fileSize: buffer.length,\n mimeType: isCSV ? 'text/csv; charset=utf-8' : 'application/json',\n })\n }\n try {\n await req.payload.update({\n id,\n collection: exportCollection,\n data: {},\n file: {\n name,\n data: buffer,\n mimetype: isCSV ? 'text/csv; charset=utf-8' : 'application/json',\n size: buffer.length,\n },\n // Override access only here so that we can be sure the export collection itself is updated as expected\n overrideAccess: true,\n req,\n })\n } catch (error) {\n const errorDetails =\n error instanceof Error\n ? {\n message: error.message,\n name: error.name,\n stack: error.stack,\n // @ts-expect-error - data might exist on Payload errors\n data: error.data,\n }\n : error\n req.payload.logger.error({\n msg: '[createExport] Failed to update export document with file',\n err: errorDetails,\n exportDocId: id,\n exportCollection,\n fileName: name,\n })\n throw error\n }\n }\n if (debug) {\n req.payload.logger.debug('Export process completed successfully')\n }\n}\n"],"names":["stringify","APIError","Readable","applyFieldHooks","buildDisabledFieldRegex","flattenObject","getExportFieldFunctions","getFilename","getSchemaColumns","mergeColumns","getSelect","validateLimitValue","createExportBatchProcessor","createExport","args","id","name","nameArg","batchSize","collectionSlug","debug","download","drafts","draftsFromInput","exportCollection","fields","format","limit","incomingLimit","maxLimit","locale","localeFromInput","page","req","sort","userCollection","userID","where","whereFromInput","localeFromReq","payload","logger","msg","exportDocId","exportName","draft","collectionConfig","config","collections","find","slug","user","findByID","collection","overrideAccess","hasVersions","Boolean","versions","publishedWhere","_status","equals","and","baseName","isCSV","select","Array","isArray","length","undefined","maxExportDocuments","Math","min","totalDocs","accessDenied","countResult","count","error","totalPages","max","ceil","requestedPage","adjustedPage","findArgs","depth","exportFieldHooks","flattenedFields","exportHooks","custom","disabledFields","admin","disabledMatchers","map","filterDisabledCSV","row","filtered","key","value","Object","entries","isDisabled","some","matcher","test","filterDisabledJSON","doc","parentPath","item","currentPath","includes","limitErrorMsg","t","schemaColumns","localeCodes","localization","columnCount","allColumns","columnsFinalized","encoder","TextEncoder","isFirstBatch","currentBatchPage","fetched","maxDocs","Number","POSITIVE_INFINITY","effectiveStreamDocs","totalBatches","streamBatchNumber","stream","read","remaining","push","encode","result","docs","batchRows","data","originalDocs","batchRowsToWrite","before","batchNumber","originalData","dataColumns","seenCols","Set","keys","has","add","mergedColumns","filter","col","dataColumnsCount","finalColumnsCount","paddedRows","fullRow","csvString","bom","header","columns","after","fieldHooks","operation","type","batchJSON","JSON","join","hasNextPage","Response","toWeb","headers","processor","transformDoc","exportResult","fetchedCount","processExport","hooks","startPage","rows","outputData","finalColumns","content","buffer","Buffer","from","file","mimetype","size","fileName","fileSize","mimeType","update","errorDetails","Error","message","stack","err"],"mappings":"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"}
@@ -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;AA2C1D,eAAO,MAAM,aAAa,QAAe,cAAc,KAAG,OAAO,CAAC,QAAQ,CAuQzE,CAAA"}
@@ -1,6 +1,7 @@
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';
@@ -9,6 +10,19 @@ import { getSelect } from '../utilities/getSelect.js';
9
10
  import { removeDisabledFields } from '../utilities/removeDisabledFields.js';
10
11
  import { resolveLimit } from '../utilities/resolveLimit.js';
11
12
  import { setNestedValue } from '../utilities/setNestedValue.js';
13
+ const applyExportBeforeHook = async (hook, data, originalDocs, format, req)=>{
14
+ if (!hook || data.length === 0) {
15
+ return data;
16
+ }
17
+ return hook({
18
+ batchNumber: 1,
19
+ data,
20
+ format,
21
+ originalData: originalDocs,
22
+ req,
23
+ totalBatches: 1
24
+ });
25
+ };
12
26
  export const handlePreview = async (req)=>{
13
27
  await addDataAndFileToRequest(req);
14
28
  const { collectionSlug, draft: draftFromReq, fields, limit: exportLimit, locale, previewLimit: rawPreviewLimit = DEFAULT_PREVIEW_LIMIT, previewPage: rawPreviewPage = 1, sort, where: whereFromReq = {} } = req.data;
@@ -123,22 +137,24 @@ export const handlePreview = async (req)=>{
123
137
  }
124
138
  // Transform docs based on format
125
139
  let transformed;
140
+ const exportFieldHooks = getExportFieldFunctions({
141
+ fields: targetCollection.config.flattenedFields
142
+ });
143
+ const exportHooks = targetCollection.config.custom?.['plugin-import-export']?.exportHooks;
126
144
  if (isCSV) {
127
- const toCSVFunctions = getExportFieldFunctions({
128
- fields: targetCollection.config.fields
129
- });
130
- const possibleKeys = getFlattenedFieldKeys(targetCollection.config.fields, '', {
145
+ const possibleKeys = getFlattenedFieldKeys(targetCollection.config.flattenedFields, '', {
131
146
  localeCodes
132
147
  });
133
148
  // Flatten docs without padding yet. This preserves the exact keys produced by toCSV hooks,
134
149
  // allowing mergeColumns to detect which schema columns were replaced with derived ones.
135
150
  transformed = docs.map((doc)=>flattenObject({
136
- doc,
151
+ data: doc,
152
+ exportFieldHooks,
137
153
  fields,
138
- toCSVFunctions
154
+ format: 'csv',
155
+ req
139
156
  }));
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
157
+ transformed = await applyExportBeforeHook(exportHooks?.before, transformed, docs, 'csv', req);
142
158
  if (schemaColumns && transformed.length > 0) {
143
159
  const dataColumns = [];
144
160
  const seenCols = new Set();
@@ -150,7 +166,8 @@ export const handlePreview = async (req)=>{
150
166
  }
151
167
  }
152
168
  }
153
- columns = mergeColumns(schemaColumns, dataColumns);
169
+ const mergedColumns = mergeColumns(schemaColumns, dataColumns);
170
+ columns = Boolean(exportHooks?.before) && transformed.length > 0 ? mergedColumns.filter((col)=>dataColumns.includes(col)) : mergedColumns;
154
171
  }
155
172
  // Pad rows with null for missing columns (uses merged columns, not raw schema)
156
173
  if (!fields || fields.length === 0) {
@@ -165,10 +182,17 @@ export const handlePreview = async (req)=>{
165
182
  }
166
183
  } else {
167
184
  transformed = docs.map((doc)=>{
168
- let output = {
169
- ...doc
170
- };
171
- // Remove disabled fields first
185
+ // Apply field-level export hooks for JSON format
186
+ let output = applyFieldHooks({
187
+ type: 'beforeExport',
188
+ data: doc,
189
+ fieldHooks: exportFieldHooks,
190
+ fields: targetCollection.config.flattenedFields,
191
+ format: 'json',
192
+ operation: 'export',
193
+ req
194
+ });
195
+ // Remove disabled fields
172
196
  output = removeDisabledFields(output, disabledFields);
173
197
  // Then trim to selected fields only (if fields are provided)
174
198
  if (Array.isArray(fields) && fields.length > 0) {
@@ -181,6 +205,7 @@ export const handlePreview = async (req)=>{
181
205
  }
182
206
  return output;
183
207
  });
208
+ transformed = await applyExportBeforeHook(exportHooks?.before, transformed, docs, 'json', req);
184
209
  }
185
210
  const hasNextPage = previewPage < previewTotalPages;
186
211
  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, 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 { removeDisabledFields } from '../utilities/removeDisabledFields.js'\nimport { resolveLimit } from '../utilities/resolveLimit.js'\nimport { setNestedValue } from '../utilities/setNestedValue.js'\n\nconst applyExportBeforeHook = async (\n hook: ExportBeforeHook | undefined,\n data: Record<string, unknown>[],\n originalDocs: unknown[],\n format: 'csv' | 'json' | ({} & string),\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 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 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?: 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 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 toCSV 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(exportHooks?.before, transformed, docs, 'csv', req)\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)\n }\n\n output = trimmed\n }\n\n return output\n })\n\n transformed = await applyExportBeforeHook(exportHooks?.before, transformed, docs, 'json', req)\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","removeDisabledFields","resolveLimit","setNestedValue","applyExportBeforeHook","hook","data","originalDocs","format","req","length","batchNumber","originalData","totalBatches","handlePreview","collectionSlug","draft","draftFromReq","fields","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, FieldBeforeExportHook, FieldBeforeImportHook, FromCSVFunction, ImportAfterHook, ImportBeforeHook, ImportExportPluginConfig, ImportResult, Limit, LimitFunction, ToCSVFunction, } 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,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,YAAY,EACZ,KAAK,EACL,aAAa,EACb,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 FieldBeforeExportHook,\n FieldBeforeImportHook,\n FromCSVFunction,\n ImportAfterHook,\n ImportBeforeHook,\n ImportExportPluginConfig,\n ImportResult,\n Limit,\n LimitFunction,\n ToCSVFunction,\n} from '../types.js'\n"],"names":[],"mappings":"AAAA,WAaoB"}
@@ -1,5 +1,6 @@
1
1
  import type { PayloadRequest, TypedUser } from 'payload';
2
- import type { ImportMode, ImportResult } from './createImport.js';
2
+ import type { ImportAfterHook, ImportBeforeHook, 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,10 +35,21 @@ 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
+ };
38
46
  importMode: ImportMode;
39
47
  matchField?: string;
48
+ /** Raw parsed rows before unflattening — used as originalData in hooks */
49
+ originalDocs?: Record<string, unknown>[];
40
50
  req: PayloadRequest;
51
+ /** Total number of batches (pre-computed for hook args) */
52
+ totalBatches?: number;
41
53
  user?: TypedUser;
42
54
  }
43
55
  export declare function createImportBatchProcessor(options?: ImportBatchProcessorOptions): {
@@ -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,SAAS,EAAE,MAAM,SAAS,CAAA;AAIxD,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAClF,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,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,SAAS,CAAA;CACjB;AA4hBD,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,2BAAgC;oCAMrC,oBAAoB,KAAG,OAAO,CAAC,YAAY,CAAC;EAgH1F"}
@@ -140,25 +140,22 @@ import { categorizeError, createBatches, extractErrorMessage } from '../utilitie
140
140
  req: defaultLocaleReq,
141
141
  user
142
142
  });
143
- // Update for other locales
144
143
  if (savedDocument && Object.keys(localeUpdates).length > 0) {
145
144
  for (const [locale, localeData] of Object.entries(localeUpdates)){
146
145
  try {
147
- const localeReq = {
148
- ...req,
149
- locale
150
- };
151
146
  await req.payload.update({
152
147
  id: savedDocument.id,
153
148
  collection: collectionSlug,
154
149
  data: localeData,
155
150
  draft: collectionHasVersions ? false : undefined,
156
151
  overrideAccess: false,
157
- req: localeReq,
152
+ req: {
153
+ ...req,
154
+ locale
155
+ },
158
156
  user
159
157
  });
160
158
  } catch (error) {
161
- // Log but don't fail the entire import if a locale update fails
162
159
  req.payload.logger.error({
163
160
  err: error,
164
161
  msg: `Failed to update locale ${locale} for document ${String(savedDocument.id)}`
@@ -280,27 +277,22 @@ import { categorizeError, createBatches, extractErrorMessage } from '../utilitie
280
277
  req: defaultLocaleReq,
281
278
  user
282
279
  });
283
- // Update for other locales
284
280
  if (savedDocument && Object.keys(localeUpdates).length > 0) {
285
281
  for (const [locale, localeData] of Object.entries(localeUpdates)){
286
282
  try {
287
- // Clone the request with the specific locale
288
- const localeReq = {
289
- ...req,
290
- locale
291
- };
292
283
  await req.payload.update({
293
284
  id: existingDoc.id,
294
285
  collection: collectionSlug,
295
286
  data: localeData,
296
287
  depth: 0,
297
- // Don't specify draft - this creates a new draft for versioned collections
298
288
  overrideAccess: false,
299
- req: localeReq,
289
+ req: {
290
+ ...req,
291
+ locale
292
+ },
300
293
  user
301
294
  });
302
295
  } catch (error) {
303
- // Log but don't fail the entire import if a locale update fails
304
296
  req.payload.logger.error({
305
297
  err: error,
306
298
  msg: `Failed to update locale ${locale} for document ${String(existingDoc.id)}`
@@ -390,25 +382,22 @@ import { categorizeError, createBatches, extractErrorMessage } from '../utilitie
390
382
  req: defaultLocaleReq,
391
383
  user
392
384
  });
393
- // Update for other locales
394
385
  if (savedDocument && Object.keys(localeUpdates).length > 0) {
395
386
  for (const [locale, localeData] of Object.entries(localeUpdates)){
396
387
  try {
397
- // Clone the request with the specific locale
398
- const localeReq = {
399
- ...req,
400
- locale
401
- };
402
388
  await req.payload.update({
403
389
  id: savedDocument.id,
404
390
  collection: collectionSlug,
405
391
  data: localeData,
406
392
  draft: collectionHasVersions ? false : undefined,
407
393
  overrideAccess: false,
408
- req: localeReq
394
+ req: {
395
+ ...req,
396
+ locale
397
+ },
398
+ user
409
399
  });
410
400
  } catch (error) {
411
- // Log but don't fail the entire import if a locale update fails
412
401
  req.payload.logger.error({
413
402
  err: error,
414
403
  msg: `Failed to update locale ${locale} for document ${String(savedDocument.id)}`
@@ -497,8 +486,9 @@ export function createImportBatchProcessor(options = {}) {
497
486
  defaultVersionStatus: options.defaultVersionStatus ?? 'published'
498
487
  };
499
488
  const processImport = async (processOptions)=>{
500
- const { collectionSlug, documents, importMode, matchField, req, user } = processOptions;
489
+ const { collectionSlug, docs: documents, format = 'csv', hooks, importMode, matchField, originalDocs: originalDocs, req, totalBatches: totalBatchesFromOptions, user } = processOptions;
501
490
  const batches = createBatches(documents, processorOptions.batchSize);
491
+ const totalBatches = totalBatchesFromOptions ?? batches.length;
502
492
  const result = {
503
493
  errors: [],
504
494
  imported: 0,
@@ -510,8 +500,19 @@ export function createImportBatchProcessor(options = {}) {
510
500
  if (!currentBatch) {
511
501
  continue;
512
502
  }
503
+ const batchNumber = i + 1;
504
+ const batchStart = i * processorOptions.batchSize;
505
+ const originalBatch = originalDocs ? originalDocs.slice(batchStart, batchStart + currentBatch.length) : currentBatch;
506
+ const batchToProcess = hooks?.before && currentBatch.length > 0 ? await hooks.before({
507
+ batchNumber,
508
+ data: currentBatch,
509
+ format,
510
+ originalData: originalBatch,
511
+ req,
512
+ totalBatches
513
+ }) : currentBatch;
513
514
  const batchResult = await processImportBatch({
514
- batch: currentBatch,
515
+ batch: batchToProcess,
515
516
  batchIndex: i,
516
517
  collectionSlug,
517
518
  importMode,
@@ -520,18 +521,23 @@ export function createImportBatchProcessor(options = {}) {
520
521
  req,
521
522
  user
522
523
  });
523
- // Update results
524
+ let batchImported = 0;
525
+ let batchUpdated = 0;
524
526
  for (const success of batchResult.successful){
525
527
  if (success.operation === 'created') {
526
528
  result.imported++;
529
+ batchImported++;
527
530
  } else if (success.operation === 'updated') {
528
531
  result.updated++;
532
+ batchUpdated++;
529
533
  } else {
530
534
  // Fallback
531
535
  if (importMode === 'create') {
532
536
  result.imported++;
537
+ batchImported++;
533
538
  } else {
534
539
  result.updated++;
540
+ batchUpdated++;
535
541
  }
536
542
  }
537
543
  }
@@ -542,6 +548,22 @@ export function createImportBatchProcessor(options = {}) {
542
548
  index: error.rowNumber - 1
543
549
  });
544
550
  }
551
+ if (hooks?.after) {
552
+ const batchHookResult = {
553
+ errors: batchResult.failed.length > 0 ? result.errors.slice(-batchResult.failed.length) : [],
554
+ imported: batchImported,
555
+ total: batchToProcess.length,
556
+ updated: batchUpdated
557
+ };
558
+ await hooks.after({
559
+ batchNumber,
560
+ format,
561
+ originalData: originalBatch,
562
+ req,
563
+ result: batchHookResult,
564
+ totalBatches
565
+ });
566
+ }
545
567
  }
546
568
  return result;
547
569
  };