@payloadcms/plugin-import-export 3.91.0-internal.c1569dc → 4.0.0-beta.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 (180) hide show
  1. package/README.md +2 -2
  2. package/dist/components/CollectionField/index.d.ts +3 -2
  3. package/dist/components/CollectionField/index.d.ts.map +1 -1
  4. package/dist/components/CollectionField/index.js.map +1 -1
  5. package/dist/components/ExportListMenuItem/index.d.ts.map +1 -1
  6. package/dist/components/ExportListMenuItem/index.js +14 -12
  7. package/dist/components/ExportListMenuItem/index.js.map +1 -1
  8. package/dist/components/ExportPreview/index.css +52 -0
  9. package/dist/components/ExportPreview/index.d.ts +1 -1
  10. package/dist/components/ExportPreview/index.d.ts.map +1 -1
  11. package/dist/components/ExportPreview/index.js +12 -2
  12. package/dist/components/ExportPreview/index.js.map +1 -1
  13. package/dist/components/FieldsToExport/index.d.ts +3 -2
  14. package/dist/components/FieldsToExport/index.d.ts.map +1 -1
  15. package/dist/components/FieldsToExport/index.js +18 -15
  16. package/dist/components/FieldsToExport/index.js.map +1 -1
  17. package/dist/components/FieldsToExport/reduceFields.d.ts +6 -0
  18. package/dist/components/FieldsToExport/reduceFields.d.ts.map +1 -1
  19. package/dist/components/FieldsToExport/reduceFields.js +4 -0
  20. package/dist/components/FieldsToExport/reduceFields.js.map +1 -1
  21. package/dist/components/FormatField/index.d.ts +3 -2
  22. package/dist/components/FormatField/index.d.ts.map +1 -1
  23. package/dist/components/FormatField/index.js +6 -3
  24. package/dist/components/FormatField/index.js.map +1 -1
  25. package/dist/components/ImportListMenuItem/index.d.ts.map +1 -1
  26. package/dist/components/ImportListMenuItem/index.js +14 -12
  27. package/dist/components/ImportListMenuItem/index.js.map +1 -1
  28. package/dist/components/ImportPreview/index.css +45 -0
  29. package/dist/components/ImportPreview/index.d.ts +1 -1
  30. package/dist/components/ImportPreview/index.d.ts.map +1 -1
  31. package/dist/components/ImportPreview/index.js +44 -11
  32. package/dist/components/ImportPreview/index.js.map +1 -1
  33. package/dist/components/LimitField/index.d.ts +3 -2
  34. package/dist/components/LimitField/index.d.ts.map +1 -1
  35. package/dist/components/LimitField/index.js.map +1 -1
  36. package/dist/components/LocaleField/index.d.ts +3 -2
  37. package/dist/components/LocaleField/index.d.ts.map +1 -1
  38. package/dist/components/LocaleField/index.js.map +1 -1
  39. package/dist/components/Page/index.d.ts +4 -3
  40. package/dist/components/Page/index.d.ts.map +1 -1
  41. package/dist/components/Page/index.js +1 -1
  42. package/dist/components/Page/index.js.map +1 -1
  43. package/dist/components/RelationshipCell/getRelationshipGroupKey.d.ts +7 -0
  44. package/dist/components/RelationshipCell/getRelationshipGroupKey.d.ts.map +1 -0
  45. package/dist/components/RelationshipCell/getRelationshipGroupKey.js +3 -0
  46. package/dist/components/RelationshipCell/getRelationshipGroupKey.js.map +1 -0
  47. package/dist/components/RelationshipCell/getRelationshipGroups.d.ts +43 -0
  48. package/dist/components/RelationshipCell/getRelationshipGroups.d.ts.map +1 -0
  49. package/dist/components/RelationshipCell/getRelationshipGroups.js +109 -0
  50. package/dist/components/RelationshipCell/getRelationshipGroups.js.map +1 -0
  51. package/dist/components/RelationshipCell/index.css +30 -0
  52. package/dist/components/RelationshipCell/index.d.ts +15 -0
  53. package/dist/components/RelationshipCell/index.d.ts.map +1 -0
  54. package/dist/components/RelationshipCell/index.js +57 -0
  55. package/dist/components/RelationshipCell/index.js.map +1 -0
  56. package/dist/components/SortBy/index.css +9 -0
  57. package/dist/components/SortBy/index.d.ts +4 -3
  58. package/dist/components/SortBy/index.d.ts.map +1 -1
  59. package/dist/components/SortBy/index.js +1 -2
  60. package/dist/components/SortBy/index.js.map +1 -1
  61. package/dist/components/SortOrder/index.css +9 -0
  62. package/dist/components/SortOrder/index.d.ts +4 -3
  63. package/dist/components/SortOrder/index.d.ts.map +1 -1
  64. package/dist/components/SortOrder/index.js +1 -2
  65. package/dist/components/SortOrder/index.js.map +1 -1
  66. package/dist/export/batchProcessor.d.ts +4 -3
  67. package/dist/export/batchProcessor.d.ts.map +1 -1
  68. package/dist/export/batchProcessor.js +6 -2
  69. package/dist/export/batchProcessor.js.map +1 -1
  70. package/dist/export/createExport.d.ts +4 -2
  71. package/dist/export/createExport.d.ts.map +1 -1
  72. package/dist/export/createExport.js +7 -2
  73. package/dist/export/createExport.js.map +1 -1
  74. package/dist/export/getCreateExportCollectionTask.d.ts.map +1 -1
  75. package/dist/export/getCreateExportCollectionTask.js +11 -0
  76. package/dist/export/getCreateExportCollectionTask.js.map +1 -1
  77. package/dist/export/getExportCollection.d.ts.map +1 -1
  78. package/dist/export/getExportCollection.js +9 -4
  79. package/dist/export/getExportCollection.js.map +1 -1
  80. package/dist/export/handleDownload.d.ts.map +1 -1
  81. package/dist/export/handleDownload.js +7 -3
  82. package/dist/export/handleDownload.js.map +1 -1
  83. package/dist/export/handlePreview.d.ts.map +1 -1
  84. package/dist/export/handlePreview.js +24 -5
  85. package/dist/export/handlePreview.js.map +1 -1
  86. package/dist/exports/types.d.ts +1 -1
  87. package/dist/exports/types.d.ts.map +1 -1
  88. package/dist/exports/types.js.map +1 -1
  89. package/dist/import/batchProcessor.d.ts +4 -3
  90. package/dist/import/batchProcessor.d.ts.map +1 -1
  91. package/dist/import/batchProcessor.js +15 -8
  92. package/dist/import/batchProcessor.js.map +1 -1
  93. package/dist/import/createImport.d.ts +3 -2
  94. package/dist/import/createImport.d.ts.map +1 -1
  95. package/dist/import/createImport.js +9 -2
  96. package/dist/import/createImport.js.map +1 -1
  97. package/dist/import/getCreateImportCollectionTask.d.ts.map +1 -1
  98. package/dist/import/getCreateImportCollectionTask.js +5 -2
  99. package/dist/import/getCreateImportCollectionTask.js.map +1 -1
  100. package/dist/import/getImportCollection.d.ts.map +1 -1
  101. package/dist/import/getImportCollection.js +6 -4
  102. package/dist/import/getImportCollection.js.map +1 -1
  103. package/dist/import/handlePreview.d.ts.map +1 -1
  104. package/dist/import/handlePreview.js +5 -1
  105. package/dist/import/handlePreview.js.map +1 -1
  106. package/dist/index.d.ts +2 -13
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +19 -8
  109. package/dist/index.js.map +1 -1
  110. package/dist/translations/languages/en.d.ts.map +1 -1
  111. package/dist/types.d.ts +17 -33
  112. package/dist/types.d.ts.map +1 -1
  113. package/dist/types.js.map +1 -1
  114. package/dist/utilities/applyFieldHooks.d.ts +1 -2
  115. package/dist/utilities/applyFieldHooks.d.ts.map +1 -1
  116. package/dist/utilities/applyFieldHooks.js +2 -3
  117. package/dist/utilities/applyFieldHooks.js.map +1 -1
  118. package/dist/utilities/flattenObject.d.ts.map +1 -1
  119. package/dist/utilities/flattenObject.js +3 -13
  120. package/dist/utilities/flattenObject.js.map +1 -1
  121. package/dist/utilities/flattenedFields.d.ts.map +1 -1
  122. package/dist/utilities/flattenedFields.js +3 -0
  123. package/dist/utilities/flattenedFields.js.map +1 -1
  124. package/dist/utilities/getExportFieldFunctions.js +64 -35
  125. package/dist/utilities/getExportFieldFunctions.js.map +1 -1
  126. package/dist/utilities/getFileFromDoc.js +3 -3
  127. package/dist/utilities/getFileFromDoc.js.map +1 -1
  128. package/dist/utilities/getImportFieldFunctions.js +0 -8
  129. package/dist/utilities/getImportFieldFunctions.js.map +1 -1
  130. package/dist/utilities/getSchemaColumns.d.ts +1 -1
  131. package/dist/utilities/getSchemaColumns.js +2 -2
  132. package/dist/utilities/getSchemaColumns.js.map +1 -1
  133. package/dist/utilities/getSubmittedFormValues.d.ts +12 -0
  134. package/dist/utilities/getSubmittedFormValues.d.ts.map +1 -0
  135. package/dist/utilities/getSubmittedFormValues.js +24 -0
  136. package/dist/utilities/getSubmittedFormValues.js.map +1 -0
  137. package/dist/utilities/sortHelpers.d.ts +1 -1
  138. package/dist/utilities/unflattenObject.d.ts.map +1 -1
  139. package/dist/utilities/unflattenObject.js +8 -16
  140. package/dist/utilities/unflattenObject.js.map +1 -1
  141. package/license.md +1 -1
  142. package/package.json +9 -9
  143. package/dist/components/ExportPreview/index.scss +0 -48
  144. package/dist/components/FieldsToExport/index.scss +0 -0
  145. package/dist/components/FieldsToExport/reduceFields.spec.js +0 -239
  146. package/dist/components/FieldsToExport/reduceFields.spec.js.map +0 -1
  147. package/dist/components/ImportPreview/index.scss +0 -41
  148. package/dist/components/SortBy/index.scss +0 -3
  149. package/dist/components/SortOrder/index.scss +0 -3
  150. package/dist/utilities/applyFieldHooks.spec.js +0 -205
  151. package/dist/utilities/applyFieldHooks.spec.js.map +0 -1
  152. package/dist/utilities/buildDisabledFieldRegex.spec.js +0 -64
  153. package/dist/utilities/buildDisabledFieldRegex.spec.js.map +0 -1
  154. package/dist/utilities/fieldToRegex.spec.js +0 -151
  155. package/dist/utilities/fieldToRegex.spec.js.map +0 -1
  156. package/dist/utilities/filterToSelectedFields.spec.js +0 -204
  157. package/dist/utilities/filterToSelectedFields.spec.js.map +0 -1
  158. package/dist/utilities/flattenObject.spec.js +0 -158
  159. package/dist/utilities/flattenObject.spec.js.map +0 -1
  160. package/dist/utilities/getExportFieldFunctions.spec.js +0 -50
  161. package/dist/utilities/getExportFieldFunctions.spec.js.map +0 -1
  162. package/dist/utilities/getImportFieldFunctions.spec.js +0 -167
  163. package/dist/utilities/getImportFieldFunctions.spec.js.map +0 -1
  164. package/dist/utilities/getSchemaColumns.spec.js +0 -157
  165. package/dist/utilities/getSchemaColumns.spec.js.map +0 -1
  166. package/dist/utilities/getSelect.spec.js +0 -57
  167. package/dist/utilities/getSelect.spec.js.map +0 -1
  168. package/dist/utilities/legacyHookDispatch.spec.js +0 -227
  169. package/dist/utilities/legacyHookDispatch.spec.js.map +0 -1
  170. package/dist/utilities/parseCSV.spec.js +0 -195
  171. package/dist/utilities/parseCSV.spec.js.map +0 -1
  172. package/dist/utilities/processRichTextField.spec.js +0 -308
  173. package/dist/utilities/processRichTextField.spec.js.map +0 -1
  174. package/dist/utilities/setNestedValue.spec.js +0 -214
  175. package/dist/utilities/setNestedValue.spec.js.map +0 -1
  176. package/dist/utilities/siblingDoc.spec.js +0 -278
  177. package/dist/utilities/siblingDoc.spec.js.map +0 -1
  178. package/dist/utilities/unflattenObject.spec.js +0 -819
  179. package/dist/utilities/unflattenObject.spec.js.map +0 -1
  180. /package/dist/components/Page/{index.scss → index.css} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/utilities/legacyHookDispatch.spec.ts"],"sourcesContent":["import { FlattenedField, PayloadRequest } from 'payload'\n\nimport type { FromCSVFunction, ToCSVFunction } from '../types.js'\n\nimport { flattenObject } from './flattenObject.js'\nimport { getExportFieldFunctions } from './getExportFieldFunctions.js'\nimport { getImportFieldFunctions } from './getImportFieldFunctions.js'\nimport { unflattenObject } from './unflattenObject.js'\n\nimport { describe, expect, it, vi } from 'vitest'\n\nconst mockReq = {\n payload: {\n logger: {\n error: vi.fn(),\n },\n },\n} as unknown as PayloadRequest\n\ndescribe('legacy toCSV / fromCSV argument shape', () => {\n describe('toCSV receives { columnName, data, doc, row, siblingDoc, value }', () => {\n it('should pass row as flat row accumulator, doc as top-level doc, and siblingDoc as source doc', () => {\n const received: Parameters<ToCSVFunction>[0][] = []\n\n const fields: FlattenedField[] = [\n {\n name: 'legacy',\n type: 'text',\n custom: {\n 'plugin-import-export': {\n toCSV: ((args) => {\n received.push(args)\n args.row[`${args.columnName}_extra`] = 'added'\n return String(args.value) + '_transformed'\n }) satisfies ToCSVFunction,\n },\n },\n } as FlattenedField,\n ]\n\n const exportFieldHooks = getExportFieldFunctions({ fields })\n\n const doc = { legacy: 'hello', title: 'Top' }\n const result = flattenObject({\n data: doc,\n exportFieldHooks,\n format: 'csv',\n req: mockReq,\n })\n\n expect(received).toHaveLength(1)\n const args = received[0]!\n expect(args.columnName).toBe('legacy')\n expect(args.value).toBe('hello')\n // doc should be the top-level document\n expect(args.doc).toBe(doc)\n // siblingDoc should be the source doc at the current nesting level (top-level == doc)\n expect(args.siblingDoc).toBe(doc)\n // row should be the flat row accumulator (a different object from doc)\n expect(args.row).not.toBe(doc)\n // data is kept as alias for row to avoid breaking legacy usage\n expect(args.data).toBe(args.row)\n\n expect(result.legacy).toBe('hello_transformed')\n expect(result.legacy_extra).toBe('added')\n })\n\n it('should not pass legacy args to hooks.beforeExport', () => {\n const received: Array<Record<string, unknown>> = []\n\n const fields: FlattenedField[] = [\n {\n name: 'modern',\n type: 'text',\n custom: {\n 'plugin-import-export': {\n hooks: {\n beforeExport: (args) => {\n received.push(args as unknown as Record<string, unknown>)\n return String(args.value) + '_modern'\n },\n },\n },\n },\n } as FlattenedField,\n ]\n\n const exportFieldHooks = getExportFieldFunctions({ fields })\n\n const doc = { modern: 'v', title: 'Top' }\n flattenObject({ data: doc, exportFieldHooks, format: 'csv', req: mockReq })\n\n expect(received).toHaveLength(1)\n const args = received[0]!\n // Modern signature: data === top-level doc\n expect(args.data).toBe(doc)\n // Modern signature: siblingData === flat row accumulator (not source doc)\n expect(args.siblingData).not.toBe(doc)\n expect(args.format).toBe('csv')\n // Legacy-only args should not be present\n expect(args.doc).toBeUndefined()\n expect(args.row).toBeUndefined()\n // `siblingDoc` is part of the modern signature too (read-only source view)\n expect(args.siblingDoc).toBeDefined()\n })\n\n it('should prefer hooks.beforeExport when both are defined on a field', () => {\n const legacyCalls: string[] = []\n const modernCalls: string[] = []\n\n const fields: FlattenedField[] = [\n {\n name: 'both',\n type: 'text',\n custom: {\n 'plugin-import-export': {\n hooks: {\n beforeExport: ({ value }) => {\n modernCalls.push(String(value))\n return `${value}_modern`\n },\n },\n toCSV: ({ value }: { value: unknown }) => {\n legacyCalls.push(String(value))\n return `${value}_legacy`\n },\n },\n },\n } as FlattenedField,\n ]\n\n const exportFieldHooks = getExportFieldFunctions({ fields })\n const result = flattenObject({\n data: { both: 'x' },\n exportFieldHooks,\n format: 'csv',\n req: mockReq,\n })\n\n expect(modernCalls).toEqual(['x'])\n expect(legacyCalls).toEqual([])\n expect(result.both).toBe('x_modern')\n })\n })\n\n describe('fromCSV receives { columnName, data, value } with data as full flat row', () => {\n it('should pass the full flat row as data', () => {\n const received: Parameters<FromCSVFunction>[0][] = []\n\n const fields: FlattenedField[] = [\n {\n name: 'legacy',\n type: 'text',\n custom: {\n 'plugin-import-export': {\n fromCSV: ((args) => {\n received.push(args)\n return String(args.value) + '_imported'\n }) satisfies FromCSVFunction,\n },\n },\n } as FlattenedField,\n ]\n\n const importFieldHooks = getImportFieldFunctions({ fields })\n\n const flatRow = { legacy: 'incoming', title: 'Top' }\n const result = unflattenObject({\n data: flatRow,\n fields,\n format: 'csv',\n importFieldHooks,\n req: mockReq,\n })\n\n expect(received).toHaveLength(1)\n expect(received[0]!.columnName).toBe('legacy')\n expect(received[0]!.value).toBe('incoming')\n // data should be the full flat row\n expect(received[0]!.data).toBe(flatRow)\n\n expect(result.legacy).toBe('incoming_imported')\n })\n\n it('should prefer hooks.beforeImport when both are defined on a field', () => {\n const legacyCalls: string[] = []\n const modernCalls: string[] = []\n\n const fields: FlattenedField[] = [\n {\n name: 'both',\n type: 'text',\n custom: {\n 'plugin-import-export': {\n fromCSV: ({ value }: { value: unknown }) => {\n legacyCalls.push(String(value))\n return `${value}_legacy`\n },\n hooks: {\n beforeImport: ({ value }) => {\n modernCalls.push(String(value))\n return `${value}_modern`\n },\n },\n },\n },\n } as FlattenedField,\n ]\n\n const importFieldHooks = getImportFieldFunctions({ fields })\n const result = unflattenObject({\n data: { both: 'x' },\n fields,\n format: 'csv',\n importFieldHooks,\n req: mockReq,\n })\n\n expect(modernCalls).toEqual(['x'])\n expect(legacyCalls).toEqual([])\n expect(result.both).toBe('x_modern')\n })\n })\n})\n"],"names":["flattenObject","getExportFieldFunctions","getImportFieldFunctions","unflattenObject","describe","expect","it","vi","mockReq","payload","logger","error","fn","received","fields","name","type","custom","toCSV","args","push","row","columnName","String","value","exportFieldHooks","doc","legacy","title","result","data","format","req","toHaveLength","toBe","siblingDoc","not","legacy_extra","hooks","beforeExport","modern","siblingData","toBeUndefined","toBeDefined","legacyCalls","modernCalls","both","toEqual","fromCSV","importFieldHooks","flatRow","beforeImport"],"mappings":"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"}
@@ -1,195 +0,0 @@
1
- import { parseCSV } from './parseCSV.js';
2
- import { describe, it, expect, vi } from 'vitest';
3
- describe('parseCSV', ()=>{
4
- const mockReq = {
5
- payload: {
6
- logger: {
7
- error: vi.fn()
8
- }
9
- }
10
- };
11
- describe('cast function behavior', ()=>{
12
- it('should preserve comma-separated values as strings', async ()=>{
13
- const csvData = Buffer.from('numbers,ids\n"1,2,3,5,8","id1,id2,id3"');
14
- const result = await parseCSV({
15
- data: csvData,
16
- req: mockReq
17
- });
18
- expect(result).toEqual([
19
- {
20
- numbers: '1,2,3,5,8',
21
- ids: 'id1,id2,id3'
22
- }
23
- ]);
24
- });
25
- it('should convert single numbers to numbers', async ()=>{
26
- const csvData = Buffer.from('single,decimal\n"42","3.14"');
27
- const result = await parseCSV({
28
- data: csvData,
29
- req: mockReq
30
- });
31
- expect(result).toEqual([
32
- {
33
- single: 42,
34
- decimal: 3.14
35
- }
36
- ]);
37
- });
38
- it('should handle booleans correctly', async ()=>{
39
- const csvData = Buffer.from('bool1,bool2,notBool\n"true","false","True"');
40
- const result = await parseCSV({
41
- data: csvData,
42
- req: mockReq
43
- });
44
- expect(result).toEqual([
45
- {
46
- bool1: true,
47
- bool2: false,
48
- notBool: 'True'
49
- }
50
- ]);
51
- });
52
- it('should convert empty strings to undefined', async ()=>{
53
- const csvData = Buffer.from('field1,field2\n"","value"');
54
- const result = await parseCSV({
55
- data: csvData,
56
- req: mockReq
57
- });
58
- expect(result).toEqual([
59
- {
60
- // field1 is undefined (not present) - empty cells don't update fields
61
- field2: 'value'
62
- }
63
- ]);
64
- });
65
- it('should handle null strings', async ()=>{
66
- const csvData = Buffer.from('field1,field2,field3\n"null","NULL","Null"');
67
- const result = await parseCSV({
68
- data: csvData,
69
- req: mockReq
70
- });
71
- expect(result).toEqual([
72
- {
73
- field1: null,
74
- field2: null,
75
- field3: 'Null'
76
- }
77
- ]);
78
- });
79
- it('should preserve spaces in comma-separated values', async ()=>{
80
- const csvData = Buffer.from('numbers\n" 10 , 20 , 30 "');
81
- const result = await parseCSV({
82
- data: csvData,
83
- req: mockReq
84
- });
85
- expect(result).toEqual([
86
- {
87
- numbers: ' 10 , 20 , 30 '
88
- }
89
- ]);
90
- });
91
- it('should handle mixed comma-separated values with empty entries', async ()=>{
92
- const csvData = Buffer.from('mixed\n"1,,3,,5"');
93
- const result = await parseCSV({
94
- data: csvData,
95
- req: mockReq
96
- });
97
- expect(result).toEqual([
98
- {
99
- mixed: '1,,3,,5'
100
- }
101
- ]);
102
- });
103
- it('should handle MongoDB ObjectIds as strings', async ()=>{
104
- const csvData = Buffer.from('id\n"507f1f77bcf86cd799439011"');
105
- const result = await parseCSV({
106
- data: csvData,
107
- req: mockReq
108
- });
109
- expect(result).toEqual([
110
- {
111
- id: '507f1f77bcf86cd799439011'
112
- }
113
- ]);
114
- });
115
- it('should handle multiple rows with various data types', async ()=>{
116
- const csvData = Buffer.from('title,count,tags,active\n' + '"Item 1","5","tag1,tag2,tag3","true"\n' + '"Item 2","","","false"\n' + '"Item 3","10","single",""\n');
117
- const result = await parseCSV({
118
- data: csvData,
119
- req: mockReq
120
- });
121
- expect(result).toEqual([
122
- {
123
- title: 'Item 1',
124
- count: 5,
125
- tags: 'tag1,tag2,tag3',
126
- active: true
127
- },
128
- {
129
- title: 'Item 2',
130
- // count is undefined (empty cell - field not updated)
131
- // tags is undefined (empty cell - field not updated)
132
- active: false
133
- },
134
- {
135
- title: 'Item 3',
136
- count: 10,
137
- tags: 'single'
138
- }
139
- ]);
140
- });
141
- it('should skip empty lines', async ()=>{
142
- const csvData = Buffer.from('field\n"value1"\n\n"value2"\n\n');
143
- const result = await parseCSV({
144
- data: csvData,
145
- req: mockReq
146
- });
147
- expect(result).toEqual([
148
- {
149
- field: 'value1'
150
- },
151
- {
152
- field: 'value2'
153
- }
154
- ]);
155
- });
156
- it('should strip UTF-8 BOM from column names', async ()=>{
157
- // UTF-8 BOM is 0xEF 0xBB 0xBF
158
- const bomBytes = Buffer.from([
159
- 0xef,
160
- 0xbb,
161
- 0xbf
162
- ]);
163
- const csvContent = Buffer.from('id,title,createdAt\ntesssst,test,2026-02-11T21:03:39.020Z');
164
- const csvWithBOM = Buffer.concat([
165
- bomBytes,
166
- csvContent
167
- ]);
168
- const result = await parseCSV({
169
- data: csvWithBOM,
170
- req: mockReq
171
- });
172
- expect(result).toEqual([
173
- {
174
- id: 'tesssst',
175
- title: 'test',
176
- createdAt: '2026-02-11T21:03:39.020Z'
177
- }
178
- ]);
179
- // Verify the column name is exactly "id" without BOM character
180
- expect(Object.keys(result[0])[0]).toBe('id');
181
- });
182
- });
183
- describe('error handling', ()=>{
184
- it('should handle parsing errors', async ()=>{
185
- const invalidCsv = Buffer.from('field1,field2\n"value1');
186
- await expect(parseCSV({
187
- data: invalidCsv,
188
- req: mockReq
189
- })).rejects.toThrow();
190
- expect(mockReq.payload.logger.error).toHaveBeenCalled();
191
- });
192
- });
193
- });
194
-
195
- //# sourceMappingURL=parseCSV.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/utilities/parseCSV.spec.ts"],"sourcesContent":["import { PayloadRequest } from 'payload'\n\nimport { parseCSV } from './parseCSV.js'\nimport { describe, it, expect, vi } from 'vitest'\n\ndescribe('parseCSV', () => {\n const mockReq = {\n payload: {\n logger: {\n error: vi.fn(),\n },\n },\n } as unknown as PayloadRequest\n\n describe('cast function behavior', () => {\n it('should preserve comma-separated values as strings', async () => {\n const csvData = Buffer.from('numbers,ids\\n\"1,2,3,5,8\",\"id1,id2,id3\"')\n const result = await parseCSV({ data: csvData, req: mockReq })\n\n expect(result).toEqual([\n {\n numbers: '1,2,3,5,8',\n ids: 'id1,id2,id3',\n },\n ])\n })\n\n it('should convert single numbers to numbers', async () => {\n const csvData = Buffer.from('single,decimal\\n\"42\",\"3.14\"')\n const result = await parseCSV({ data: csvData, req: mockReq })\n\n expect(result).toEqual([\n {\n single: 42,\n decimal: 3.14,\n },\n ])\n })\n\n it('should handle booleans correctly', async () => {\n const csvData = Buffer.from('bool1,bool2,notBool\\n\"true\",\"false\",\"True\"')\n const result = await parseCSV({ data: csvData, req: mockReq })\n\n expect(result).toEqual([\n {\n bool1: true,\n bool2: false,\n notBool: 'True', // Case-sensitive\n },\n ])\n })\n\n it('should convert empty strings to undefined', async () => {\n const csvData = Buffer.from('field1,field2\\n\"\",\"value\"')\n const result = await parseCSV({ data: csvData, req: mockReq })\n\n expect(result).toEqual([\n {\n // field1 is undefined (not present) - empty cells don't update fields\n field2: 'value',\n },\n ])\n })\n\n it('should handle null strings', async () => {\n const csvData = Buffer.from('field1,field2,field3\\n\"null\",\"NULL\",\"Null\"')\n const result = await parseCSV({ data: csvData, req: mockReq })\n\n expect(result).toEqual([\n {\n field1: null,\n field2: null,\n field3: 'Null', // Case-sensitive for mixed case\n },\n ])\n })\n\n it('should preserve spaces in comma-separated values', async () => {\n const csvData = Buffer.from('numbers\\n\" 10 , 20 , 30 \"')\n const result = await parseCSV({ data: csvData, req: mockReq })\n\n expect(result).toEqual([\n {\n numbers: ' 10 , 20 , 30 ', // CSV parser trims outer quotes but preserves the content\n },\n ])\n })\n\n it('should handle mixed comma-separated values with empty entries', async () => {\n const csvData = Buffer.from('mixed\\n\"1,,3,,5\"')\n const result = await parseCSV({ data: csvData, req: mockReq })\n\n expect(result).toEqual([\n {\n mixed: '1,,3,,5',\n },\n ])\n })\n\n it('should handle MongoDB ObjectIds as strings', async () => {\n const csvData = Buffer.from('id\\n\"507f1f77bcf86cd799439011\"')\n const result = await parseCSV({ data: csvData, req: mockReq })\n\n expect(result).toEqual([\n {\n id: '507f1f77bcf86cd799439011',\n },\n ])\n })\n\n it('should handle multiple rows with various data types', async () => {\n const csvData = Buffer.from(\n 'title,count,tags,active\\n' +\n '\"Item 1\",\"5\",\"tag1,tag2,tag3\",\"true\"\\n' +\n '\"Item 2\",\"\",\"\",\"false\"\\n' +\n '\"Item 3\",\"10\",\"single\",\"\"\\n',\n )\n const result = await parseCSV({ data: csvData, req: mockReq })\n\n expect(result).toEqual([\n {\n title: 'Item 1',\n count: 5,\n tags: 'tag1,tag2,tag3',\n active: true,\n },\n {\n title: 'Item 2',\n // count is undefined (empty cell - field not updated)\n // tags is undefined (empty cell - field not updated)\n active: false,\n },\n {\n title: 'Item 3',\n count: 10,\n tags: 'single',\n // active is undefined (empty cell - field not updated)\n },\n ])\n })\n\n it('should skip empty lines', async () => {\n const csvData = Buffer.from('field\\n\"value1\"\\n\\n\"value2\"\\n\\n')\n const result = await parseCSV({ data: csvData, req: mockReq })\n\n expect(result).toEqual([{ field: 'value1' }, { field: 'value2' }])\n })\n\n it('should strip UTF-8 BOM from column names', async () => {\n // UTF-8 BOM is 0xEF 0xBB 0xBF\n const bomBytes = Buffer.from([0xef, 0xbb, 0xbf])\n const csvContent = Buffer.from('id,title,createdAt\\ntesssst,test,2026-02-11T21:03:39.020Z')\n const csvWithBOM = Buffer.concat([bomBytes, csvContent])\n\n const result = await parseCSV({ data: csvWithBOM, req: mockReq })\n\n expect(result).toEqual([\n {\n id: 'tesssst',\n title: 'test',\n createdAt: '2026-02-11T21:03:39.020Z',\n },\n ])\n\n // Verify the column name is exactly \"id\" without BOM character\n expect(Object.keys(result[0])[0]).toBe('id')\n })\n })\n\n describe('error handling', () => {\n it('should handle parsing errors', async () => {\n const invalidCsv = Buffer.from('field1,field2\\n\"value1')\n\n await expect(parseCSV({ data: invalidCsv, req: mockReq })).rejects.toThrow()\n expect(mockReq.payload.logger.error).toHaveBeenCalled()\n })\n })\n})\n"],"names":["parseCSV","describe","it","expect","vi","mockReq","payload","logger","error","fn","csvData","Buffer","from","result","data","req","toEqual","numbers","ids","single","decimal","bool1","bool2","notBool","field2","field1","field3","mixed","id","title","count","tags","active","field","bomBytes","csvContent","csvWithBOM","concat","createdAt","Object","keys","toBe","invalidCsv","rejects","toThrow","toHaveBeenCalled"],"mappings":"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"}
@@ -1,308 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { processRichTextField } from './processRichTextField.js';
3
- // Minimal helpers to keep assertions readable
4
- const asRecord = (v)=>v;
5
- const asArray = (v)=>v;
6
- // ─── Fixtures ────────────────────────────────────────────────────────────────
7
- const textNode = (overrides = {})=>({
8
- detail: 0,
9
- format: 0,
10
- mode: 'normal',
11
- text: 'Hello',
12
- type: 'text',
13
- version: 1,
14
- ...overrides
15
- });
16
- const paragraphNode = (children = [
17
- textNode()
18
- ])=>({
19
- children,
20
- direction: 'ltr',
21
- format: '',
22
- indent: 0,
23
- type: 'paragraph',
24
- version: 1
25
- });
26
- const lexicalDoc = (children = [
27
- paragraphNode()
28
- ])=>({
29
- children,
30
- direction: 'ltr',
31
- format: '',
32
- indent: 0,
33
- type: 'root',
34
- version: 1
35
- });
36
- // ─── Primitive pass-through ──────────────────────────────────────────────────
37
- describe('processRichTextField — primitive pass-through', ()=>{
38
- it('should return null unchanged', ()=>{
39
- expect(processRichTextField(null)).toBeNull();
40
- });
41
- it('should return undefined unchanged', ()=>{
42
- expect(processRichTextField(undefined)).toBeUndefined();
43
- });
44
- it('should return a number unchanged', ()=>{
45
- expect(processRichTextField(42)).toBe(42);
46
- });
47
- it('should return false unchanged', ()=>{
48
- expect(processRichTextField(false)).toBe(false);
49
- });
50
- });
51
- // ─── String input (the recovered-from-missed-hook path) ─────────────────────
52
- describe('processRichTextField — JSON string input', ()=>{
53
- it('should parse a valid JSON string into an object', ()=>{
54
- const doc = lexicalDoc();
55
- expect(processRichTextField(JSON.stringify(doc))).toEqual(doc);
56
- });
57
- it('should return an unparseable string unchanged', ()=>{
58
- expect(processRichTextField('not json')).toBe('not json');
59
- });
60
- it('should return an empty string unchanged', ()=>{
61
- expect(processRichTextField('')).toBe('');
62
- });
63
- it('should parse a string and still convert numeric string properties', ()=>{
64
- const node = {
65
- type: 'text',
66
- detail: '0',
67
- format: '3',
68
- indent: '0',
69
- version: '1',
70
- text: 'hi'
71
- };
72
- const result = asRecord(processRichTextField(JSON.stringify(node)));
73
- expect(result.detail).toBe(0);
74
- expect(result.format).toBe(3);
75
- expect(result.indent).toBe(0);
76
- expect(result.version).toBe(1);
77
- });
78
- });
79
- // ─── Numeric property coercion ───────────────────────────────────────────────
80
- describe('processRichTextField — numeric property coercion', ()=>{
81
- it('should convert detail, format, indent, version from strings to numbers', ()=>{
82
- const input = textNode({
83
- detail: '0',
84
- format: '0',
85
- indent: '0',
86
- version: '1'
87
- });
88
- const result = asRecord(processRichTextField(input));
89
- expect(result.detail).toBe(0);
90
- expect(result.format).toBe(0);
91
- expect(result.indent).toBe(0);
92
- expect(result.version).toBe(1);
93
- });
94
- it('should convert start and value from strings to numbers (list/listitem nodes)', ()=>{
95
- const listItemNode = {
96
- type: 'listitem',
97
- start: '1',
98
- value: '2',
99
- version: '1'
100
- };
101
- const result = asRecord(processRichTextField(listItemNode));
102
- expect(result.start).toBe(1);
103
- expect(result.value).toBe(2);
104
- });
105
- it('should convert textFormat and textStyle from strings to numbers', ()=>{
106
- const input = {
107
- type: 'text',
108
- textFormat: '4',
109
- textStyle: '0',
110
- version: '1',
111
- text: 'x'
112
- };
113
- const result = asRecord(processRichTextField(input));
114
- expect(result.textFormat).toBe(4);
115
- expect(result.textStyle).toBe(0);
116
- });
117
- it('should leave a non-numeric string in a numeric-property slot unchanged', ()=>{
118
- // Lexical paragraph format can be "" (empty) or alignment strings
119
- const input = paragraphNode();
120
- const result = asRecord(processRichTextField(input));
121
- expect(result.format).toBe('');
122
- });
123
- it('should leave already-numeric values unchanged', ()=>{
124
- const input = textNode({
125
- detail: 0,
126
- format: 3,
127
- version: 1
128
- });
129
- const result = asRecord(processRichTextField(input));
130
- expect(result.detail).toBe(0);
131
- expect(result.format).toBe(3);
132
- expect(result.version).toBe(1);
133
- });
134
- it('should not convert boolean values on numeric-property keys', ()=>{
135
- const input = {
136
- type: 'custom',
137
- format: true,
138
- version: '1'
139
- };
140
- const result = asRecord(processRichTextField(input));
141
- expect(result.format).toBe(true);
142
- expect(result.version).toBe(1);
143
- });
144
- });
145
- // ─── Recursive children processing ──────────────────────────────────────────
146
- describe('processRichTextField — recursive children', ()=>{
147
- it('should recursively convert numeric strings inside children arrays', ()=>{
148
- const input = paragraphNode([
149
- textNode({
150
- detail: '0',
151
- format: '0',
152
- version: '1'
153
- })
154
- ]);
155
- const result = asRecord(processRichTextField(input));
156
- const child = asRecord(asArray(result.children)[0]);
157
- expect(child.detail).toBe(0);
158
- expect(child.format).toBe(0);
159
- expect(child.version).toBe(1);
160
- });
161
- it('should handle three levels of nesting (root → paragraph → text)', ()=>{
162
- const input = lexicalDoc([
163
- paragraphNode([
164
- textNode({
165
- version: '1',
166
- format: '2'
167
- })
168
- ])
169
- ]);
170
- const result = asRecord(processRichTextField(input));
171
- const paragraph = asRecord(asArray(result.children)[0]);
172
- const text = asRecord(asArray(paragraph.children)[0]);
173
- expect(text.version).toBe(1);
174
- expect(text.format).toBe(2);
175
- });
176
- it('should handle multiple children at the same level', ()=>{
177
- const input = lexicalDoc([
178
- paragraphNode([
179
- textNode({
180
- text: 'Bold',
181
- format: '1'
182
- }),
183
- textNode({
184
- text: ' normal',
185
- format: '0'
186
- })
187
- ]),
188
- paragraphNode([
189
- textNode({
190
- text: 'Second para',
191
- version: '1'
192
- })
193
- ])
194
- ]);
195
- const result = asRecord(processRichTextField(input));
196
- const firstPara = asRecord(asArray(result.children)[0]);
197
- const secondPara = asRecord(asArray(result.children)[1]);
198
- const bold = asRecord(asArray(firstPara.children)[0]);
199
- const normal = asRecord(asArray(firstPara.children)[1]);
200
- const secondText = asRecord(asArray(secondPara.children)[0]);
201
- expect(bold.format).toBe(1);
202
- expect(normal.format).toBe(0);
203
- expect(secondText.version).toBe(1);
204
- });
205
- it('should skip null and non-object entries in children without throwing', ()=>{
206
- const input = {
207
- type: 'root',
208
- version: 1,
209
- children: [
210
- null,
211
- undefined,
212
- 'stray',
213
- textNode()
214
- ]
215
- };
216
- const result = asRecord(processRichTextField(input));
217
- const children = asArray(result.children);
218
- expect(children[0]).toBeNull();
219
- expect(children[1]).toBeUndefined();
220
- expect(children[2]).toBe('stray');
221
- expect(asRecord(children[3]).type).toBe('text');
222
- });
223
- });
224
- // ─── Nested non-children objects ─────────────────────────────────────────────
225
- describe('processRichTextField — nested non-children objects', ()=>{
226
- it('should recurse into plain nested objects (e.g. decorator node data)', ()=>{
227
- const input = {
228
- type: 'decorator',
229
- version: '1',
230
- data: {
231
- detail: '2',
232
- label: 'keep me'
233
- }
234
- };
235
- const result = asRecord(processRichTextField(input));
236
- const data = asRecord(result.data);
237
- expect(result.version).toBe(1);
238
- expect(data.detail).toBe(2);
239
- expect(data.label).toBe('keep me');
240
- });
241
- });
242
- // ─── Full Lexical document round-trips ───────────────────────────────────────
243
- describe('processRichTextField — full document', ()=>{
244
- it('should produce a stable result when called on an already-processed object', ()=>{
245
- const doc = lexicalDoc();
246
- const firstPass = processRichTextField(doc);
247
- const secondPass = processRichTextField(firstPass);
248
- expect(secondPass).toEqual(firstPass);
249
- });
250
- it('should fully round-trip a complex Lexical document serialised to JSON', ()=>{
251
- const doc = lexicalDoc([
252
- paragraphNode([
253
- textNode({
254
- text: 'Bold',
255
- format: '1',
256
- detail: '0',
257
- indent: '0',
258
- version: '1'
259
- }),
260
- textNode({
261
- text: ' normal',
262
- format: '0',
263
- version: '1'
264
- })
265
- ]),
266
- {
267
- type: 'list',
268
- listType: 'number',
269
- start: '1',
270
- version: '1',
271
- indent: '0',
272
- direction: 'ltr',
273
- children: [
274
- {
275
- type: 'listitem',
276
- value: '1',
277
- detail: '0',
278
- format: '0',
279
- version: '1',
280
- text: 'Item A'
281
- },
282
- {
283
- type: 'listitem',
284
- value: '2',
285
- detail: '0',
286
- format: '0',
287
- version: '1',
288
- text: 'Item B'
289
- }
290
- ]
291
- }
292
- ]);
293
- const result = asRecord(processRichTextField(JSON.stringify(doc)));
294
- const para = asRecord(asArray(result.children)[0]);
295
- const boldText = asRecord(asArray(para.children)[0]);
296
- expect(boldText.format).toBe(1);
297
- expect(boldText.detail).toBe(0);
298
- const list = asRecord(asArray(result.children)[1]);
299
- expect(list.start).toBe(1);
300
- expect(list.indent).toBe(0);
301
- const itemA = asRecord(asArray(list.children)[0]);
302
- const itemB = asRecord(asArray(list.children)[1]);
303
- expect(itemA.value).toBe(1);
304
- expect(itemB.value).toBe(2);
305
- });
306
- });
307
-
308
- //# sourceMappingURL=processRichTextField.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/utilities/processRichTextField.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { processRichTextField } from './processRichTextField.js'\n\n// Minimal helpers to keep assertions readable\nconst asRecord = (v: unknown) => v as Record<string, unknown>\nconst asArray = (v: unknown) => v as unknown[]\n\n// ─── Fixtures ────────────────────────────────────────────────────────────────\n\nconst textNode = (overrides: Record<string, unknown> = {}) => ({\n detail: 0,\n format: 0,\n mode: 'normal',\n text: 'Hello',\n type: 'text',\n version: 1,\n ...overrides,\n})\n\nconst paragraphNode = (children: unknown[] = [textNode()]) => ({\n children,\n direction: 'ltr',\n format: '',\n indent: 0,\n type: 'paragraph',\n version: 1,\n})\n\nconst lexicalDoc = (children: unknown[] = [paragraphNode()]) => ({\n children,\n direction: 'ltr',\n format: '',\n indent: 0,\n type: 'root',\n version: 1,\n})\n\n// ─── Primitive pass-through ──────────────────────────────────────────────────\n\ndescribe('processRichTextField — primitive pass-through', () => {\n it('should return null unchanged', () => {\n expect(processRichTextField(null)).toBeNull()\n })\n\n it('should return undefined unchanged', () => {\n expect(processRichTextField(undefined)).toBeUndefined()\n })\n\n it('should return a number unchanged', () => {\n expect(processRichTextField(42)).toBe(42)\n })\n\n it('should return false unchanged', () => {\n expect(processRichTextField(false)).toBe(false)\n })\n})\n\n// ─── String input (the recovered-from-missed-hook path) ─────────────────────\n\ndescribe('processRichTextField — JSON string input', () => {\n it('should parse a valid JSON string into an object', () => {\n const doc = lexicalDoc()\n expect(processRichTextField(JSON.stringify(doc))).toEqual(doc)\n })\n\n it('should return an unparseable string unchanged', () => {\n expect(processRichTextField('not json')).toBe('not json')\n })\n\n it('should return an empty string unchanged', () => {\n expect(processRichTextField('')).toBe('')\n })\n\n it('should parse a string and still convert numeric string properties', () => {\n const node = { type: 'text', detail: '0', format: '3', indent: '0', version: '1', text: 'hi' }\n const result = asRecord(processRichTextField(JSON.stringify(node)))\n expect(result.detail).toBe(0)\n expect(result.format).toBe(3)\n expect(result.indent).toBe(0)\n expect(result.version).toBe(1)\n })\n})\n\n// ─── Numeric property coercion ───────────────────────────────────────────────\n\ndescribe('processRichTextField — numeric property coercion', () => {\n it('should convert detail, format, indent, version from strings to numbers', () => {\n const input = textNode({ detail: '0', format: '0', indent: '0', version: '1' })\n const result = asRecord(processRichTextField(input))\n expect(result.detail).toBe(0)\n expect(result.format).toBe(0)\n expect(result.indent).toBe(0)\n expect(result.version).toBe(1)\n })\n\n it('should convert start and value from strings to numbers (list/listitem nodes)', () => {\n const listItemNode = { type: 'listitem', start: '1', value: '2', version: '1' }\n const result = asRecord(processRichTextField(listItemNode))\n expect(result.start).toBe(1)\n expect(result.value).toBe(2)\n })\n\n it('should convert textFormat and textStyle from strings to numbers', () => {\n const input = { type: 'text', textFormat: '4', textStyle: '0', version: '1', text: 'x' }\n const result = asRecord(processRichTextField(input))\n expect(result.textFormat).toBe(4)\n expect(result.textStyle).toBe(0)\n })\n\n it('should leave a non-numeric string in a numeric-property slot unchanged', () => {\n // Lexical paragraph format can be \"\" (empty) or alignment strings\n const input = paragraphNode()\n const result = asRecord(processRichTextField(input))\n expect(result.format).toBe('')\n })\n\n it('should leave already-numeric values unchanged', () => {\n const input = textNode({ detail: 0, format: 3, version: 1 })\n const result = asRecord(processRichTextField(input))\n expect(result.detail).toBe(0)\n expect(result.format).toBe(3)\n expect(result.version).toBe(1)\n })\n\n it('should not convert boolean values on numeric-property keys', () => {\n const input = { type: 'custom', format: true, version: '1' }\n const result = asRecord(processRichTextField(input))\n expect(result.format).toBe(true)\n expect(result.version).toBe(1)\n })\n})\n\n// ─── Recursive children processing ──────────────────────────────────────────\n\ndescribe('processRichTextField — recursive children', () => {\n it('should recursively convert numeric strings inside children arrays', () => {\n const input = paragraphNode([textNode({ detail: '0', format: '0', version: '1' })])\n const result = asRecord(processRichTextField(input))\n const child = asRecord(asArray(result.children)[0])\n expect(child.detail).toBe(0)\n expect(child.format).toBe(0)\n expect(child.version).toBe(1)\n })\n\n it('should handle three levels of nesting (root → paragraph → text)', () => {\n const input = lexicalDoc([paragraphNode([textNode({ version: '1', format: '2' })])])\n const result = asRecord(processRichTextField(input))\n const paragraph = asRecord(asArray(result.children)[0])\n const text = asRecord(asArray(paragraph.children)[0])\n expect(text.version).toBe(1)\n expect(text.format).toBe(2)\n })\n\n it('should handle multiple children at the same level', () => {\n const input = lexicalDoc([\n paragraphNode([\n textNode({ text: 'Bold', format: '1' }),\n textNode({ text: ' normal', format: '0' }),\n ]),\n paragraphNode([textNode({ text: 'Second para', version: '1' })]),\n ])\n const result = asRecord(processRichTextField(input))\n const firstPara = asRecord(asArray(result.children)[0])\n const secondPara = asRecord(asArray(result.children)[1])\n const bold = asRecord(asArray(firstPara.children)[0])\n const normal = asRecord(asArray(firstPara.children)[1])\n const secondText = asRecord(asArray(secondPara.children)[0])\n expect(bold.format).toBe(1)\n expect(normal.format).toBe(0)\n expect(secondText.version).toBe(1)\n })\n\n it('should skip null and non-object entries in children without throwing', () => {\n const input = { type: 'root', version: 1, children: [null, undefined, 'stray', textNode()] }\n const result = asRecord(processRichTextField(input))\n const children = asArray(result.children)\n expect(children[0]).toBeNull()\n expect(children[1]).toBeUndefined()\n expect(children[2]).toBe('stray')\n expect(asRecord(children[3]).type).toBe('text')\n })\n})\n\n// ─── Nested non-children objects ─────────────────────────────────────────────\n\ndescribe('processRichTextField — nested non-children objects', () => {\n it('should recurse into plain nested objects (e.g. decorator node data)', () => {\n const input = {\n type: 'decorator',\n version: '1',\n data: { detail: '2', label: 'keep me' },\n }\n const result = asRecord(processRichTextField(input))\n const data = asRecord(result.data)\n expect(result.version).toBe(1)\n expect(data.detail).toBe(2)\n expect(data.label).toBe('keep me')\n })\n})\n\n// ─── Full Lexical document round-trips ───────────────────────────────────────\n\ndescribe('processRichTextField — full document', () => {\n it('should produce a stable result when called on an already-processed object', () => {\n const doc = lexicalDoc()\n const firstPass = processRichTextField(doc)\n const secondPass = processRichTextField(firstPass)\n expect(secondPass).toEqual(firstPass)\n })\n\n it('should fully round-trip a complex Lexical document serialised to JSON', () => {\n const doc = lexicalDoc([\n paragraphNode([\n textNode({ text: 'Bold', format: '1', detail: '0', indent: '0', version: '1' }),\n textNode({ text: ' normal', format: '0', version: '1' }),\n ]),\n {\n type: 'list',\n listType: 'number',\n start: '1',\n version: '1',\n indent: '0',\n direction: 'ltr',\n children: [\n { type: 'listitem', value: '1', detail: '0', format: '0', version: '1', text: 'Item A' },\n { type: 'listitem', value: '2', detail: '0', format: '0', version: '1', text: 'Item B' },\n ],\n },\n ])\n\n const result = asRecord(processRichTextField(JSON.stringify(doc)))\n\n const para = asRecord(asArray(result.children)[0])\n const boldText = asRecord(asArray(para.children)[0])\n expect(boldText.format).toBe(1)\n expect(boldText.detail).toBe(0)\n\n const list = asRecord(asArray(result.children)[1])\n expect(list.start).toBe(1)\n expect(list.indent).toBe(0)\n\n const itemA = asRecord(asArray(list.children)[0])\n const itemB = asRecord(asArray(list.children)[1])\n expect(itemA.value).toBe(1)\n expect(itemB.value).toBe(2)\n })\n})\n"],"names":["describe","expect","it","processRichTextField","asRecord","v","asArray","textNode","overrides","detail","format","mode","text","type","version","paragraphNode","children","direction","indent","lexicalDoc","toBeNull","undefined","toBeUndefined","toBe","doc","JSON","stringify","toEqual","node","result","input","listItemNode","start","value","textFormat","textStyle","child","paragraph","firstPara","secondPara","bold","normal","secondText","data","label","firstPass","secondPass","listType","para","boldText","list","itemA","itemB"],"mappings":"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"}