@payloadcms/plugin-import-export 3.71.0-internal.ef75fa0 → 3.71.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CollectionField/index.d.ts.map +1 -1
- package/dist/components/CollectionField/index.js +8 -3
- package/dist/components/CollectionField/index.js.map +1 -1
- package/dist/components/ExportListMenuItem/index.d.ts +0 -1
- package/dist/components/ExportListMenuItem/index.d.ts.map +1 -1
- package/dist/components/ExportListMenuItem/index.js +0 -1
- package/dist/components/ExportListMenuItem/index.js.map +1 -1
- package/dist/components/ExportPreview/index.d.ts +4 -0
- package/dist/components/ExportPreview/index.d.ts.map +1 -0
- package/dist/components/ExportPreview/index.js +252 -0
- package/dist/components/ExportPreview/index.js.map +1 -0
- package/dist/components/ExportPreview/index.scss +36 -0
- package/dist/components/ImportCollectionField/index.d.ts +3 -0
- package/dist/components/ImportCollectionField/index.d.ts.map +1 -0
- package/dist/components/ImportCollectionField/index.js +17 -0
- package/dist/components/ImportCollectionField/index.js.map +1 -0
- package/dist/components/ImportListMenuItem/index.d.ts +6 -0
- package/dist/components/ImportListMenuItem/index.d.ts.map +1 -0
- package/dist/components/ImportListMenuItem/index.js +48 -0
- package/dist/components/ImportListMenuItem/index.js.map +1 -0
- package/dist/components/ImportPreview/index.d.ts +4 -0
- package/dist/components/ImportPreview/index.d.ts.map +1 -0
- package/dist/components/ImportPreview/index.js +624 -0
- package/dist/components/ImportPreview/index.js.map +1 -0
- package/dist/components/ImportPreview/index.scss +41 -0
- package/dist/components/ImportSaveButton/index.d.ts +2 -0
- package/dist/components/ImportSaveButton/index.d.ts.map +1 -0
- package/dist/components/ImportSaveButton/index.js +18 -0
- package/dist/components/ImportSaveButton/index.js.map +1 -0
- package/dist/components/Page/index.scss +4 -2
- package/dist/constants.d.ts +21 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +21 -0
- package/dist/constants.js.map +1 -0
- package/dist/export/batchProcessor.d.ts +107 -0
- package/dist/export/batchProcessor.d.ts.map +1 -0
- package/dist/export/batchProcessor.js +187 -0
- package/dist/export/batchProcessor.js.map +1 -0
- package/dist/export/createExport.d.ts +9 -4
- package/dist/export/createExport.d.ts.map +1 -1
- package/dist/export/createExport.js +163 -111
- package/dist/export/createExport.js.map +1 -1
- package/dist/export/getCreateExportCollectionTask.d.ts +1 -2
- package/dist/export/getCreateExportCollectionTask.d.ts.map +1 -1
- package/dist/export/getCreateExportCollectionTask.js +10 -18
- package/dist/export/getCreateExportCollectionTask.js.map +1 -1
- package/dist/export/getExportCollection.d.ts +8 -0
- package/dist/export/getExportCollection.d.ts.map +1 -0
- package/dist/export/getExportCollection.js +100 -0
- package/dist/export/getExportCollection.js.map +1 -0
- package/dist/export/getFields.d.ts +8 -2
- package/dist/export/getFields.d.ts.map +1 -1
- package/dist/export/getFields.js +7 -9
- package/dist/export/getFields.js.map +1 -1
- package/dist/export/handleDownload.d.ts +3 -0
- package/dist/export/handleDownload.d.ts.map +1 -0
- package/dist/export/{download.js → handleDownload.js} +7 -6
- package/dist/export/handleDownload.js.map +1 -0
- package/dist/export/handlePreview.d.ts +3 -0
- package/dist/export/handlePreview.d.ts.map +1 -0
- package/dist/export/handlePreview.js +163 -0
- package/dist/export/handlePreview.js.map +1 -0
- package/dist/exports/rsc.d.ts +5 -1
- package/dist/exports/rsc.d.ts.map +1 -1
- package/dist/exports/rsc.js +5 -1
- package/dist/exports/rsc.js.map +1 -1
- package/dist/import/batchProcessor.d.ts +46 -0
- package/dist/import/batchProcessor.d.ts.map +1 -0
- package/dist/import/batchProcessor.js +529 -0
- package/dist/import/batchProcessor.js.map +1 -0
- package/dist/import/createImport.d.ts +45 -0
- package/dist/import/createImport.d.ts.map +1 -0
- package/dist/import/createImport.js +175 -0
- package/dist/import/createImport.js.map +1 -0
- package/dist/import/getCreateImportCollectionTask.d.ts +13 -0
- package/dist/import/getCreateImportCollectionTask.d.ts.map +1 -0
- package/dist/import/getCreateImportCollectionTask.js +81 -0
- package/dist/import/getCreateImportCollectionTask.js.map +1 -0
- package/dist/import/getFields.d.ts +7 -0
- package/dist/import/getFields.d.ts.map +1 -0
- package/dist/import/getFields.js +150 -0
- package/dist/import/getFields.js.map +1 -0
- package/dist/import/getImportCollection.d.ts +8 -0
- package/dist/import/getImportCollection.d.ts.map +1 -0
- package/dist/import/getImportCollection.js +258 -0
- package/dist/import/getImportCollection.js.map +1 -0
- package/dist/import/handlePreview.d.ts +3 -0
- package/dist/import/handlePreview.d.ts.map +1 -0
- package/dist/import/handlePreview.js +94 -0
- package/dist/import/handlePreview.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +68 -110
- package/dist/index.js.map +1 -1
- package/dist/translations/languages/ar.d.ts.map +1 -1
- package/dist/translations/languages/ar.js +21 -1
- package/dist/translations/languages/ar.js.map +1 -1
- package/dist/translations/languages/az.d.ts.map +1 -1
- package/dist/translations/languages/az.js +21 -1
- package/dist/translations/languages/az.js.map +1 -1
- package/dist/translations/languages/bg.d.ts.map +1 -1
- package/dist/translations/languages/bg.js +21 -1
- package/dist/translations/languages/bg.js.map +1 -1
- package/dist/translations/languages/bnBd.d.ts +4 -0
- package/dist/translations/languages/bnBd.d.ts.map +1 -0
- package/dist/translations/languages/bnBd.js +48 -0
- package/dist/translations/languages/bnBd.js.map +1 -0
- package/dist/translations/languages/bnIn.d.ts +4 -0
- package/dist/translations/languages/bnIn.d.ts.map +1 -0
- package/dist/translations/languages/bnIn.js +48 -0
- package/dist/translations/languages/bnIn.js.map +1 -0
- package/dist/translations/languages/ca.d.ts.map +1 -1
- package/dist/translations/languages/ca.js +21 -1
- package/dist/translations/languages/ca.js.map +1 -1
- package/dist/translations/languages/cs.d.ts.map +1 -1
- package/dist/translations/languages/cs.js +21 -1
- package/dist/translations/languages/cs.js.map +1 -1
- package/dist/translations/languages/da.d.ts.map +1 -1
- package/dist/translations/languages/da.js +21 -1
- package/dist/translations/languages/da.js.map +1 -1
- package/dist/translations/languages/de.d.ts.map +1 -1
- package/dist/translations/languages/de.js +21 -1
- package/dist/translations/languages/de.js.map +1 -1
- package/dist/translations/languages/en.d.ts +20 -0
- package/dist/translations/languages/en.d.ts.map +1 -1
- package/dist/translations/languages/en.js +21 -1
- package/dist/translations/languages/en.js.map +1 -1
- package/dist/translations/languages/es.d.ts.map +1 -1
- package/dist/translations/languages/es.js +21 -1
- package/dist/translations/languages/es.js.map +1 -1
- package/dist/translations/languages/et.d.ts.map +1 -1
- package/dist/translations/languages/et.js +21 -1
- package/dist/translations/languages/et.js.map +1 -1
- package/dist/translations/languages/fa.d.ts.map +1 -1
- package/dist/translations/languages/fa.js +21 -1
- package/dist/translations/languages/fa.js.map +1 -1
- package/dist/translations/languages/fr.d.ts.map +1 -1
- package/dist/translations/languages/fr.js +21 -1
- package/dist/translations/languages/fr.js.map +1 -1
- package/dist/translations/languages/he.d.ts.map +1 -1
- package/dist/translations/languages/he.js +21 -1
- package/dist/translations/languages/he.js.map +1 -1
- package/dist/translations/languages/hr.d.ts.map +1 -1
- package/dist/translations/languages/hr.js +21 -1
- package/dist/translations/languages/hr.js.map +1 -1
- package/dist/translations/languages/hu.d.ts.map +1 -1
- package/dist/translations/languages/hu.js +21 -1
- package/dist/translations/languages/hu.js.map +1 -1
- package/dist/translations/languages/hy.d.ts.map +1 -1
- package/dist/translations/languages/hy.js +21 -1
- package/dist/translations/languages/hy.js.map +1 -1
- package/dist/translations/languages/id.d.ts +4 -0
- package/dist/translations/languages/id.d.ts.map +1 -0
- package/dist/translations/languages/id.js +48 -0
- package/dist/translations/languages/id.js.map +1 -0
- package/dist/translations/languages/is.d.ts.map +1 -1
- package/dist/translations/languages/is.js +21 -1
- package/dist/translations/languages/is.js.map +1 -1
- package/dist/translations/languages/it.d.ts.map +1 -1
- package/dist/translations/languages/it.js +21 -1
- package/dist/translations/languages/it.js.map +1 -1
- package/dist/translations/languages/ja.d.ts.map +1 -1
- package/dist/translations/languages/ja.js +21 -1
- package/dist/translations/languages/ja.js.map +1 -1
- package/dist/translations/languages/ko.d.ts.map +1 -1
- package/dist/translations/languages/ko.js +21 -1
- package/dist/translations/languages/ko.js.map +1 -1
- package/dist/translations/languages/lt.d.ts.map +1 -1
- package/dist/translations/languages/lt.js +21 -1
- package/dist/translations/languages/lt.js.map +1 -1
- package/dist/translations/languages/lv.d.ts.map +1 -1
- package/dist/translations/languages/lv.js +26 -6
- package/dist/translations/languages/lv.js.map +1 -1
- package/dist/translations/languages/my.d.ts.map +1 -1
- package/dist/translations/languages/my.js +21 -1
- package/dist/translations/languages/my.js.map +1 -1
- package/dist/translations/languages/nb.d.ts.map +1 -1
- package/dist/translations/languages/nb.js +21 -1
- package/dist/translations/languages/nb.js.map +1 -1
- package/dist/translations/languages/nl.d.ts.map +1 -1
- package/dist/translations/languages/nl.js +21 -1
- package/dist/translations/languages/nl.js.map +1 -1
- package/dist/translations/languages/pl.d.ts.map +1 -1
- package/dist/translations/languages/pl.js +21 -1
- package/dist/translations/languages/pl.js.map +1 -1
- package/dist/translations/languages/pt.d.ts.map +1 -1
- package/dist/translations/languages/pt.js +21 -1
- package/dist/translations/languages/pt.js.map +1 -1
- package/dist/translations/languages/ro.d.ts.map +1 -1
- package/dist/translations/languages/ro.js +21 -1
- package/dist/translations/languages/ro.js.map +1 -1
- package/dist/translations/languages/rs.d.ts.map +1 -1
- package/dist/translations/languages/rs.js +21 -1
- package/dist/translations/languages/rs.js.map +1 -1
- package/dist/translations/languages/rsLatin.d.ts.map +1 -1
- package/dist/translations/languages/rsLatin.js +21 -1
- package/dist/translations/languages/rsLatin.js.map +1 -1
- package/dist/translations/languages/ru.d.ts.map +1 -1
- package/dist/translations/languages/ru.js +21 -1
- package/dist/translations/languages/ru.js.map +1 -1
- package/dist/translations/languages/sk.d.ts.map +1 -1
- package/dist/translations/languages/sk.js +21 -1
- package/dist/translations/languages/sk.js.map +1 -1
- package/dist/translations/languages/sl.d.ts.map +1 -1
- package/dist/translations/languages/sl.js +21 -1
- package/dist/translations/languages/sl.js.map +1 -1
- package/dist/translations/languages/sv.d.ts.map +1 -1
- package/dist/translations/languages/sv.js +21 -1
- package/dist/translations/languages/sv.js.map +1 -1
- package/dist/translations/languages/ta.d.ts.map +1 -1
- package/dist/translations/languages/ta.js +21 -1
- package/dist/translations/languages/ta.js.map +1 -1
- package/dist/translations/languages/th.d.ts.map +1 -1
- package/dist/translations/languages/th.js +21 -1
- package/dist/translations/languages/th.js.map +1 -1
- package/dist/translations/languages/tr.d.ts.map +1 -1
- package/dist/translations/languages/tr.js +21 -1
- package/dist/translations/languages/tr.js.map +1 -1
- package/dist/translations/languages/uk.d.ts.map +1 -1
- package/dist/translations/languages/uk.js +21 -1
- package/dist/translations/languages/uk.js.map +1 -1
- package/dist/translations/languages/vi.d.ts.map +1 -1
- package/dist/translations/languages/vi.js +21 -1
- package/dist/translations/languages/vi.js.map +1 -1
- package/dist/translations/languages/zh.d.ts.map +1 -1
- package/dist/translations/languages/zh.js +21 -1
- package/dist/translations/languages/zh.js.map +1 -1
- package/dist/translations/languages/zhTw.d.ts.map +1 -1
- package/dist/translations/languages/zhTw.js +21 -1
- package/dist/translations/languages/zhTw.js.map +1 -1
- package/dist/translations/types.d.ts +13 -0
- package/dist/translations/types.d.ts.map +1 -1
- package/dist/translations/types.js.map +1 -1
- package/dist/types.d.ts +166 -22
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utilities/flattenObject.d.ts.map +1 -0
- package/dist/{export → utilities}/flattenObject.js +13 -6
- package/dist/utilities/flattenObject.js.map +1 -0
- package/dist/utilities/getExportFieldFunctions.d.ts +12 -0
- package/dist/utilities/getExportFieldFunctions.d.ts.map +1 -0
- package/dist/{export/getCustomFieldFunctions.js → utilities/getExportFieldFunctions.js} +18 -2
- package/dist/utilities/getExportFieldFunctions.js.map +1 -0
- package/dist/utilities/getFilename.d.ts +6 -0
- package/dist/utilities/getFilename.d.ts.map +1 -0
- package/dist/{export → utilities}/getFilename.js +4 -1
- package/dist/utilities/getFilename.js.map +1 -0
- package/dist/utilities/getFlattenedFieldKeys.d.ts +12 -1
- package/dist/utilities/getFlattenedFieldKeys.d.ts.map +1 -1
- package/dist/utilities/getFlattenedFieldKeys.js +35 -10
- package/dist/utilities/getFlattenedFieldKeys.js.map +1 -1
- package/dist/utilities/getImportFieldFunctions.d.ts +12 -0
- package/dist/utilities/getImportFieldFunctions.d.ts.map +1 -0
- package/dist/utilities/getImportFieldFunctions.js +130 -0
- package/dist/utilities/getImportFieldFunctions.js.map +1 -0
- package/dist/utilities/getPluginCollections.d.ts +39 -0
- package/dist/utilities/getPluginCollections.d.ts.map +1 -0
- package/dist/utilities/getPluginCollections.js +102 -0
- package/dist/utilities/getPluginCollections.js.map +1 -0
- package/dist/utilities/getSchemaColumns.d.ts +43 -0
- package/dist/utilities/getSchemaColumns.d.ts.map +1 -0
- package/dist/utilities/getSchemaColumns.js +163 -0
- package/dist/utilities/getSchemaColumns.js.map +1 -0
- package/dist/utilities/getSelect.d.ts +11 -0
- package/dist/utilities/getSelect.d.ts.map +1 -0
- package/dist/{export → utilities}/getSelect.js +6 -2
- package/dist/utilities/getSelect.js.map +1 -0
- package/dist/utilities/parseCSV.d.ts +11 -0
- package/dist/utilities/parseCSV.d.ts.map +1 -0
- package/dist/utilities/parseCSV.js +67 -0
- package/dist/utilities/parseCSV.js.map +1 -0
- package/dist/utilities/parseCSV.spec.js +169 -0
- package/dist/utilities/parseCSV.spec.js.map +1 -0
- package/dist/utilities/parseJSON.d.ts +11 -0
- package/dist/utilities/parseJSON.d.ts.map +1 -0
- package/dist/utilities/parseJSON.js +25 -0
- package/dist/utilities/parseJSON.js.map +1 -0
- package/dist/utilities/processRichTextField.d.ts +6 -0
- package/dist/utilities/processRichTextField.d.ts.map +1 -0
- package/dist/utilities/processRichTextField.js +45 -0
- package/dist/utilities/processRichTextField.js.map +1 -0
- package/dist/utilities/unflattenObject.d.ts +11 -0
- package/dist/utilities/unflattenObject.d.ts.map +1 -0
- package/dist/utilities/unflattenObject.js +431 -0
- package/dist/utilities/unflattenObject.js.map +1 -0
- package/dist/utilities/unflattenObject.spec.js +680 -0
- package/dist/utilities/unflattenObject.spec.js.map +1 -0
- package/dist/utilities/useBatchProcessor.d.ts +103 -0
- package/dist/utilities/useBatchProcessor.d.ts.map +1 -0
- package/dist/utilities/useBatchProcessor.js +88 -0
- package/dist/utilities/useBatchProcessor.js.map +1 -0
- package/dist/utilities/validateLimitValue.d.ts +1 -1
- package/dist/utilities/validateLimitValue.d.ts.map +1 -1
- package/dist/utilities/validateLimitValue.js +1 -4
- package/dist/utilities/validateLimitValue.js.map +1 -1
- package/package.json +9 -9
- package/dist/components/ExportListMenuItem/index.scss +0 -52
- package/dist/components/Preview/index.d.ts +0 -4
- package/dist/components/Preview/index.d.ts.map +0 -1
- package/dist/components/Preview/index.js +0 -180
- package/dist/components/Preview/index.js.map +0 -1
- package/dist/components/Preview/index.scss +0 -8
- package/dist/export/download.d.ts +0 -3
- package/dist/export/download.d.ts.map +0 -1
- package/dist/export/download.js.map +0 -1
- package/dist/export/flattenObject.d.ts.map +0 -1
- package/dist/export/flattenObject.js.map +0 -1
- package/dist/export/getCustomFieldFunctions.d.ts +0 -8
- package/dist/export/getCustomFieldFunctions.d.ts.map +0 -1
- package/dist/export/getCustomFieldFunctions.js.map +0 -1
- package/dist/export/getFilename.d.ts +0 -2
- package/dist/export/getFilename.d.ts.map +0 -1
- package/dist/export/getFilename.js.map +0 -1
- package/dist/export/getSelect.d.ts +0 -7
- package/dist/export/getSelect.d.ts.map +0 -1
- package/dist/export/getSelect.js.map +0 -1
- package/dist/getExportCollection.d.ts +0 -7
- package/dist/getExportCollection.d.ts.map +0 -1
- package/dist/getExportCollection.js +0 -86
- package/dist/getExportCollection.js.map +0 -1
- /package/dist/{export → utilities}/flattenObject.d.ts +0 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { createImport } from './createImport.js';
|
|
4
|
+
import { getFields } from './getFields.js';
|
|
5
|
+
import { handlePreview } from './handlePreview.js';
|
|
6
|
+
export const getImportCollection = ({ config, importConfig, pluginConfig })=>{
|
|
7
|
+
const beforeOperation = [];
|
|
8
|
+
const afterChange = [];
|
|
9
|
+
// Extract import-specific settings
|
|
10
|
+
const disableJobsQueue = importConfig?.disableJobsQueue ?? false;
|
|
11
|
+
const batchSize = importConfig?.batchSize ?? 100;
|
|
12
|
+
const defaultVersionStatus = importConfig?.defaultVersionStatus ?? 'published';
|
|
13
|
+
// Get collection slugs for the dropdown
|
|
14
|
+
const collectionSlugs = pluginConfig.collections?.map((c)=>c.slug);
|
|
15
|
+
const collection = {
|
|
16
|
+
slug: 'imports',
|
|
17
|
+
access: {
|
|
18
|
+
update: ()=>false
|
|
19
|
+
},
|
|
20
|
+
admin: {
|
|
21
|
+
components: {
|
|
22
|
+
edit: {
|
|
23
|
+
SaveButton: '@payloadcms/plugin-import-export/rsc#ImportSaveButton'
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
disableCopyToLocale: true,
|
|
27
|
+
group: false,
|
|
28
|
+
useAsTitle: 'filename'
|
|
29
|
+
},
|
|
30
|
+
disableDuplicate: true,
|
|
31
|
+
endpoints: [
|
|
32
|
+
{
|
|
33
|
+
handler: handlePreview,
|
|
34
|
+
method: 'post',
|
|
35
|
+
path: '/preview-data'
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
fields: getFields(config, {
|
|
39
|
+
collectionSlugs
|
|
40
|
+
}),
|
|
41
|
+
hooks: {
|
|
42
|
+
afterChange,
|
|
43
|
+
beforeOperation
|
|
44
|
+
},
|
|
45
|
+
lockDocuments: false,
|
|
46
|
+
upload: {
|
|
47
|
+
filesRequiredOnCreate: true,
|
|
48
|
+
hideFileInputOnCreate: false,
|
|
49
|
+
hideRemoveFile: true,
|
|
50
|
+
mimeTypes: [
|
|
51
|
+
'text/csv',
|
|
52
|
+
'application/json'
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
if (disableJobsQueue) {
|
|
57
|
+
// Process the import synchronously after the document (with file) has been created
|
|
58
|
+
afterChange.push(async ({ collection: collectionConfig, doc, operation, req })=>{
|
|
59
|
+
if (operation !== 'create' || doc.status !== 'pending') {
|
|
60
|
+
return doc;
|
|
61
|
+
}
|
|
62
|
+
const debug = pluginConfig.debug || false;
|
|
63
|
+
try {
|
|
64
|
+
// Get file data from the uploaded document
|
|
65
|
+
let fileData;
|
|
66
|
+
let fileMimetype;
|
|
67
|
+
if (doc.url && doc.url.startsWith('http')) {
|
|
68
|
+
// File has been uploaded to external storage (S3, etc.) - fetch it
|
|
69
|
+
const response = await fetch(doc.url);
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
throw new Error(`Failed to fetch file from URL: ${doc.url}`);
|
|
72
|
+
}
|
|
73
|
+
fileData = Buffer.from(await response.arrayBuffer());
|
|
74
|
+
fileMimetype = doc.mimeType || 'text/csv';
|
|
75
|
+
} else {
|
|
76
|
+
// File is stored locally - read from filesystem
|
|
77
|
+
const filePath = doc.filename;
|
|
78
|
+
// Get upload config from the actual sanitized collection config
|
|
79
|
+
const uploadConfig = typeof collectionConfig?.upload === 'object' ? collectionConfig.upload : undefined;
|
|
80
|
+
const uploadDir = uploadConfig?.staticDir || './uploads';
|
|
81
|
+
const fullPath = path.resolve(uploadDir, filePath);
|
|
82
|
+
fileData = await fs.promises.readFile(fullPath);
|
|
83
|
+
fileMimetype = doc.mimeType || 'text/csv';
|
|
84
|
+
}
|
|
85
|
+
const result = await createImport({
|
|
86
|
+
id: doc.id,
|
|
87
|
+
name: doc.filename || 'import',
|
|
88
|
+
batchSize,
|
|
89
|
+
collectionSlug: doc.collectionSlug,
|
|
90
|
+
debug,
|
|
91
|
+
defaultVersionStatus,
|
|
92
|
+
file: {
|
|
93
|
+
name: doc.filename,
|
|
94
|
+
data: fileData,
|
|
95
|
+
mimetype: fileMimetype
|
|
96
|
+
},
|
|
97
|
+
format: fileMimetype === 'text/csv' ? 'csv' : 'json',
|
|
98
|
+
importMode: doc.importMode || 'create',
|
|
99
|
+
matchField: doc.matchField,
|
|
100
|
+
req,
|
|
101
|
+
userCollection: req?.user?.collection || req?.user?.user?.collection,
|
|
102
|
+
userID: req?.user?.id || req?.user?.user?.id
|
|
103
|
+
});
|
|
104
|
+
// Determine status
|
|
105
|
+
let status;
|
|
106
|
+
if (result.errors.length === 0) {
|
|
107
|
+
status = 'completed';
|
|
108
|
+
} else if (result.imported + result.updated === 0) {
|
|
109
|
+
status = 'failed';
|
|
110
|
+
} else {
|
|
111
|
+
status = 'partial';
|
|
112
|
+
}
|
|
113
|
+
const summary = {
|
|
114
|
+
imported: result.imported,
|
|
115
|
+
issueDetails: result.errors.length > 0 ? result.errors.map((e)=>({
|
|
116
|
+
data: e.doc,
|
|
117
|
+
error: e.error,
|
|
118
|
+
row: e.index + 1
|
|
119
|
+
})) : undefined,
|
|
120
|
+
issues: result.errors.length,
|
|
121
|
+
total: result.total,
|
|
122
|
+
updated: result.updated
|
|
123
|
+
};
|
|
124
|
+
// Try to update the document with results (may fail due to transaction timing)
|
|
125
|
+
try {
|
|
126
|
+
await req.payload.update({
|
|
127
|
+
id: doc.id,
|
|
128
|
+
collection: collectionConfig.slug,
|
|
129
|
+
data: {
|
|
130
|
+
status,
|
|
131
|
+
summary
|
|
132
|
+
},
|
|
133
|
+
overrideAccess: true,
|
|
134
|
+
req
|
|
135
|
+
});
|
|
136
|
+
} catch (updateErr) {
|
|
137
|
+
// Update may fail if document not yet committed, log but continue
|
|
138
|
+
if (debug) {
|
|
139
|
+
req.payload.logger.error({
|
|
140
|
+
err: updateErr,
|
|
141
|
+
msg: `Failed to update import document ${doc.id} with results`
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Return updated doc for immediate response
|
|
146
|
+
return {
|
|
147
|
+
...doc,
|
|
148
|
+
status,
|
|
149
|
+
summary
|
|
150
|
+
};
|
|
151
|
+
} catch (err) {
|
|
152
|
+
const summary = {
|
|
153
|
+
imported: 0,
|
|
154
|
+
issueDetails: [
|
|
155
|
+
{
|
|
156
|
+
data: {},
|
|
157
|
+
error: err instanceof Error ? err.message : String(err),
|
|
158
|
+
row: 0
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
issues: 1,
|
|
162
|
+
total: 0,
|
|
163
|
+
updated: 0
|
|
164
|
+
};
|
|
165
|
+
// Try to update document with error status
|
|
166
|
+
try {
|
|
167
|
+
await req.payload.update({
|
|
168
|
+
id: doc.id,
|
|
169
|
+
collection: collectionConfig.slug,
|
|
170
|
+
data: {
|
|
171
|
+
status: 'failed',
|
|
172
|
+
summary
|
|
173
|
+
},
|
|
174
|
+
overrideAccess: true,
|
|
175
|
+
req
|
|
176
|
+
});
|
|
177
|
+
} catch (updateErr) {
|
|
178
|
+
// Update may fail if document not yet committed, log but continue
|
|
179
|
+
if (debug) {
|
|
180
|
+
req.payload.logger.error({
|
|
181
|
+
err: updateErr,
|
|
182
|
+
msg: `Failed to update import document ${doc.id} with error status`
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (debug) {
|
|
187
|
+
req.payload.logger.error({
|
|
188
|
+
err,
|
|
189
|
+
msg: 'Import processing failed'
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
// Return error status for immediate response
|
|
193
|
+
return {
|
|
194
|
+
...doc,
|
|
195
|
+
status: 'failed',
|
|
196
|
+
summary
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
} else {
|
|
201
|
+
// When jobs queue is enabled, queue the import as a job
|
|
202
|
+
afterChange.push(async ({ collection: collectionConfig, doc, operation, req })=>{
|
|
203
|
+
if (operation !== 'create') {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
// Get file data for job - need to read from disk/URL since req.file is not available in afterChange
|
|
208
|
+
let fileData;
|
|
209
|
+
if (doc.url && doc.url.startsWith('http')) {
|
|
210
|
+
const response = await fetch(doc.url);
|
|
211
|
+
if (!response.ok) {
|
|
212
|
+
throw new Error(`Failed to fetch file from URL: ${doc.url}`);
|
|
213
|
+
}
|
|
214
|
+
fileData = Buffer.from(await response.arrayBuffer());
|
|
215
|
+
} else {
|
|
216
|
+
const filePath = doc.filename;
|
|
217
|
+
// Get upload config from the actual sanitized collection config
|
|
218
|
+
const uploadConfig = typeof collectionConfig?.upload === 'object' ? collectionConfig.upload : undefined;
|
|
219
|
+
const uploadDir = uploadConfig?.staticDir || './uploads';
|
|
220
|
+
const fullPath = path.resolve(uploadDir, filePath);
|
|
221
|
+
fileData = await fs.promises.readFile(fullPath);
|
|
222
|
+
}
|
|
223
|
+
const input = {
|
|
224
|
+
name: doc.filename,
|
|
225
|
+
batchSize,
|
|
226
|
+
collectionSlug: doc.collectionSlug,
|
|
227
|
+
debug: pluginConfig.debug,
|
|
228
|
+
defaultVersionStatus,
|
|
229
|
+
file: {
|
|
230
|
+
name: doc.filename,
|
|
231
|
+
// Convert to base64 for job serialization - will be converted back to Buffer in task handler
|
|
232
|
+
data: fileData.toString('base64'),
|
|
233
|
+
mimetype: doc.mimeType || 'text/csv'
|
|
234
|
+
},
|
|
235
|
+
format: doc.mimeType === 'text/csv' ? 'csv' : 'json',
|
|
236
|
+
importId: doc.id,
|
|
237
|
+
importMode: doc.importMode || 'create',
|
|
238
|
+
importsCollection: collectionConfig.slug,
|
|
239
|
+
matchField: doc.matchField,
|
|
240
|
+
userCollection: req.user?.collection || req?.user?.user?.collection,
|
|
241
|
+
userID: req?.user?.id || req?.user?.user?.id
|
|
242
|
+
};
|
|
243
|
+
await req.payload.jobs.queue({
|
|
244
|
+
input,
|
|
245
|
+
task: 'createCollectionImport'
|
|
246
|
+
});
|
|
247
|
+
} catch (err) {
|
|
248
|
+
req.payload.logger.error({
|
|
249
|
+
err,
|
|
250
|
+
msg: `Failed to queue import job for document ${doc.id}`
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return collection;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
//# sourceMappingURL=getImportCollection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/import/getImportCollection.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionBeforeOperationHook,\n CollectionConfig,\n Config,\n} from 'payload'\n\nimport fs from 'fs'\nimport path from 'path'\n\nimport type { ImportConfig, ImportExportPluginConfig } from '../types.js'\nimport type { ImportTaskInput } from './getCreateImportCollectionTask.js'\n\nimport { createImport } from './createImport.js'\nimport { getFields } from './getFields.js'\nimport { handlePreview } from './handlePreview.js'\n\nexport const getImportCollection = ({\n config,\n importConfig,\n pluginConfig,\n}: {\n config: Config\n importConfig?: ImportConfig\n pluginConfig: ImportExportPluginConfig\n}): CollectionConfig => {\n const beforeOperation: CollectionBeforeOperationHook[] = []\n const afterChange: CollectionAfterChangeHook[] = []\n\n // Extract import-specific settings\n const disableJobsQueue = importConfig?.disableJobsQueue ?? false\n const batchSize = importConfig?.batchSize ?? 100\n const defaultVersionStatus = importConfig?.defaultVersionStatus ?? 'published'\n\n // Get collection slugs for the dropdown\n const collectionSlugs = pluginConfig.collections?.map((c) => c.slug)\n\n const collection: CollectionConfig = {\n slug: 'imports',\n access: {\n update: () => false,\n },\n admin: {\n components: {\n edit: {\n SaveButton: '@payloadcms/plugin-import-export/rsc#ImportSaveButton',\n },\n },\n disableCopyToLocale: true,\n group: false,\n useAsTitle: 'filename',\n },\n disableDuplicate: true,\n endpoints: [\n {\n handler: handlePreview,\n method: 'post',\n path: '/preview-data',\n },\n ],\n fields: getFields(config, { collectionSlugs }),\n hooks: {\n afterChange,\n beforeOperation,\n },\n lockDocuments: false,\n upload: {\n filesRequiredOnCreate: true,\n hideFileInputOnCreate: false,\n hideRemoveFile: true,\n mimeTypes: ['text/csv', 'application/json'],\n },\n }\n\n if (disableJobsQueue) {\n // Process the import synchronously after the document (with file) has been created\n afterChange.push(async ({ collection: collectionConfig, doc, operation, req }) => {\n if (operation !== 'create' || doc.status !== 'pending') {\n return doc\n }\n\n const debug = pluginConfig.debug || false\n\n try {\n // Get file data from the uploaded document\n let fileData: Buffer\n let fileMimetype: string\n\n if (doc.url && doc.url.startsWith('http')) {\n // File has been uploaded to external storage (S3, etc.) - fetch it\n const response = await fetch(doc.url)\n if (!response.ok) {\n throw new Error(`Failed to fetch file from URL: ${doc.url}`)\n }\n fileData = Buffer.from(await response.arrayBuffer())\n fileMimetype = doc.mimeType || 'text/csv'\n } else {\n // File is stored locally - read from filesystem\n const filePath = doc.filename\n // Get upload config from the actual sanitized collection config\n const uploadConfig =\n typeof collectionConfig?.upload === 'object' ? collectionConfig.upload : undefined\n const uploadDir = uploadConfig?.staticDir || './uploads'\n const fullPath = path.resolve(uploadDir, filePath)\n fileData = await fs.promises.readFile(fullPath)\n fileMimetype = doc.mimeType || 'text/csv'\n }\n\n const result = await createImport({\n id: doc.id,\n name: doc.filename || 'import',\n batchSize,\n collectionSlug: doc.collectionSlug,\n debug,\n defaultVersionStatus,\n file: {\n name: doc.filename,\n data: fileData,\n mimetype: fileMimetype,\n },\n format: fileMimetype === 'text/csv' ? 'csv' : 'json',\n importMode: doc.importMode || 'create',\n matchField: doc.matchField,\n req,\n userCollection: req?.user?.collection || req?.user?.user?.collection,\n userID: req?.user?.id || req?.user?.user?.id,\n })\n\n // Determine status\n let status: 'completed' | 'failed' | 'partial'\n if (result.errors.length === 0) {\n status = 'completed'\n } else if (result.imported + result.updated === 0) {\n status = 'failed'\n } else {\n status = 'partial'\n }\n\n const summary = {\n imported: result.imported,\n issueDetails:\n result.errors.length > 0\n ? result.errors.map((e) => ({\n data: e.doc,\n error: e.error,\n row: e.index + 1,\n }))\n : undefined,\n issues: result.errors.length,\n total: result.total,\n updated: result.updated,\n }\n\n // Try to update the document with results (may fail due to transaction timing)\n try {\n await req.payload.update({\n id: doc.id,\n collection: collectionConfig.slug,\n data: {\n status,\n summary,\n },\n overrideAccess: true,\n req,\n })\n } catch (updateErr) {\n // Update may fail if document not yet committed, log but continue\n if (debug) {\n req.payload.logger.error({\n err: updateErr,\n msg: `Failed to update import document ${doc.id} with results`,\n })\n }\n }\n\n // Return updated doc for immediate response\n return {\n ...doc,\n status,\n summary,\n }\n } catch (err) {\n const summary = {\n imported: 0,\n issueDetails: [\n {\n data: {},\n error: err instanceof Error ? err.message : String(err),\n row: 0,\n },\n ],\n issues: 1,\n total: 0,\n updated: 0,\n }\n\n // Try to update document with error status\n try {\n await req.payload.update({\n id: doc.id,\n collection: collectionConfig.slug,\n data: {\n status: 'failed',\n summary,\n },\n overrideAccess: true,\n req,\n })\n } catch (updateErr) {\n // Update may fail if document not yet committed, log but continue\n if (debug) {\n req.payload.logger.error({\n err: updateErr,\n msg: `Failed to update import document ${doc.id} with error status`,\n })\n }\n }\n\n if (debug) {\n req.payload.logger.error({\n err,\n msg: 'Import processing failed',\n })\n }\n\n // Return error status for immediate response\n return {\n ...doc,\n status: 'failed',\n summary,\n }\n }\n })\n } else {\n // When jobs queue is enabled, queue the import as a job\n afterChange.push(async ({ collection: collectionConfig, doc, operation, req }) => {\n if (operation !== 'create') {\n return\n }\n\n try {\n // Get file data for job - need to read from disk/URL since req.file is not available in afterChange\n let fileData: Buffer\n if (doc.url && doc.url.startsWith('http')) {\n const response = await fetch(doc.url)\n if (!response.ok) {\n throw new Error(`Failed to fetch file from URL: ${doc.url}`)\n }\n fileData = Buffer.from(await response.arrayBuffer())\n } else {\n const filePath = doc.filename\n // Get upload config from the actual sanitized collection config\n const uploadConfig =\n typeof collectionConfig?.upload === 'object' ? collectionConfig.upload : undefined\n const uploadDir = uploadConfig?.staticDir || './uploads'\n const fullPath = path.resolve(uploadDir, filePath)\n fileData = await fs.promises.readFile(fullPath)\n }\n\n const input: ImportTaskInput = {\n name: doc.filename,\n batchSize,\n collectionSlug: doc.collectionSlug,\n debug: pluginConfig.debug,\n defaultVersionStatus,\n file: {\n name: doc.filename,\n // Convert to base64 for job serialization - will be converted back to Buffer in task handler\n data: fileData.toString('base64') as unknown as Buffer,\n mimetype: doc.mimeType || 'text/csv',\n },\n format: doc.mimeType === 'text/csv' ? 'csv' : 'json',\n importId: doc.id,\n importMode: doc.importMode || 'create',\n importsCollection: collectionConfig.slug,\n matchField: doc.matchField,\n userCollection: req.user?.collection || req?.user?.user?.collection,\n userID: req?.user?.id || req?.user?.user?.id,\n }\n\n await req.payload.jobs.queue({\n input,\n task: 'createCollectionImport',\n })\n } catch (err) {\n req.payload.logger.error({\n err,\n msg: `Failed to queue import job for document ${doc.id}`,\n })\n }\n })\n }\n\n return collection\n}\n"],"names":["fs","path","createImport","getFields","handlePreview","getImportCollection","config","importConfig","pluginConfig","beforeOperation","afterChange","disableJobsQueue","batchSize","defaultVersionStatus","collectionSlugs","collections","map","c","slug","collection","access","update","admin","components","edit","SaveButton","disableCopyToLocale","group","useAsTitle","disableDuplicate","endpoints","handler","method","fields","hooks","lockDocuments","upload","filesRequiredOnCreate","hideFileInputOnCreate","hideRemoveFile","mimeTypes","push","collectionConfig","doc","operation","req","status","debug","fileData","fileMimetype","url","startsWith","response","fetch","ok","Error","Buffer","from","arrayBuffer","mimeType","filePath","filename","uploadConfig","undefined","uploadDir","staticDir","fullPath","resolve","promises","readFile","result","id","name","collectionSlug","file","data","mimetype","format","importMode","matchField","userCollection","user","userID","errors","length","imported","updated","summary","issueDetails","e","error","row","index","issues","total","payload","overrideAccess","updateErr","logger","err","msg","message","String","input","toString","importId","importsCollection","jobs","queue","task"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlePreview.d.ts","sourceRoot":"","sources":["../../src/import/handlePreview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAkB7C,eAAO,MAAM,aAAa,QAAe,cAAc,KAAG,OAAO,CAAC,QAAQ,CA+FzE,CAAA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { addDataAndFileToRequest } from 'payload';
|
|
2
|
+
import { DEFAULT_PREVIEW_LIMIT, MAX_PREVIEW_LIMIT, MIN_PREVIEW_LIMIT, MIN_PREVIEW_PAGE } from '../constants.js';
|
|
3
|
+
import { getImportFieldFunctions } from '../utilities/getImportFieldFunctions.js';
|
|
4
|
+
import { parseCSV } from '../utilities/parseCSV.js';
|
|
5
|
+
import { parseJSON } from '../utilities/parseJSON.js';
|
|
6
|
+
import { removeDisabledFields } from '../utilities/removeDisabledFields.js';
|
|
7
|
+
import { unflattenObject } from '../utilities/unflattenObject.js';
|
|
8
|
+
export const handlePreview = async (req)=>{
|
|
9
|
+
await addDataAndFileToRequest(req);
|
|
10
|
+
const { collectionSlug, fileData, format, previewLimit: rawPreviewLimit = DEFAULT_PREVIEW_LIMIT, previewPage: rawPreviewPage = 1 } = req.data;
|
|
11
|
+
// Validate and clamp pagination values to safe bounds
|
|
12
|
+
const previewLimit = Math.max(MIN_PREVIEW_LIMIT, Math.min(rawPreviewLimit, MAX_PREVIEW_LIMIT));
|
|
13
|
+
const previewPage = Math.max(MIN_PREVIEW_PAGE, rawPreviewPage);
|
|
14
|
+
const targetCollection = req.payload.collections[collectionSlug];
|
|
15
|
+
if (!targetCollection) {
|
|
16
|
+
return Response.json({
|
|
17
|
+
error: `Collection with slug ${collectionSlug} not found`
|
|
18
|
+
}, {
|
|
19
|
+
status: 400
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
if (!fileData) {
|
|
23
|
+
return Response.json({
|
|
24
|
+
error: 'No file data provided'
|
|
25
|
+
}, {
|
|
26
|
+
status: 400
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
// Parse the file data
|
|
31
|
+
let parsedData;
|
|
32
|
+
const buffer = Buffer.from(fileData, 'base64');
|
|
33
|
+
if (format === 'csv') {
|
|
34
|
+
const rawData = await parseCSV({
|
|
35
|
+
data: buffer,
|
|
36
|
+
req
|
|
37
|
+
});
|
|
38
|
+
// Get fromCSV functions for field transformations
|
|
39
|
+
const fromCSVFunctions = getImportFieldFunctions({
|
|
40
|
+
fields: targetCollection.config.flattenedFields || []
|
|
41
|
+
});
|
|
42
|
+
// Unflatten CSV data
|
|
43
|
+
parsedData = rawData.map((doc)=>{
|
|
44
|
+
const unflattened = unflattenObject({
|
|
45
|
+
data: doc,
|
|
46
|
+
fields: targetCollection.config.flattenedFields ?? [],
|
|
47
|
+
fromCSVFunctions,
|
|
48
|
+
req
|
|
49
|
+
});
|
|
50
|
+
return unflattened ?? {};
|
|
51
|
+
}).filter((doc)=>doc && Object.keys(doc).length > 0);
|
|
52
|
+
} else {
|
|
53
|
+
parsedData = parseJSON({
|
|
54
|
+
data: buffer,
|
|
55
|
+
req
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
// Remove disabled fields from the documents
|
|
59
|
+
const disabledFields = targetCollection.config.admin?.custom?.['plugin-import-export']?.disabledFields ?? [];
|
|
60
|
+
if (disabledFields.length > 0) {
|
|
61
|
+
parsedData = parsedData.map((doc)=>removeDisabledFields(doc, disabledFields));
|
|
62
|
+
}
|
|
63
|
+
// Calculate pagination
|
|
64
|
+
const totalDocs = parsedData.length;
|
|
65
|
+
const totalPages = totalDocs === 0 ? 0 : Math.ceil(totalDocs / previewLimit);
|
|
66
|
+
const startIndex = (previewPage - 1) * previewLimit;
|
|
67
|
+
const endIndex = startIndex + previewLimit;
|
|
68
|
+
const paginatedDocs = parsedData.slice(startIndex, endIndex);
|
|
69
|
+
const hasNextPage = previewPage < totalPages;
|
|
70
|
+
const hasPrevPage = previewPage > 1;
|
|
71
|
+
const response = {
|
|
72
|
+
docs: paginatedDocs,
|
|
73
|
+
hasNextPage,
|
|
74
|
+
hasPrevPage,
|
|
75
|
+
limit: previewLimit,
|
|
76
|
+
page: previewPage,
|
|
77
|
+
totalDocs,
|
|
78
|
+
totalPages
|
|
79
|
+
};
|
|
80
|
+
return Response.json(response);
|
|
81
|
+
} catch (error) {
|
|
82
|
+
req.payload.logger.error({
|
|
83
|
+
err: error,
|
|
84
|
+
msg: 'Error parsing import preview data'
|
|
85
|
+
});
|
|
86
|
+
return Response.json({
|
|
87
|
+
error: 'Failed to parse file data'
|
|
88
|
+
}, {
|
|
89
|
+
status: 500
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=handlePreview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/import/handlePreview.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport { addDataAndFileToRequest } from 'payload'\n\nimport type { ImportPreviewResponse } 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 { getImportFieldFunctions } from '../utilities/getImportFieldFunctions.js'\nimport { parseCSV } from '../utilities/parseCSV.js'\nimport { parseJSON } from '../utilities/parseJSON.js'\nimport { removeDisabledFields } from '../utilities/removeDisabledFields.js'\nimport { unflattenObject } from '../utilities/unflattenObject.js'\n\nexport const handlePreview = async (req: PayloadRequest): Promise<Response> => {\n await addDataAndFileToRequest(req)\n\n const {\n collectionSlug,\n fileData,\n format,\n previewLimit: rawPreviewLimit = DEFAULT_PREVIEW_LIMIT,\n previewPage: rawPreviewPage = 1,\n } = req.data as {\n collectionSlug: string\n fileData?: string\n format?: 'csv' | 'json'\n previewLimit?: number\n previewPage?: number\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 if (!fileData) {\n return Response.json({ error: 'No file data provided' }, { status: 400 })\n }\n\n try {\n // Parse the file data\n let parsedData: Record<string, unknown>[]\n const buffer = Buffer.from(fileData, 'base64')\n\n if (format === 'csv') {\n const rawData = await parseCSV({ data: buffer, req })\n\n // Get fromCSV functions for field transformations\n const fromCSVFunctions = getImportFieldFunctions({\n fields: targetCollection.config.flattenedFields || [],\n })\n\n // Unflatten CSV data\n parsedData = rawData\n .map((doc) => {\n const unflattened = unflattenObject({\n data: doc,\n fields: targetCollection.config.flattenedFields ?? [],\n fromCSVFunctions,\n req,\n })\n return unflattened ?? {}\n })\n .filter((doc) => doc && Object.keys(doc).length > 0)\n } else {\n parsedData = parseJSON({ data: buffer, req })\n }\n\n // Remove disabled fields from the documents\n const disabledFields =\n targetCollection.config.admin?.custom?.['plugin-import-export']?.disabledFields ?? []\n\n if (disabledFields.length > 0) {\n parsedData = parsedData.map((doc) => removeDisabledFields(doc, disabledFields))\n }\n\n // Calculate pagination\n const totalDocs = parsedData.length\n const totalPages = totalDocs === 0 ? 0 : Math.ceil(totalDocs / previewLimit)\n const startIndex = (previewPage - 1) * previewLimit\n const endIndex = startIndex + previewLimit\n const paginatedDocs = parsedData.slice(startIndex, endIndex)\n\n const hasNextPage = previewPage < totalPages\n const hasPrevPage = previewPage > 1\n\n const response: ImportPreviewResponse = {\n docs: paginatedDocs,\n hasNextPage,\n hasPrevPage,\n limit: previewLimit,\n page: previewPage,\n totalDocs,\n totalPages,\n }\n\n return Response.json(response)\n } catch (error) {\n req.payload.logger.error({ err: error, msg: 'Error parsing import preview data' })\n return Response.json({ error: 'Failed to parse file data' }, { status: 500 })\n }\n}\n"],"names":["addDataAndFileToRequest","DEFAULT_PREVIEW_LIMIT","MAX_PREVIEW_LIMIT","MIN_PREVIEW_LIMIT","MIN_PREVIEW_PAGE","getImportFieldFunctions","parseCSV","parseJSON","removeDisabledFields","unflattenObject","handlePreview","req","collectionSlug","fileData","format","previewLimit","rawPreviewLimit","previewPage","rawPreviewPage","data","Math","max","min","targetCollection","payload","collections","Response","json","error","status","parsedData","buffer","Buffer","from","rawData","fromCSVFunctions","fields","config","flattenedFields","map","doc","unflattened","filter","Object","keys","length","disabledFields","admin","custom","totalDocs","totalPages","ceil","startIndex","endIndex","paginatedDocs","slice","hasNextPage","hasPrevPage","response","docs","limit","page","logger","err","msg"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Config } from 'payload';
|
|
2
|
-
import type { ImportExportPluginConfig, ToCSVFunction } from './types.js';
|
|
3
|
-
export declare const importExportPlugin: (pluginConfig: ImportExportPluginConfig) => (config: Config) => Config
|
|
2
|
+
import type { FromCSVFunction, ImportExportPluginConfig, ToCSVFunction } from './types.js';
|
|
3
|
+
export declare const importExportPlugin: (pluginConfig: ImportExportPluginConfig) => (config: Config) => Promise<Config>;
|
|
4
4
|
declare module 'payload' {
|
|
5
5
|
interface FieldCustom {
|
|
6
6
|
'plugin-import-export'?: {
|
|
@@ -12,6 +12,7 @@ declare module 'payload' {
|
|
|
12
12
|
* @default false
|
|
13
13
|
*/
|
|
14
14
|
disabled?: boolean;
|
|
15
|
+
fromCSV?: FromCSVFunction;
|
|
15
16
|
/**
|
|
16
17
|
* Custom function used to modify the outgoing csv data by manipulating the data, siblingData or by returning the desired value
|
|
17
18
|
*/
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAKrC,OAAO,KAAK,EACV,eAAe,EACf,wBAAwB,EAExB,aAAa,EACd,MAAM,YAAY,CAAA;AAQnB,eAAO,MAAM,kBAAkB,iBACd,wBAAwB,cACxB,MAAM,KAAG,OAAO,CAAC,MAAM,CA8IrC,CAAA;AAEH,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAiB,WAAW;QAC1B,sBAAsB,CAAC,EAAE;YACvB;;;;;;eAMG;YACH,QAAQ,CAAC,EAAE,OAAO,CAAA;YAClB,OAAO,CAAC,EAAE,eAAe,CAAA;YACzB;;eAEG;YACH,KAAK,CAAC,EAAE,aAAa,CAAA;SACtB,CAAA;KACF;IAED,UAAiB,qBAAqB;QACpC,sBAAsB,CAAC,EAAE;YACvB;;;eAGG;YACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;SAC1B,CAAA;KACF;CACF"}
|
package/dist/index.js
CHANGED
|
@@ -1,41 +1,65 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { flattenObject } from './export/flattenObject.js';
|
|
1
|
+
import { deepMergeSimple } from 'payload';
|
|
3
2
|
import { getCreateCollectionExportTask } from './export/getCreateExportCollectionTask.js';
|
|
4
|
-
import {
|
|
5
|
-
import { getSelect } from './export/getSelect.js';
|
|
6
|
-
import { getExportCollection } from './getExportCollection.js';
|
|
3
|
+
import { getCreateCollectionImportTask } from './import/getCreateImportCollectionTask.js';
|
|
7
4
|
import { translations } from './translations/index.js';
|
|
8
5
|
import { collectDisabledFieldPaths } from './utilities/collectDisabledFieldPaths.js';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
export const importExportPlugin = (pluginConfig)=>(config)=>{
|
|
14
|
-
const exportCollection = getExportCollection({
|
|
6
|
+
import { getPluginCollections } from './utilities/getPluginCollections.js';
|
|
7
|
+
export const importExportPlugin = (pluginConfig)=>async (config)=>{
|
|
8
|
+
// Get all export/import collections and the mappings from target collections to custom collections
|
|
9
|
+
const { customExportSlugMap, customImportSlugMap, exportCollections, importCollections } = await getPluginCollections({
|
|
15
10
|
config,
|
|
16
11
|
pluginConfig
|
|
17
12
|
});
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
// Base collections are at index 0 (always present)
|
|
14
|
+
const baseExportCollection = exportCollections[0];
|
|
15
|
+
const baseImportCollection = importCollections[0];
|
|
16
|
+
// Collect all export and import collection slugs for filtering
|
|
17
|
+
const allExportSlugs = new Set(exportCollections.map((c)=>c.slug));
|
|
18
|
+
const allImportSlugs = new Set(importCollections.map((c)=>c.slug));
|
|
19
|
+
// Initialize collections array if needed
|
|
20
|
+
if (!config.collections) {
|
|
21
|
+
config.collections = [];
|
|
22
|
+
}
|
|
23
|
+
// Push all export/import collections if their slugs don't already exist
|
|
24
|
+
for (const collection of [
|
|
25
|
+
...exportCollections,
|
|
26
|
+
...importCollections
|
|
27
|
+
]){
|
|
28
|
+
const slugExists = config.collections.some((c)=>c.slug === collection.slug);
|
|
29
|
+
if (!slugExists) {
|
|
30
|
+
config.collections.push(collection);
|
|
31
|
+
}
|
|
24
32
|
}
|
|
25
33
|
// inject custom import export provider
|
|
26
34
|
config.admin = config.admin || {};
|
|
27
35
|
config.admin.components = config.admin.components || {};
|
|
28
36
|
config.admin.components.providers = config.admin.components.providers || [];
|
|
29
37
|
config.admin.components.providers.push('@payloadcms/plugin-import-export/rsc#ImportExportProvider');
|
|
30
|
-
((config.jobs ??= {}).tasks ??= []).push(getCreateCollectionExportTask(config
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
((config.jobs ??= {}).tasks ??= []).push(getCreateCollectionExportTask(config));
|
|
39
|
+
config.jobs.tasks.push(getCreateCollectionImportTask(config));
|
|
40
|
+
// Build a map of collection configs for quick lookup
|
|
41
|
+
const collectionConfigMap = new Map();
|
|
42
|
+
if (pluginConfig.collections) {
|
|
43
|
+
for (const collectionConfig of pluginConfig.collections){
|
|
44
|
+
collectionConfigMap.set(collectionConfig.slug, collectionConfig);
|
|
45
|
+
}
|
|
37
46
|
}
|
|
38
|
-
|
|
47
|
+
// Determine which collections to add import/export menu items to
|
|
48
|
+
// Exclude all export and import collections
|
|
49
|
+
const collectionsToUpdate = config.collections.filter((c)=>!allExportSlugs.has(c.slug) && !allImportSlugs.has(c.slug));
|
|
50
|
+
for (const collection of collectionsToUpdate){
|
|
51
|
+
// Get the plugin config for this collection (if specified)
|
|
52
|
+
const collectionPluginConfig = collectionConfigMap.get(collection.slug);
|
|
53
|
+
// If collections array is specified but this collection is not in it, skip
|
|
54
|
+
if (pluginConfig.collections && pluginConfig.collections.length > 0 && !collectionPluginConfig) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
// Determine which export/import collection to use for this collection
|
|
58
|
+
const exportSlugForCollection = customExportSlugMap.get(collection.slug) || baseExportCollection.slug;
|
|
59
|
+
const importSlugForCollection = customImportSlugMap.get(collection.slug) || baseImportCollection.slug;
|
|
60
|
+
// Check if export/import are disabled for this collection
|
|
61
|
+
const exportDisabled = collectionPluginConfig?.export === false;
|
|
62
|
+
const importDisabled = collectionPluginConfig?.import === false;
|
|
39
63
|
if (!collection.admin) {
|
|
40
64
|
collection.admin = {
|
|
41
65
|
components: {
|
|
@@ -47,12 +71,24 @@ export const importExportPlugin = (pluginConfig)=>(config)=>{
|
|
|
47
71
|
if (!components.listMenuItems) {
|
|
48
72
|
components.listMenuItems = [];
|
|
49
73
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
// Add export menu item if not disabled
|
|
75
|
+
if (!exportDisabled) {
|
|
76
|
+
components.listMenuItems.push({
|
|
77
|
+
clientProps: {
|
|
78
|
+
exportCollectionSlug: exportSlugForCollection
|
|
79
|
+
},
|
|
80
|
+
path: '@payloadcms/plugin-import-export/rsc#ExportListMenuItem'
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// Add import menu item if not disabled
|
|
84
|
+
if (!importDisabled) {
|
|
85
|
+
components.listMenuItems.push({
|
|
86
|
+
clientProps: {
|
|
87
|
+
importCollectionSlug: importSlugForCollection
|
|
88
|
+
},
|
|
89
|
+
path: '@payloadcms/plugin-import-export/rsc#ImportListMenuItem'
|
|
90
|
+
});
|
|
91
|
+
}
|
|
56
92
|
// Find fields explicitly marked as disabled for import/export
|
|
57
93
|
const disabledFieldAccessors = collectDisabledFieldPaths(collection.fields);
|
|
58
94
|
// Store disabled field accessors in the admin config for use in the UI
|
|
@@ -64,88 +100,10 @@ export const importExportPlugin = (pluginConfig)=>(config)=>{
|
|
|
64
100
|
}
|
|
65
101
|
};
|
|
66
102
|
collection.admin.components = components;
|
|
67
|
-
}
|
|
103
|
+
}
|
|
68
104
|
if (!config.i18n) {
|
|
69
105
|
config.i18n = {};
|
|
70
106
|
}
|
|
71
|
-
// config.i18n.translations = deepMergeSimple(translations, config.i18n?.translations ?? {})
|
|
72
|
-
// Inject custom REST endpoints into the config
|
|
73
|
-
config.endpoints = config.endpoints || [];
|
|
74
|
-
config.endpoints.push({
|
|
75
|
-
handler: async (req)=>{
|
|
76
|
-
await addDataAndFileToRequest(req);
|
|
77
|
-
const { collectionSlug, draft, fields, limit, locale, page, sort, where } = req.data;
|
|
78
|
-
const collection = req.payload.collections[collectionSlug];
|
|
79
|
-
if (!collection) {
|
|
80
|
-
return Response.json({
|
|
81
|
-
error: `Collection with slug ${collectionSlug} not found`
|
|
82
|
-
}, {
|
|
83
|
-
status: 400
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
const select = Array.isArray(fields) && fields.length > 0 ? getSelect(fields) : undefined;
|
|
87
|
-
const result = await req.payload.find({
|
|
88
|
-
collection: collectionSlug,
|
|
89
|
-
depth: 1,
|
|
90
|
-
draft: draft === 'yes',
|
|
91
|
-
limit: limit && limit > 10 ? 10 : limit,
|
|
92
|
-
locale,
|
|
93
|
-
overrideAccess: false,
|
|
94
|
-
page,
|
|
95
|
-
req,
|
|
96
|
-
select,
|
|
97
|
-
sort,
|
|
98
|
-
where
|
|
99
|
-
});
|
|
100
|
-
const isCSV = req?.data?.format === 'csv';
|
|
101
|
-
const docs = result.docs;
|
|
102
|
-
let transformed = [];
|
|
103
|
-
if (isCSV) {
|
|
104
|
-
const toCSVFunctions = getCustomFieldFunctions({
|
|
105
|
-
fields: collection.config.fields
|
|
106
|
-
});
|
|
107
|
-
const possibleKeys = getFlattenedFieldKeys(collection.config.fields);
|
|
108
|
-
transformed = docs.map((doc)=>{
|
|
109
|
-
const row = flattenObject({
|
|
110
|
-
doc,
|
|
111
|
-
fields,
|
|
112
|
-
toCSVFunctions
|
|
113
|
-
});
|
|
114
|
-
for (const key of possibleKeys){
|
|
115
|
-
if (!(key in row)) {
|
|
116
|
-
row[key] = null;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return row;
|
|
120
|
-
});
|
|
121
|
-
} else {
|
|
122
|
-
const disabledFields = collection.config.admin.custom?.['plugin-import-export']?.disabledFields;
|
|
123
|
-
transformed = docs.map((doc)=>{
|
|
124
|
-
let output = {
|
|
125
|
-
...doc
|
|
126
|
-
};
|
|
127
|
-
// Remove disabled fields first
|
|
128
|
-
output = removeDisabledFields(output, disabledFields);
|
|
129
|
-
// Then trim to selected fields only (if fields are provided)
|
|
130
|
-
if (Array.isArray(fields) && fields.length > 0) {
|
|
131
|
-
const trimmed = {};
|
|
132
|
-
for (const key of fields){
|
|
133
|
-
const value = getValueAtPath(output, key);
|
|
134
|
-
setNestedValue(trimmed, key, value ?? null);
|
|
135
|
-
}
|
|
136
|
-
output = trimmed;
|
|
137
|
-
}
|
|
138
|
-
return output;
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
return Response.json({
|
|
142
|
-
docs: transformed,
|
|
143
|
-
totalDocs: result.totalDocs
|
|
144
|
-
});
|
|
145
|
-
},
|
|
146
|
-
method: 'post',
|
|
147
|
-
path: '/preview-data'
|
|
148
|
-
});
|
|
149
107
|
/**
|
|
150
108
|
* Merge plugin translations
|
|
151
109
|
*/ const simplifiedTranslations = Object.entries(translations).reduce((acc, [key, value])=>{
|