@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,109 +1,103 @@
1
- import { traverseFields } from 'payload';
1
+ import { registerFieldHooks } from './flattenedFields.js';
2
+ import { getPolymorphicRelId, isPolymorphicRelValue } from './polymorphicRel.js';
2
3
  /**
3
- * Gets custom toCSV field functions for export.
4
- * These functions transform field values when flattening documents for CSV export.
4
+ * Builds a map from logical field path (e.g. `content_textBlock_body`) to
5
+ * the export hook entry. Paths include block slugs but never array indices.
5
6
  */ export const getExportFieldFunctions = ({ fields })=>{
6
7
  const result = {};
7
- const buildCustomFunctions = ({ field, parentRef, ref })=>{
8
- // @ts-expect-error ref is untyped
9
- ref.prefix = parentRef.prefix || '';
10
- if (field.type === 'group' || field.type === 'tab') {
11
- // @ts-expect-error ref is untyped
12
- const parentPrefix = parentRef?.prefix ? `${parentRef.prefix}_` : '';
13
- // @ts-expect-error ref is untyped
14
- ref.prefix = `${parentPrefix}${field.name}_`;
15
- }
16
- if (typeof field.custom?.['plugin-import-export']?.toCSV === 'function') {
17
- // @ts-expect-error ref is untyped
18
- result[`${ref.prefix}${field.name}`] = field.custom['plugin-import-export']?.toCSV;
19
- } else if (field.type === 'json' || field.type === 'richText') {
20
- // Serialize JSON and richText fields as JSON strings in a single column
21
- // This prevents them from being flattened into multiple columns
22
- // @ts-expect-error ref is untyped
23
- result[`${ref.prefix}${field.name}`] = ({ value })=>{
24
- if (value === null || value === undefined) {
25
- return value;
26
- }
27
- if (typeof value === 'object') {
28
- return JSON.stringify(value);
29
- }
8
+ registerFieldHooks(fields, '', result, registerExportHandler);
9
+ return result;
10
+ };
11
+ const registerExportHandler = (field, fullKey, result)=>{
12
+ const beforeExport = field.custom?.['plugin-import-export']?.hooks?.beforeExport;
13
+ const toCSV = field.custom?.['plugin-import-export']?.toCSV;
14
+ if (typeof beforeExport === 'function') {
15
+ result[fullKey] = {
16
+ type: 'beforeExport',
17
+ fn: beforeExport
18
+ };
19
+ return;
20
+ }
21
+ if (typeof toCSV === 'function') {
22
+ result[fullKey] = {
23
+ type: 'toCSV',
24
+ fn: toCSV
25
+ };
26
+ return;
27
+ }
28
+ const registerHandler = (handler)=>{
29
+ result[fullKey] = {
30
+ type: 'beforeExport',
31
+ fn: handler
32
+ };
33
+ };
34
+ if (field.type === 'json' || field.type === 'richText') {
35
+ registerHandler(({ format, value })=>{
36
+ if (format === 'json') {
30
37
  return value;
31
- };
32
- } else if (field.type === 'date') {
33
- // Handle date fields - return value as-is (ISO string format)
34
- // This prevents the flattener from treating the document as having
35
- // nested sibling properties like _tz that shouldn't be auto-included
36
- // @ts-expect-error ref is untyped
37
- const fieldKey = `${ref.prefix}${field.name}`;
38
- result[fieldKey] = ({ value })=>value;
39
- } else if (field.type === 'relationship' || field.type === 'upload') {
40
- if (field.hasMany !== true) {
41
- if (!Array.isArray(field.relationTo)) {
42
- // monomorphic single
43
- // @ts-expect-error ref is untyped
44
- result[`${ref.prefix}${field.name}`] = ({ value })=>typeof value === 'object' && value && 'id' in value ? value.id : value;
45
- } else {
46
- // polymorphic single
47
- // @ts-expect-error ref is untyped
48
- result[`${ref.prefix}${field.name}`] = ({ data, value })=>{
49
- if (value && typeof value === 'object' && 'relationTo' in value && 'value' in value) {
50
- const relationTo = value.relationTo;
51
- const relatedDoc = value.value;
52
- if (relatedDoc && typeof relatedDoc === 'object') {
53
- // @ts-expect-error ref is untyped
54
- data[`${ref.prefix}${field.name}_id`] = relatedDoc.id;
55
- // @ts-expect-error ref is untyped
56
- data[`${ref.prefix}${field.name}_relationTo`] = relationTo;
57
- }
58
- }
59
- return undefined // prevents further flattening
60
- ;
61
- };
62
- }
63
- } else {
64
- if (!Array.isArray(field.relationTo)) {
65
- // monomorphic many
66
- // @ts-expect-error ref is untyped
67
- result[`${ref.prefix}${field.name}`] = ({ data, value })=>{
68
- if (Array.isArray(value)) {
69
- value.forEach((val, i)=>{
70
- const id = typeof val === 'object' && val ? val.id : val;
71
- // @ts-expect-error ref is untyped
72
- data[`${ref.prefix}${field.name}_${i}_id`] = id;
73
- });
74
- }
75
- return undefined // prevents further flattening
76
- ;
77
- };
78
- } else {
79
- // polymorphic many
80
- // @ts-expect-error ref is untyped
81
- result[`${ref.prefix}${field.name}`] = ({ data, value })=>{
82
- if (Array.isArray(value)) {
83
- value.forEach((val, i)=>{
84
- if (val && typeof val === 'object') {
85
- const relationTo = val.relationTo;
86
- const relatedDoc = val.value;
87
- if (relationTo && relatedDoc && typeof relatedDoc === 'object') {
88
- // @ts-expect-error ref is untyped
89
- data[`${ref.prefix}${field.name}_${i}_id`] = relatedDoc.id;
90
- // @ts-expect-error ref is untyped
91
- data[`${ref.prefix}${field.name}_${i}_relationTo`] = relationTo;
92
- }
93
- }
94
- });
95
- }
96
- return undefined;
97
- };
38
+ }
39
+ if (value === null || value === undefined) {
40
+ return value;
41
+ }
42
+ if (typeof value === 'object') {
43
+ return JSON.stringify(value);
44
+ }
45
+ return value;
46
+ });
47
+ return;
48
+ }
49
+ if (field.type === 'date') {
50
+ registerHandler(({ value })=>value);
51
+ return;
52
+ }
53
+ if (field.type !== 'relationship' && field.type !== 'upload') {
54
+ return;
55
+ }
56
+ if (field.hasMany !== true) {
57
+ if (!Array.isArray(field.relationTo)) {
58
+ registerHandler(({ value })=>typeof value === 'object' && value && 'id' in value ? value.id : value);
59
+ return;
60
+ }
61
+ registerHandler(({ siblingData, value })=>{
62
+ if (isPolymorphicRelValue(value)) {
63
+ const id = getPolymorphicRelId(value);
64
+ if (id !== undefined) {
65
+ siblingData[`${fullKey}_id`] = id;
66
+ siblingData[`${fullKey}_relationTo`] = value.relationTo;
98
67
  }
99
68
  }
69
+ return null;
70
+ });
71
+ return;
72
+ }
73
+ if (!Array.isArray(field.relationTo)) {
74
+ registerHandler(({ siblingData, value })=>{
75
+ if (Array.isArray(value)) {
76
+ value.forEach((val, i)=>{
77
+ const id = typeof val === 'object' && val ? val.id : val;
78
+ siblingData[`${fullKey}_${i}_id`] = id;
79
+ });
80
+ return null;
81
+ }
82
+ return undefined;
83
+ });
84
+ return;
85
+ }
86
+ registerHandler(({ siblingData, value })=>{
87
+ if (Array.isArray(value)) {
88
+ value.forEach((val, i)=>{
89
+ if (isPolymorphicRelValue(val)) {
90
+ const id = getPolymorphicRelId(val);
91
+ if (id !== undefined) {
92
+ siblingData[`${fullKey}_${i}_id`] = id;
93
+ siblingData[`${fullKey}_${i}_relationTo`] = val.relationTo;
94
+ }
95
+ }
96
+ });
97
+ return null;
100
98
  }
101
- };
102
- traverseFields({
103
- callback: buildCustomFunctions,
104
- fields
99
+ return undefined;
105
100
  });
106
- return result;
107
101
  };
108
102
 
109
103
  //# sourceMappingURL=getExportFieldFunctions.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/getExportFieldFunctions.ts"],"sourcesContent":["import { type FlattenedField, traverseFields, type TraverseFieldsCallback } from 'payload'\n\nimport type { ToCSVFunction } from '../types.js'\n\ntype Args = {\n fields: FlattenedField[]\n}\n\n/**\n * Gets custom toCSV field functions for export.\n * These functions transform field values when flattening documents for CSV export.\n */\nexport const getExportFieldFunctions = ({ fields }: Args): Record<string, ToCSVFunction> => {\n const result: Record<string, ToCSVFunction> = {}\n\n const buildCustomFunctions: TraverseFieldsCallback = ({ field, parentRef, ref }) => {\n // @ts-expect-error ref is untyped\n ref.prefix = parentRef.prefix || ''\n if (field.type === 'group' || field.type === 'tab') {\n // @ts-expect-error ref is untyped\n const parentPrefix = parentRef?.prefix ? `${parentRef.prefix}_` : ''\n // @ts-expect-error ref is untyped\n ref.prefix = `${parentPrefix}${field.name}_`\n }\n\n if (typeof field.custom?.['plugin-import-export']?.toCSV === 'function') {\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = field.custom['plugin-import-export']?.toCSV\n } else if (field.type === 'json' || field.type === 'richText') {\n // Serialize JSON and richText fields as JSON strings in a single column\n // This prevents them from being flattened into multiple columns\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({ value }) => {\n if (value === null || value === undefined) {\n return value\n }\n if (typeof value === 'object') {\n return JSON.stringify(value)\n }\n return value\n }\n } else if (field.type === 'date') {\n // Handle date fields - return value as-is (ISO string format)\n // This prevents the flattener from treating the document as having\n // nested sibling properties like _tz that shouldn't be auto-included\n // @ts-expect-error ref is untyped\n const fieldKey = `${ref.prefix}${field.name}`\n\n result[fieldKey] = ({ value }) => value\n } else if (field.type === 'relationship' || field.type === 'upload') {\n if (field.hasMany !== true) {\n if (!Array.isArray(field.relationTo)) {\n // monomorphic single\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({ value }) =>\n typeof value === 'object' && value && 'id' in value ? value.id : value\n } else {\n // polymorphic single\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({ data, value }) => {\n if (value && typeof value === 'object' && 'relationTo' in value && 'value' in value) {\n const relationTo = (value as { relationTo: string; value: { id: number | string } })\n .relationTo\n const relatedDoc = (value as { relationTo: string; value: { id: number | string } })\n .value\n if (relatedDoc && typeof relatedDoc === 'object') {\n // @ts-expect-error ref is untyped\n data[`${ref.prefix}${field.name}_id`] = relatedDoc.id\n // @ts-expect-error ref is untyped\n data[`${ref.prefix}${field.name}_relationTo`] = relationTo\n }\n }\n return undefined // prevents further flattening\n }\n }\n } else {\n if (!Array.isArray(field.relationTo)) {\n // monomorphic many\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({\n data,\n value,\n }: {\n data: Record<string, unknown>\n value: Array<number | Record<string, any> | string> | undefined\n }) => {\n if (Array.isArray(value)) {\n value.forEach((val, i) => {\n const id = typeof val === 'object' && val ? val.id : val\n // @ts-expect-error ref is untyped\n data[`${ref.prefix}${field.name}_${i}_id`] = id\n })\n }\n return undefined // prevents further flattening\n }\n } else {\n // polymorphic many\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({\n data,\n value,\n }: {\n data: Record<string, unknown>\n value: Array<Record<string, any>> | undefined\n }) => {\n if (Array.isArray(value)) {\n value.forEach((val, i) => {\n if (val && typeof val === 'object') {\n const relationTo = val.relationTo\n const relatedDoc = val.value\n if (relationTo && relatedDoc && typeof relatedDoc === 'object') {\n // @ts-expect-error ref is untyped\n data[`${ref.prefix}${field.name}_${i}_id`] = relatedDoc.id\n // @ts-expect-error ref is untyped\n data[`${ref.prefix}${field.name}_${i}_relationTo`] = relationTo\n }\n }\n })\n }\n return undefined\n }\n }\n }\n }\n }\n\n traverseFields({ callback: buildCustomFunctions, fields })\n\n return result\n}\n"],"names":["traverseFields","getExportFieldFunctions","fields","result","buildCustomFunctions","field","parentRef","ref","prefix","type","parentPrefix","name","custom","toCSV","value","undefined","JSON","stringify","fieldKey","hasMany","Array","isArray","relationTo","id","data","relatedDoc","forEach","val","i","callback"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utilities/getExportFieldFunctions.ts"],"sourcesContent":["import type { FlattenedField } from 'payload'\n\nimport type { ExportFieldHookEntry, FieldBeforeExportHook } from '../types.js'\n\nimport { registerFieldHooks } from './flattenedFields.js'\nimport { getPolymorphicRelId, isPolymorphicRelValue } from './polymorphicRel.js'\n\ntype Args = {\n fields: FlattenedField[]\n}\n\n/**\n * Builds a map from logical field path (e.g. `content_textBlock_body`) to\n * the export hook entry. Paths include block slugs but never array indices.\n */\nexport const getExportFieldFunctions = ({ fields }: Args): Record<string, ExportFieldHookEntry> => {\n const result: Record<string, ExportFieldHookEntry> = {}\n registerFieldHooks(fields, '', result, registerExportHandler)\n return result\n}\n\nconst registerExportHandler = (\n field: FlattenedField,\n fullKey: string,\n result: Record<string, ExportFieldHookEntry>,\n): void => {\n const beforeExport = field.custom?.['plugin-import-export']?.hooks?.beforeExport\n\n const toCSV = field.custom?.['plugin-import-export']?.toCSV\n\n if (typeof beforeExport === 'function') {\n result[fullKey] = { type: 'beforeExport', fn: beforeExport }\n return\n }\n\n if (typeof toCSV === 'function') {\n result[fullKey] = { type: 'toCSV', fn: toCSV }\n return\n }\n\n const registerHandler = (handler: FieldBeforeExportHook) => {\n result[fullKey] = { type: 'beforeExport', fn: handler }\n }\n\n if (field.type === 'json' || field.type === 'richText') {\n registerHandler(({ format, value }) => {\n if (format === 'json') {\n return value\n }\n if (value === null || value === undefined) {\n return value\n }\n if (typeof value === 'object') {\n return JSON.stringify(value)\n }\n return value\n })\n return\n }\n\n if (field.type === 'date') {\n registerHandler(({ value }) => value)\n return\n }\n\n if (field.type !== 'relationship' && field.type !== 'upload') {\n return\n }\n\n if (field.hasMany !== true) {\n if (!Array.isArray(field.relationTo)) {\n registerHandler(({ value }) =>\n typeof value === 'object' && value && 'id' in value ? value.id : value,\n )\n return\n }\n\n registerHandler(({ siblingData, value }) => {\n if (isPolymorphicRelValue(value)) {\n const id = getPolymorphicRelId(value)\n if (id !== undefined) {\n siblingData[`${fullKey}_id`] = id\n siblingData[`${fullKey}_relationTo`] = value.relationTo\n }\n }\n return null\n })\n return\n }\n\n if (!Array.isArray(field.relationTo)) {\n registerHandler(({ siblingData, value }) => {\n if (Array.isArray(value)) {\n value.forEach((val, i) => {\n const id = typeof val === 'object' && val ? (val as { id: unknown }).id : val\n siblingData[`${fullKey}_${i}_id`] = id\n })\n return null\n }\n return undefined\n })\n return\n }\n\n registerHandler(({ siblingData, value }) => {\n if (Array.isArray(value)) {\n value.forEach((val, i) => {\n if (isPolymorphicRelValue(val)) {\n const id = getPolymorphicRelId(val)\n if (id !== undefined) {\n siblingData[`${fullKey}_${i}_id`] = id\n siblingData[`${fullKey}_${i}_relationTo`] = val.relationTo\n }\n }\n })\n return null\n }\n return undefined\n })\n}\n"],"names":["registerFieldHooks","getPolymorphicRelId","isPolymorphicRelValue","getExportFieldFunctions","fields","result","registerExportHandler","field","fullKey","beforeExport","custom","hooks","toCSV","type","fn","registerHandler","handler","format","value","undefined","JSON","stringify","hasMany","Array","isArray","relationTo","id","siblingData","forEach","val","i"],"mappings":"AAIA,SAASA,kBAAkB,QAAQ,uBAAsB;AACzD,SAASC,mBAAmB,EAAEC,qBAAqB,QAAQ,sBAAqB;AAMhF;;;CAGC,GACD,OAAO,MAAMC,0BAA0B,CAAC,EAAEC,MAAM,EAAQ;IACtD,MAAMC,SAA+C,CAAC;IACtDL,mBAAmBI,QAAQ,IAAIC,QAAQC;IACvC,OAAOD;AACT,EAAC;AAED,MAAMC,wBAAwB,CAC5BC,OACAC,SACAH;IAEA,MAAMI,eAAeF,MAAMG,MAAM,EAAE,CAAC,uBAAuB,EAAEC,OAAOF;IAEpE,MAAMG,QAAQL,MAAMG,MAAM,EAAE,CAAC,uBAAuB,EAAEE;IAEtD,IAAI,OAAOH,iBAAiB,YAAY;QACtCJ,MAAM,CAACG,QAAQ,GAAG;YAAEK,MAAM;YAAgBC,IAAIL;QAAa;QAC3D;IACF;IAEA,IAAI,OAAOG,UAAU,YAAY;QAC/BP,MAAM,CAACG,QAAQ,GAAG;YAAEK,MAAM;YAASC,IAAIF;QAAM;QAC7C;IACF;IAEA,MAAMG,kBAAkB,CAACC;QACvBX,MAAM,CAACG,QAAQ,GAAG;YAAEK,MAAM;YAAgBC,IAAIE;QAAQ;IACxD;IAEA,IAAIT,MAAMM,IAAI,KAAK,UAAUN,MAAMM,IAAI,KAAK,YAAY;QACtDE,gBAAgB,CAAC,EAAEE,MAAM,EAAEC,KAAK,EAAE;YAChC,IAAID,WAAW,QAAQ;gBACrB,OAAOC;YACT;YACA,IAAIA,UAAU,QAAQA,UAAUC,WAAW;gBACzC,OAAOD;YACT;YACA,IAAI,OAAOA,UAAU,UAAU;gBAC7B,OAAOE,KAAKC,SAAS,CAACH;YACxB;YACA,OAAOA;QACT;QACA;IACF;IAEA,IAAIX,MAAMM,IAAI,KAAK,QAAQ;QACzBE,gBAAgB,CAAC,EAAEG,KAAK,EAAE,GAAKA;QAC/B;IACF;IAEA,IAAIX,MAAMM,IAAI,KAAK,kBAAkBN,MAAMM,IAAI,KAAK,UAAU;QAC5D;IACF;IAEA,IAAIN,MAAMe,OAAO,KAAK,MAAM;QAC1B,IAAI,CAACC,MAAMC,OAAO,CAACjB,MAAMkB,UAAU,GAAG;YACpCV,gBAAgB,CAAC,EAAEG,KAAK,EAAE,GACxB,OAAOA,UAAU,YAAYA,SAAS,QAAQA,QAAQA,MAAMQ,EAAE,GAAGR;YAEnE;QACF;QAEAH,gBAAgB,CAAC,EAAEY,WAAW,EAAET,KAAK,EAAE;YACrC,IAAIhB,sBAAsBgB,QAAQ;gBAChC,MAAMQ,KAAKzB,oBAAoBiB;gBAC/B,IAAIQ,OAAOP,WAAW;oBACpBQ,WAAW,CAAC,GAAGnB,QAAQ,GAAG,CAAC,CAAC,GAAGkB;oBAC/BC,WAAW,CAAC,GAAGnB,QAAQ,WAAW,CAAC,CAAC,GAAGU,MAAMO,UAAU;gBACzD;YACF;YACA,OAAO;QACT;QACA;IACF;IAEA,IAAI,CAACF,MAAMC,OAAO,CAACjB,MAAMkB,UAAU,GAAG;QACpCV,gBAAgB,CAAC,EAAEY,WAAW,EAAET,KAAK,EAAE;YACrC,IAAIK,MAAMC,OAAO,CAACN,QAAQ;gBACxBA,MAAMU,OAAO,CAAC,CAACC,KAAKC;oBAClB,MAAMJ,KAAK,OAAOG,QAAQ,YAAYA,MAAM,AAACA,IAAwBH,EAAE,GAAGG;oBAC1EF,WAAW,CAAC,GAAGnB,QAAQ,CAAC,EAAEsB,EAAE,GAAG,CAAC,CAAC,GAAGJ;gBACtC;gBACA,OAAO;YACT;YACA,OAAOP;QACT;QACA;IACF;IAEAJ,gBAAgB,CAAC,EAAEY,WAAW,EAAET,KAAK,EAAE;QACrC,IAAIK,MAAMC,OAAO,CAACN,QAAQ;YACxBA,MAAMU,OAAO,CAAC,CAACC,KAAKC;gBAClB,IAAI5B,sBAAsB2B,MAAM;oBAC9B,MAAMH,KAAKzB,oBAAoB4B;oBAC/B,IAAIH,OAAOP,WAAW;wBACpBQ,WAAW,CAAC,GAAGnB,QAAQ,CAAC,EAAEsB,EAAE,GAAG,CAAC,CAAC,GAAGJ;wBACpCC,WAAW,CAAC,GAAGnB,QAAQ,CAAC,EAAEsB,EAAE,WAAW,CAAC,CAAC,GAAGD,IAAIJ,UAAU;oBAC5D;gBACF;YACF;YACA,OAAO;QACT;QACA,OAAON;IACT;AACF"}
@@ -0,0 +1,50 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { getExportFieldFunctions } from './getExportFieldFunctions.js';
3
+ describe('getExportFieldFunctions registration', ()=>{
4
+ it('should not collide bare-key entries when two same-named fields with built-in handlers exist in different positions', ()=>{
5
+ const fields = [
6
+ {
7
+ name: 'groupA',
8
+ type: 'group',
9
+ flattenedFields: [
10
+ {
11
+ name: 'data',
12
+ type: 'json'
13
+ }
14
+ ]
15
+ },
16
+ {
17
+ name: 'groupB',
18
+ type: 'group',
19
+ flattenedFields: [
20
+ {
21
+ name: 'data',
22
+ type: 'json'
23
+ }
24
+ ]
25
+ }
26
+ ];
27
+ const result = getExportFieldFunctions({
28
+ fields
29
+ });
30
+ // Both nested paths must be registered (not overwritten by collision)
31
+ expect(result['groupA_data']).toBeDefined();
32
+ expect(result['groupB_data']).toBeDefined();
33
+ // No bare-key fallback should exist for nested fields — that's the bug
34
+ expect(result['data']).toBeUndefined();
35
+ });
36
+ it('should still register a top-level field at its name', ()=>{
37
+ const fields = [
38
+ {
39
+ name: 'topLevelData',
40
+ type: 'json'
41
+ }
42
+ ];
43
+ const result = getExportFieldFunctions({
44
+ fields
45
+ });
46
+ expect(result['topLevelData']).toBeDefined();
47
+ });
48
+ });
49
+
50
+ //# sourceMappingURL=getExportFieldFunctions.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/getExportFieldFunctions.spec.ts"],"sourcesContent":["import { FlattenedField } from 'payload'\n\nimport { describe, expect, it } from 'vitest'\n\nimport { getExportFieldFunctions } from './getExportFieldFunctions.js'\n\ndescribe('getExportFieldFunctions registration', () => {\n it('should not collide bare-key entries when two same-named fields with built-in handlers exist in different positions', () => {\n const fields: FlattenedField[] = [\n {\n name: 'groupA',\n type: 'group',\n flattenedFields: [{ name: 'data', type: 'json' } as FlattenedField],\n } as unknown as FlattenedField,\n {\n name: 'groupB',\n type: 'group',\n flattenedFields: [{ name: 'data', type: 'json' } as FlattenedField],\n } as unknown as FlattenedField,\n ]\n\n const result = getExportFieldFunctions({ fields })\n\n // Both nested paths must be registered (not overwritten by collision)\n expect(result['groupA_data']).toBeDefined()\n expect(result['groupB_data']).toBeDefined()\n\n // No bare-key fallback should exist for nested fields — that's the bug\n expect(result['data']).toBeUndefined()\n })\n\n it('should still register a top-level field at its name', () => {\n const fields: FlattenedField[] = [{ name: 'topLevelData', type: 'json' } as FlattenedField]\n\n const result = getExportFieldFunctions({ fields })\n\n expect(result['topLevelData']).toBeDefined()\n })\n})\n"],"names":["describe","expect","it","getExportFieldFunctions","fields","name","type","flattenedFields","result","toBeDefined","toBeUndefined"],"mappings":"AAEA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,uBAAuB,QAAQ,+BAA8B;AAEtEH,SAAS,wCAAwC;IAC/CE,GAAG,sHAAsH;QACvH,MAAME,SAA2B;YAC/B;gBACEC,MAAM;gBACNC,MAAM;gBACNC,iBAAiB;oBAAC;wBAAEF,MAAM;wBAAQC,MAAM;oBAAO;iBAAoB;YACrE;YACA;gBACED,MAAM;gBACNC,MAAM;gBACNC,iBAAiB;oBAAC;wBAAEF,MAAM;wBAAQC,MAAM;oBAAO;iBAAoB;YACrE;SACD;QAED,MAAME,SAASL,wBAAwB;YAAEC;QAAO;QAEhD,sEAAsE;QACtEH,OAAOO,MAAM,CAAC,cAAc,EAAEC,WAAW;QACzCR,OAAOO,MAAM,CAAC,cAAc,EAAEC,WAAW;QAEzC,uEAAuE;QACvER,OAAOO,MAAM,CAAC,OAAO,EAAEE,aAAa;IACtC;IAEAR,GAAG,uDAAuD;QACxD,MAAME,SAA2B;YAAC;gBAAEC,MAAM;gBAAgBC,MAAM;YAAO;SAAoB;QAE3F,MAAME,SAASL,wBAAwB;YAAEC;QAAO;QAEhDH,OAAOO,MAAM,CAAC,eAAe,EAAEC,WAAW;IAC5C;AACF"}
@@ -1,12 +1,12 @@
1
- import { type FlattenedField } from 'payload';
2
- import type { FromCSVFunction } from '../types.js';
1
+ import type { FlattenedField } from 'payload';
2
+ import type { ImportFieldHookEntry } from '../types.js';
3
3
  type Args = {
4
4
  fields: FlattenedField[];
5
5
  };
6
6
  /**
7
- * Gets custom fromCSV field functions for import.
8
- * These functions transform field values when unflattening CSV data for import.
7
+ * Builds a map from logical field path (e.g. `content_textBlock_body`) to
8
+ * the import hook entry. Paths include block slugs but never array indices.
9
9
  */
10
- export declare const getImportFieldFunctions: ({ fields }: Args) => Record<string, FromCSVFunction>;
10
+ export declare const getImportFieldFunctions: ({ fields }: Args) => Record<string, ImportFieldHookEntry>;
11
11
  export {};
12
12
  //# sourceMappingURL=getImportFieldFunctions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getImportFieldFunctions.d.ts","sourceRoot":"","sources":["../../src/utilities/getImportFieldFunctions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAA+C,MAAM,SAAS,CAAA;AAE1F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD,KAAK,IAAI,GAAG;IACV,MAAM,EAAE,cAAc,EAAE,CAAA;CACzB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,eAAgB,IAAI,KAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CA8GxF,CAAA"}
1
+ {"version":3,"file":"getImportFieldFunctions.d.ts","sourceRoot":"","sources":["../../src/utilities/getImportFieldFunctions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,OAAO,KAAK,EAAyB,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAI9E,KAAK,IAAI,GAAG;IACV,MAAM,EAAE,cAAc,EAAE,CAAA;CACzB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,eAAgB,IAAI,KAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAI7F,CAAA"}
@@ -1,116 +1,116 @@
1
- import { traverseFields } from 'payload';
1
+ import { registerFieldHooks } from './flattenedFields.js';
2
2
  /**
3
- * Gets custom fromCSV field functions for import.
4
- * These functions transform field values when unflattening CSV data for import.
3
+ * Builds a map from logical field path (e.g. `content_textBlock_body`) to
4
+ * the import hook entry. Paths include block slugs but never array indices.
5
5
  */ export const getImportFieldFunctions = ({ fields })=>{
6
6
  const result = {};
7
- const buildCustomFunctions = ({ field, parentRef, ref })=>{
8
- // @ts-expect-error ref is untyped
9
- ref.prefix = parentRef.prefix || '';
10
- if (field.type === 'group' || field.type === 'tab') {
11
- // @ts-expect-error ref is untyped
12
- const parentPrefix = parentRef?.prefix ? `${parentRef.prefix}_` : '';
13
- // @ts-expect-error ref is untyped
14
- ref.prefix = `${parentPrefix}${field.name}_`;
7
+ registerFieldHooks(fields, '', result, registerImportHandler);
8
+ return result;
9
+ };
10
+ const registerImportHandler = (field, fullKey, result)=>{
11
+ const beforeImport = field.custom?.['plugin-import-export']?.hooks?.beforeImport;
12
+ const fromCSV = field.custom?.['plugin-import-export']?.fromCSV;
13
+ if (typeof beforeImport === 'function') {
14
+ result[fullKey] = {
15
+ type: 'beforeImport',
16
+ fn: beforeImport
17
+ };
18
+ return;
19
+ }
20
+ if (typeof fromCSV === 'function') {
21
+ result[fullKey] = {
22
+ type: 'fromCSV',
23
+ fn: fromCSV
24
+ };
25
+ return;
26
+ }
27
+ const registerBeforeImport = (fn)=>{
28
+ result[fullKey] = {
29
+ type: 'beforeImport',
30
+ fn
31
+ };
32
+ };
33
+ if (field.type === 'relationship' || field.type === 'upload') {
34
+ if (field.hasMany !== true) {
35
+ if (!Array.isArray(field.relationTo)) {
36
+ registerBeforeImport(({ value })=>value);
37
+ }
38
+ } else if (!Array.isArray(field.relationTo)) {
39
+ registerBeforeImport(({ value })=>value);
15
40
  }
16
- if (typeof field.custom?.['plugin-import-export']?.fromCSV === 'function') {
17
- // @ts-expect-error ref is untyped
18
- result[`${ref.prefix}${field.name}`] = field.custom['plugin-import-export']?.fromCSV;
19
- } else if (field.type === 'relationship' || field.type === 'upload') {
20
- if (field.hasMany !== true) {
21
- if (!Array.isArray(field.relationTo)) {
22
- // monomorphic single relationship - simple ID to value conversion
23
- // @ts-expect-error ref is untyped
24
- result[`${ref.prefix}${field.name}`] = ({ value })=>{
25
- // If it's already an object (from JSON import), return as-is
26
- if (typeof value === 'object' && value !== null) {
27
- return value;
28
- }
29
- // Convert string/number ID to relationship value
30
- return value;
31
- };
32
- } else {
33
- // Polymorphic single: handled in unflattenObject via _id/_relationTo columns
34
- }
35
- } else {
36
- if (!Array.isArray(field.relationTo)) {
37
- // @ts-expect-error ref is untyped
38
- result[`${ref.prefix}${field.name}`] = ({ value })=>{
39
- if (Array.isArray(value)) {
40
- return value;
41
- }
42
- return value;
43
- };
44
- } else {
45
- // Polymorphic many: handled in unflattenObject
46
- }
41
+ return;
42
+ }
43
+ if (field.type === 'number') {
44
+ if (field.hasMany) {
45
+ registerBeforeImport(({ value })=>value);
46
+ return;
47
+ }
48
+ registerBeforeImport(({ value })=>{
49
+ if (isEmptyImportValue(value)) {
50
+ return undefined;
47
51
  }
48
- } else if (field.type === 'number') {
49
- if (field.hasMany) {
50
- // @ts-expect-error ref is untyped
51
- result[`${ref.prefix}${field.name}`] = ({ value })=>value;
52
- } else {
53
- // @ts-expect-error ref is untyped
54
- result[`${ref.prefix}${field.name}`] = ({ value })=>{
55
- if (typeof value === 'number') {
56
- return value;
57
- }
58
- if (typeof value === 'string') {
59
- const parsed = parseFloat(value);
60
- return isNaN(parsed) ? 0 : parsed;
61
- }
62
- return value;
63
- };
52
+ if (typeof value === 'number') {
53
+ return value;
64
54
  }
65
- } else if (field.type === 'checkbox') {
66
- // @ts-expect-error ref is untyped
67
- result[`${ref.prefix}${field.name}`] = ({ value })=>{
68
- if (typeof value === 'boolean') {
69
- return value;
70
- }
71
- if (typeof value === 'string') {
72
- return value.toLowerCase() === 'true' || value === '1';
73
- }
74
- return Boolean(value);
75
- };
76
- } else if (field.type === 'date') {
77
- // @ts-expect-error ref is untyped
78
- result[`${ref.prefix}${field.name}`] = ({ value })=>{
79
- if (!value) {
80
- return value;
81
- }
82
- if (typeof value === 'string' && !isNaN(Date.parse(value))) {
83
- return value;
84
- }
55
+ if (typeof value === 'string') {
56
+ const parsed = parseFloat(value);
57
+ return isNaN(parsed) ? undefined : parsed;
58
+ }
59
+ return value;
60
+ });
61
+ return;
62
+ }
63
+ if (field.type === 'checkbox') {
64
+ registerBeforeImport(({ value })=>{
65
+ if (isEmptyImportValue(value)) {
66
+ return undefined;
67
+ }
68
+ if (typeof value === 'boolean') {
69
+ return value;
70
+ }
71
+ if (typeof value === 'string') {
72
+ return value.toLowerCase() === 'true' || value === '1';
73
+ }
74
+ return Boolean(value);
75
+ });
76
+ return;
77
+ }
78
+ if (field.type === 'date') {
79
+ registerBeforeImport(({ value })=>{
80
+ if (isEmptyImportValue(value)) {
81
+ return undefined;
82
+ }
83
+ if (typeof value === 'string' && !isNaN(Date.parse(value))) {
84
+ return value;
85
+ }
86
+ try {
87
+ const date = new Date(value);
88
+ return isNaN(date.getTime()) ? value : date.toISOString();
89
+ } catch {
90
+ return value;
91
+ }
92
+ });
93
+ return;
94
+ }
95
+ if (field.type === 'json' || field.type === 'richText') {
96
+ registerBeforeImport(({ value })=>{
97
+ if (isEmptyImportValue(value)) {
98
+ return undefined;
99
+ }
100
+ if (typeof value === 'object') {
101
+ return value;
102
+ }
103
+ if (typeof value === 'string') {
85
104
  try {
86
- const date = new Date(value);
87
- return isNaN(date.getTime()) ? value : date.toISOString();
105
+ return JSON.parse(value);
88
106
  } catch {
89
107
  return value;
90
108
  }
91
- };
92
- } else if (field.type === 'json' || field.type === 'richText') {
93
- // @ts-expect-error ref is untyped
94
- result[`${ref.prefix}${field.name}`] = ({ value })=>{
95
- if (typeof value === 'object') {
96
- return value;
97
- }
98
- if (typeof value === 'string') {
99
- try {
100
- return JSON.parse(value);
101
- } catch {
102
- return value;
103
- }
104
- }
105
- return value;
106
- };
107
- }
108
- };
109
- traverseFields({
110
- callback: buildCustomFunctions,
111
- fields
112
- });
113
- return result;
109
+ }
110
+ return value;
111
+ });
112
+ }
114
113
  };
114
+ const isEmptyImportValue = (value)=>value === '' || value === null || value === undefined;
115
115
 
116
116
  //# sourceMappingURL=getImportFieldFunctions.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/getImportFieldFunctions.ts"],"sourcesContent":["import { type FlattenedField, traverseFields, type TraverseFieldsCallback } from 'payload'\n\nimport type { FromCSVFunction } from '../types.js'\n\ntype Args = {\n fields: FlattenedField[]\n}\n\n/**\n * Gets custom fromCSV field functions for import.\n * These functions transform field values when unflattening CSV data for import.\n */\nexport const getImportFieldFunctions = ({ fields }: Args): Record<string, FromCSVFunction> => {\n const result: Record<string, FromCSVFunction> = {}\n\n const buildCustomFunctions: TraverseFieldsCallback = ({ field, parentRef, ref }) => {\n // @ts-expect-error ref is untyped\n ref.prefix = parentRef.prefix || ''\n if (field.type === 'group' || field.type === 'tab') {\n // @ts-expect-error ref is untyped\n const parentPrefix = parentRef?.prefix ? `${parentRef.prefix}_` : ''\n // @ts-expect-error ref is untyped\n ref.prefix = `${parentPrefix}${field.name}_`\n }\n\n if (typeof field.custom?.['plugin-import-export']?.fromCSV === 'function') {\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = field.custom['plugin-import-export']?.fromCSV\n } else if (field.type === 'relationship' || field.type === 'upload') {\n if (field.hasMany !== true) {\n if (!Array.isArray(field.relationTo)) {\n // monomorphic single relationship - simple ID to value conversion\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({ value }) => {\n // If it's already an object (from JSON import), return as-is\n if (typeof value === 'object' && value !== null) {\n return value\n }\n // Convert string/number ID to relationship value\n return value\n }\n } else {\n // Polymorphic single: handled in unflattenObject via _id/_relationTo columns\n }\n } else {\n if (!Array.isArray(field.relationTo)) {\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({ value }) => {\n if (Array.isArray(value)) {\n return value\n }\n return value\n }\n } else {\n // Polymorphic many: handled in unflattenObject\n }\n }\n } else if (field.type === 'number') {\n if (field.hasMany) {\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({ value }) => value\n } else {\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({ value }) => {\n if (typeof value === 'number') {\n return value\n }\n if (typeof value === 'string') {\n const parsed = parseFloat(value)\n return isNaN(parsed) ? 0 : parsed\n }\n return value\n }\n }\n } else if (field.type === 'checkbox') {\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({ value }) => {\n if (typeof value === 'boolean') {\n return value\n }\n if (typeof value === 'string') {\n return value.toLowerCase() === 'true' || value === '1'\n }\n return Boolean(value)\n }\n } else if (field.type === 'date') {\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({ value }) => {\n if (!value) {\n return value\n }\n if (typeof value === 'string' && !isNaN(Date.parse(value))) {\n return value\n }\n try {\n const date = new Date(value as string)\n return isNaN(date.getTime()) ? value : date.toISOString()\n } catch {\n return value\n }\n }\n } else if (field.type === 'json' || field.type === 'richText') {\n // @ts-expect-error ref is untyped\n result[`${ref.prefix}${field.name}`] = ({ value }) => {\n if (typeof value === 'object') {\n return value\n }\n if (typeof value === 'string') {\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n }\n return value\n }\n }\n }\n\n traverseFields({ callback: buildCustomFunctions, fields })\n\n return result\n}\n"],"names":["traverseFields","getImportFieldFunctions","fields","result","buildCustomFunctions","field","parentRef","ref","prefix","type","parentPrefix","name","custom","fromCSV","hasMany","Array","isArray","relationTo","value","parsed","parseFloat","isNaN","toLowerCase","Boolean","Date","parse","date","getTime","toISOString","JSON","callback"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utilities/getImportFieldFunctions.ts"],"sourcesContent":["import type { FlattenedField } from 'payload'\n\nimport type { FieldBeforeImportHook, ImportFieldHookEntry } from '../types.js'\n\nimport { registerFieldHooks } from './flattenedFields.js'\n\ntype Args = {\n fields: FlattenedField[]\n}\n\n/**\n * Builds a map from logical field path (e.g. `content_textBlock_body`) to\n * the import hook entry. Paths include block slugs but never array indices.\n */\nexport const getImportFieldFunctions = ({ fields }: Args): Record<string, ImportFieldHookEntry> => {\n const result: Record<string, ImportFieldHookEntry> = {}\n registerFieldHooks(fields, '', result, registerImportHandler)\n return result\n}\n\nconst registerImportHandler = (\n field: FlattenedField,\n fullKey: string,\n result: Record<string, ImportFieldHookEntry>,\n): void => {\n const beforeImport = field.custom?.['plugin-import-export']?.hooks?.beforeImport\n\n const fromCSV = field.custom?.['plugin-import-export']?.fromCSV\n\n if (typeof beforeImport === 'function') {\n result[fullKey] = { type: 'beforeImport', fn: beforeImport }\n return\n }\n\n if (typeof fromCSV === 'function') {\n result[fullKey] = { type: 'fromCSV', fn: fromCSV }\n return\n }\n\n const registerBeforeImport = (fn: FieldBeforeImportHook) => {\n result[fullKey] = { type: 'beforeImport', fn }\n }\n\n if (field.type === 'relationship' || field.type === 'upload') {\n if (field.hasMany !== true) {\n if (!Array.isArray(field.relationTo)) {\n registerBeforeImport(({ value }) => value)\n }\n } else if (!Array.isArray(field.relationTo)) {\n registerBeforeImport(({ value }) => value)\n }\n return\n }\n\n if (field.type === 'number') {\n if (field.hasMany) {\n registerBeforeImport(({ value }) => value)\n return\n }\n registerBeforeImport(({ value }) => {\n if (isEmptyImportValue(value)) {\n return undefined\n }\n if (typeof value === 'number') {\n return value\n }\n if (typeof value === 'string') {\n const parsed = parseFloat(value)\n return isNaN(parsed) ? undefined : parsed\n }\n return value\n })\n return\n }\n\n if (field.type === 'checkbox') {\n registerBeforeImport(({ value }) => {\n if (isEmptyImportValue(value)) {\n return undefined\n }\n if (typeof value === 'boolean') {\n return value\n }\n if (typeof value === 'string') {\n return value.toLowerCase() === 'true' || value === '1'\n }\n return Boolean(value)\n })\n return\n }\n\n if (field.type === 'date') {\n registerBeforeImport(({ value }) => {\n if (isEmptyImportValue(value)) {\n return undefined\n }\n if (typeof value === 'string' && !isNaN(Date.parse(value))) {\n return value\n }\n try {\n const date = new Date(value as string)\n return isNaN(date.getTime()) ? value : date.toISOString()\n } catch {\n return value\n }\n })\n return\n }\n\n if (field.type === 'json' || field.type === 'richText') {\n registerBeforeImport(({ value }) => {\n if (isEmptyImportValue(value)) {\n return undefined\n }\n if (typeof value === 'object') {\n return value\n }\n if (typeof value === 'string') {\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n }\n return value\n })\n }\n}\n\nconst isEmptyImportValue = (value: unknown): boolean =>\n value === '' || value === null || value === undefined\n"],"names":["registerFieldHooks","getImportFieldFunctions","fields","result","registerImportHandler","field","fullKey","beforeImport","custom","hooks","fromCSV","type","fn","registerBeforeImport","hasMany","Array","isArray","relationTo","value","isEmptyImportValue","undefined","parsed","parseFloat","isNaN","toLowerCase","Boolean","Date","parse","date","getTime","toISOString","JSON"],"mappings":"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"}