Skip to content

feat(plugin-import-export): add debug logging option #12705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions packages/plugin-import-export/src/export/createExport.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable perfectionist/sort-objects */
import type { PaginatedDocs, PayloadRequest, Sort, User, Where } from 'payload'

import { stringify } from 'csv-stringify/sync'
Expand All @@ -10,6 +11,10 @@ import { getSelect } from './getSelect.js'

type Export = {
collectionSlug: string
/**
* If true, enables debug logging
*/
debug?: boolean
drafts?: 'no' | 'yes'
exportsCollection: string
fields?: string[]
Expand Down Expand Up @@ -42,6 +47,7 @@ export const createExport = async (args: CreateExportArgs) => {
id,
name: nameArg,
collectionSlug,
debug = false,
drafts,
exportsCollection,
fields,
Expand All @@ -54,6 +60,17 @@ export const createExport = async (args: CreateExportArgs) => {
req: { locale: localeArg, payload },
req,
} = args

if (debug) {
req.payload.logger.info({
message: 'Starting export process with args:',
collectionSlug,
drafts,
fields,
format,
})
}

const locale = localeInput ?? localeArg
const collectionConfig = payload.config.collections.find(({ slug }) => slug === collectionSlug)
if (!collectionConfig) {
Expand All @@ -63,6 +80,10 @@ export const createExport = async (args: CreateExportArgs) => {
const name = `${nameArg ?? `${getFilename()}-${collectionSlug}`}.${format}`
const isCSV = format === 'csv'

if (debug) {
req.payload.logger.info({ message: 'Export configuration:', name, isCSV, locale })
}

const findArgs = {
collection: collectionSlug,
depth: 0,
Expand All @@ -77,22 +98,37 @@ export const createExport = async (args: CreateExportArgs) => {
where,
}

if (debug) {
req.payload.logger.info({ message: 'Find arguments:', findArgs })
}

let result: PaginatedDocs = { hasNextPage: true } as PaginatedDocs

if (download) {
if (debug) {
req.payload.logger.info('Starting download stream')
}
const encoder = new TextEncoder()
const stream = new Readable({
async read() {
let result = await payload.find(findArgs)
let isFirstBatch = true

while (result.docs.length > 0) {
if (debug) {
req.payload.logger.info(
`Processing batch ${findArgs.page + 1} with ${result.docs.length} documents`,
)
}
const csvInput = result.docs.map((doc) => flattenObject({ doc, fields }))
const csvString = stringify(csvInput, { header: isFirstBatch })
this.push(encoder.encode(csvString))
isFirstBatch = false

if (!result.hasNextPage) {
if (debug) {
req.payload.logger.info('Stream complete - no more pages')
}
this.push(null) // End the stream
break
}
Expand All @@ -111,13 +147,22 @@ export const createExport = async (args: CreateExportArgs) => {
})
}

if (debug) {
req.payload.logger.info('Starting file generation')
}
const outputData: string[] = []
let isFirstBatch = true

while (result.hasNextPage) {
findArgs.page += 1
result = await payload.find(findArgs)

if (debug) {
req.payload.logger.info(
`Processing batch ${findArgs.page} with ${result.docs.length} documents`,
)
}

if (isCSV) {
const csvInput = result.docs.map((doc) => flattenObject({ doc, fields }))
outputData.push(stringify(csvInput, { header: isFirstBatch }))
Expand All @@ -129,15 +174,24 @@ export const createExport = async (args: CreateExportArgs) => {
}

const buffer = Buffer.from(format === 'json' ? `[${outputData.join(',')}]` : outputData.join(''))
if (debug) {
req.payload.logger.info(`${format} file generation complete`)
}

if (!id) {
if (debug) {
req.payload.logger.info('Creating new export file')
}
req.file = {
name,
data: buffer,
mimetype: isCSV ? 'text/csv' : 'application/json',
size: buffer.length,
}
} else {
if (debug) {
req.payload.logger.info(`Updating existing export with id: ${id}`)
}
await req.payload.update({
id,
collection: exportsCollection,
Expand All @@ -151,4 +205,7 @@ export const createExport = async (args: CreateExportArgs) => {
user,
})
}
if (debug) {
req.payload.logger.info('Export process completed successfully')
}
}
6 changes: 3 additions & 3 deletions packages/plugin-import-export/src/export/download.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { PayloadHandler } from 'payload'
import type { PayloadRequest } from 'payload'

import { APIError } from 'payload'

import { createExport } from './createExport.js'

export const download: PayloadHandler = async (req) => {
export const download = async (req: PayloadRequest, debug = false) => {
let body
if (typeof req?.json === 'function') {
body = await req.json()
Expand All @@ -20,7 +20,7 @@ export const download: PayloadHandler = async (req) => {

return createExport({
download: true,
input: body.data,
input: { ...body.data, debug },
req,
}) as Promise<Response>
}
7 changes: 5 additions & 2 deletions packages/plugin-import-export/src/getExportCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ export const getExportCollection = ({
disableDuplicate: true,
endpoints: [
{
handler: download,
handler: (req) => {
return download(req, pluginConfig.debug)
},
method: 'post',
path: '/download',
},
Expand All @@ -63,7 +65,8 @@ export const getExportCollection = ({
return
}
const { user } = req
await createExport({ input: { ...args.data, user }, req })
const debug = pluginConfig.debug
await createExport({ input: { ...args.data, debug, user }, req })
})
} else {
afterChange.push(async ({ doc, operation, req }) => {
Expand Down
4 changes: 4 additions & 0 deletions packages/plugin-import-export/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export type ImportExportPluginConfig = {
* Defaults to all collections
*/
collections?: string[]
/**
* If true, enables debug logging
*/
debug?: boolean
/**
* Enable to force the export to run synchronously
*/
Expand Down
Loading