@payloadcms/plugin-import-export 3.77.0-canary.1 → 3.77.0-canary.2

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.
@@ -1,5 +1,5 @@
1
1
  import { fieldToRegex } from './fieldToRegex.js';
2
- export const flattenObject = ({ doc, fields, prefix, timezoneCompanionFields, toCSVFunctions })=>{
2
+ export const flattenObject = ({ doc, fields, prefix, toCSVFunctions })=>{
3
3
  const row = {};
4
4
  // Helper to get toCSV function by full path or base field name
5
5
  // This allows functions registered for field names (e.g., 'richText') to work
@@ -7,13 +7,19 @@ export const flattenObject = ({ doc, fields, prefix, timezoneCompanionFields, to
7
7
  const getToCSVFunction = (fullPath, baseFieldName)=>{
8
8
  return toCSVFunctions?.[fullPath] ?? toCSVFunctions?.[baseFieldName];
9
9
  };
10
- const flatten = (siblingDoc, prefix)=>{
10
+ // When fields are selected, build a set of top-level document keys to process.
11
+ // This prevents sibling fields with similar prefixes from being included
12
+ // (e.g. selecting 'dateWithTimezone' won't pull in 'dateWithTimezone_tz')
13
+ const selectedTopLevelKeys = Array.isArray(fields) && fields.length > 0 ? new Set(fields.map((f)=>f.split('.')[0])) : undefined;
14
+ const flattenWithFilter = (siblingDoc, currentPrefix)=>{
11
15
  Object.entries(siblingDoc).forEach(([key, value])=>{
12
- const newKey = prefix ? `${prefix}_${key}` : key;
16
+ // At the document root, skip keys that don't match any selected field
17
+ if (!currentPrefix && selectedTopLevelKeys && !selectedTopLevelKeys.has(key)) {
18
+ return;
19
+ }
20
+ const newKey = currentPrefix ? `${currentPrefix}_${key}` : key;
13
21
  const toCSVFn = getToCSVFunction(newKey, key);
14
22
  if (Array.isArray(value)) {
15
- // If a custom toCSV function exists for this array field, run it first.
16
- // If it produces output, skip per-item handling; otherwise, fall back.
17
23
  if (toCSVFn) {
18
24
  try {
19
25
  const result = toCSVFn({
@@ -25,17 +31,14 @@ export const flattenObject = ({ doc, fields, prefix, timezoneCompanionFields, to
25
31
  value
26
32
  });
27
33
  if (typeof result !== 'undefined') {
28
- // Custom function returned a single value for this array field.
29
34
  row[newKey] = result;
30
35
  return;
31
36
  }
32
- // If the custom function wrote any keys for this field, consider it handled.
33
37
  for(const k in row){
34
38
  if (k === newKey || k.startsWith(`${newKey}_`)) {
35
39
  return;
36
40
  }
37
41
  }
38
- // Otherwise, fall through to per-item handling.
39
42
  } catch (error) {
40
43
  throw new Error(`Error in toCSVFunction for array "${newKey}": ${JSON.stringify(value)}\n${error.message}`);
41
44
  }
@@ -44,23 +47,19 @@ export const flattenObject = ({ doc, fields, prefix, timezoneCompanionFields, to
44
47
  if (typeof item === 'object' && item !== null) {
45
48
  const blockType = typeof item.blockType === 'string' ? item.blockType : undefined;
46
49
  const itemPrefix = blockType ? `${newKey}_${index}_${blockType}` : `${newKey}_${index}`;
47
- // Case: hasMany polymorphic relationships
48
50
  if ('relationTo' in item && 'value' in item && typeof item.value === 'object' && item.value !== null) {
49
51
  row[`${itemPrefix}_relationTo`] = item.relationTo;
50
52
  row[`${itemPrefix}_id`] = item.value.id;
51
53
  return;
52
54
  }
53
- // Fallback: deep-flatten nested objects
54
- flatten(item, itemPrefix);
55
+ flattenWithFilter(item, itemPrefix);
55
56
  } else {
56
- // Primitive array item.
57
57
  row[`${newKey}_${index}`] = item;
58
58
  }
59
59
  });
60
60
  } else if (typeof value === 'object' && value !== null) {
61
- // Object field: use custom toCSV if present, else recurse.
62
61
  if (!toCSVFn) {
63
- flatten(value, newKey);
62
+ flattenWithFilter(value, newKey);
64
63
  } else {
65
64
  try {
66
65
  const result = toCSVFn({
@@ -101,7 +100,7 @@ export const flattenObject = ({ doc, fields, prefix, timezoneCompanionFields, to
101
100
  }
102
101
  });
103
102
  };
104
- flatten(doc, prefix);
103
+ flattenWithFilter(doc, prefix);
105
104
  if (Array.isArray(fields) && fields.length > 0) {
106
105
  const orderedResult = {};
107
106
  // Build all field regexes once
@@ -109,12 +108,6 @@ export const flattenObject = ({ doc, fields, prefix, timezoneCompanionFields, to
109
108
  field,
110
109
  regex: fieldToRegex(field)
111
110
  }));
112
- // Track which timezone companion fields were explicitly selected
113
- // Convert dotted notation to underscore for matching against flattened keys
114
- const explicitlySelectedTimezoneFields = new Set(fields.filter((f)=>{
115
- const underscored = f.replace(/\./g, '_');
116
- return timezoneCompanionFields?.has(underscored);
117
- }).map((f)=>f.replace(/\./g, '_')));
118
111
  // Single pass through row keys - O(keys * fields) regex tests but only one iteration
119
112
  const rowKeys = Object.keys(row);
120
113
  // Process in field order to maintain user's specified ordering
@@ -124,10 +117,6 @@ export const flattenObject = ({ doc, fields, prefix, timezoneCompanionFields, to
124
117
  if (key in orderedResult) {
125
118
  continue;
126
119
  }
127
- // Skip auto-generated timezone companion fields unless explicitly selected
128
- if (timezoneCompanionFields?.has(key) && !explicitlySelectedTimezoneFields.has(key)) {
129
- continue;
130
- }
131
120
  if (regex.test(key)) {
132
121
  orderedResult[key] = row[key];
133
122
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/flattenObject.ts"],"sourcesContent":["import type { Document } from 'payload'\n\nimport type { ToCSVFunction } from '../types.js'\n\nimport { fieldToRegex } from './fieldToRegex.js'\n\ntype Args = {\n doc: Document\n fields?: string[]\n prefix?: string\n /**\n * Set of auto-generated timezone companion field names (from collectTimezoneCompanionFields).\n * These fields are excluded unless explicitly selected.\n * If not provided, no timezone filtering is applied.\n */\n timezoneCompanionFields?: Set<string>\n toCSVFunctions: Record<string, ToCSVFunction>\n}\n\nexport const flattenObject = ({\n doc,\n fields,\n prefix,\n timezoneCompanionFields,\n toCSVFunctions,\n}: Args): Record<string, unknown> => {\n const row: Record<string, unknown> = {}\n\n // Helper to get toCSV function by full path or base field name\n // This allows functions registered for field names (e.g., 'richText') to work\n // even when the field is nested in arrays/blocks (e.g., 'blocks_0_content_richText')\n const getToCSVFunction = (fullPath: string, baseFieldName: string): ToCSVFunction | undefined => {\n return toCSVFunctions?.[fullPath] ?? toCSVFunctions?.[baseFieldName]\n }\n\n const flatten = (siblingDoc: Document, prefix?: string) => {\n Object.entries(siblingDoc).forEach(([key, value]) => {\n const newKey = prefix ? `${prefix}_${key}` : key\n const toCSVFn = getToCSVFunction(newKey, key)\n\n if (Array.isArray(value)) {\n // If a custom toCSV function exists for this array field, run it first.\n // If it produces output, skip per-item handling; otherwise, fall back.\n if (toCSVFn) {\n try {\n const result = toCSVFn({\n columnName: newKey,\n data: row,\n doc,\n row,\n siblingDoc,\n value, // whole array\n })\n\n if (typeof result !== 'undefined') {\n // Custom function returned a single value for this array field.\n row[newKey] = result\n return\n }\n\n // If the custom function wrote any keys for this field, consider it handled.\n for (const k in row) {\n if (k === newKey || k.startsWith(`${newKey}_`)) {\n return\n }\n }\n // Otherwise, fall through to per-item handling.\n } catch (error) {\n throw new Error(\n `Error in toCSVFunction for array \"${newKey}\": ${JSON.stringify(value)}\\n${\n (error as Error).message\n }`,\n )\n }\n }\n\n value.forEach((item, index) => {\n if (typeof item === 'object' && item !== null) {\n const blockType = typeof item.blockType === 'string' ? item.blockType : undefined\n const itemPrefix = blockType ? `${newKey}_${index}_${blockType}` : `${newKey}_${index}`\n\n // Case: hasMany polymorphic relationships\n if (\n 'relationTo' in item &&\n 'value' in item &&\n typeof item.value === 'object' &&\n item.value !== null\n ) {\n row[`${itemPrefix}_relationTo`] = item.relationTo\n row[`${itemPrefix}_id`] = item.value.id\n return\n }\n\n // Fallback: deep-flatten nested objects\n flatten(item, itemPrefix)\n } else {\n // Primitive array item.\n row[`${newKey}_${index}`] = item\n }\n })\n } else if (typeof value === 'object' && value !== null) {\n // Object field: use custom toCSV if present, else recurse.\n if (!toCSVFn) {\n flatten(value, newKey)\n } else {\n try {\n const result = toCSVFn({\n columnName: newKey,\n data: row,\n doc,\n row,\n siblingDoc,\n value,\n })\n if (typeof result !== 'undefined') {\n row[newKey] = result\n }\n } catch (error) {\n throw new Error(\n `Error in toCSVFunction for nested object \"${newKey}\": ${JSON.stringify(value)}\\n${\n (error as Error).message\n }`,\n )\n }\n }\n } else {\n if (toCSVFn) {\n try {\n const result = toCSVFn({\n columnName: newKey,\n data: row,\n doc,\n row,\n siblingDoc,\n value,\n })\n if (typeof result !== 'undefined') {\n row[newKey] = result\n }\n } catch (error) {\n throw new Error(\n `Error in toCSVFunction for field \"${newKey}\": ${JSON.stringify(value)}\\n${\n (error as Error).message\n }`,\n )\n }\n } else {\n row[newKey] = value\n }\n }\n })\n }\n\n flatten(doc, prefix)\n\n if (Array.isArray(fields) && fields.length > 0) {\n const orderedResult: Record<string, unknown> = {}\n\n // Build all field regexes once\n const fieldPatterns = fields.map((field) => ({\n field,\n regex: fieldToRegex(field),\n }))\n\n // Track which timezone companion fields were explicitly selected\n // Convert dotted notation to underscore for matching against flattened keys\n const explicitlySelectedTimezoneFields = new Set(\n fields\n .filter((f) => {\n const underscored = f.replace(/\\./g, '_')\n return timezoneCompanionFields?.has(underscored)\n })\n .map((f) => f.replace(/\\./g, '_')),\n )\n\n // Single pass through row keys - O(keys * fields) regex tests but only one iteration\n const rowKeys = Object.keys(row)\n\n // Process in field order to maintain user's specified ordering\n for (const { regex } of fieldPatterns) {\n for (const key of rowKeys) {\n // Skip if already added (a key might match multiple field patterns)\n if (key in orderedResult) {\n continue\n }\n\n // Skip auto-generated timezone companion fields unless explicitly selected\n if (timezoneCompanionFields?.has(key) && !explicitlySelectedTimezoneFields.has(key)) {\n continue\n }\n\n if (regex.test(key)) {\n orderedResult[key] = row[key]\n }\n }\n }\n\n return orderedResult\n }\n\n return row\n}\n"],"names":["fieldToRegex","flattenObject","doc","fields","prefix","timezoneCompanionFields","toCSVFunctions","row","getToCSVFunction","fullPath","baseFieldName","flatten","siblingDoc","Object","entries","forEach","key","value","newKey","toCSVFn","Array","isArray","result","columnName","data","k","startsWith","error","Error","JSON","stringify","message","item","index","blockType","undefined","itemPrefix","relationTo","id","length","orderedResult","fieldPatterns","map","field","regex","explicitlySelectedTimezoneFields","Set","filter","f","underscored","replace","has","rowKeys","keys","test"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utilities/flattenObject.ts"],"sourcesContent":["import type { Document } from 'payload'\n\nimport type { ToCSVFunction } from '../types.js'\n\nimport { fieldToRegex } from './fieldToRegex.js'\n\ntype Args = {\n doc: Document\n fields?: string[]\n prefix?: string\n toCSVFunctions: Record<string, ToCSVFunction>\n}\n\nexport const flattenObject = ({\n doc,\n fields,\n prefix,\n toCSVFunctions,\n}: Args): Record<string, unknown> => {\n const row: Record<string, unknown> = {}\n\n // Helper to get toCSV function by full path or base field name\n // This allows functions registered for field names (e.g., 'richText') to work\n // even when the field is nested in arrays/blocks (e.g., 'blocks_0_content_richText')\n const getToCSVFunction = (fullPath: string, baseFieldName: string): ToCSVFunction | undefined => {\n return toCSVFunctions?.[fullPath] ?? toCSVFunctions?.[baseFieldName]\n }\n\n // When fields are selected, build a set of top-level document keys to process.\n // This prevents sibling fields with similar prefixes from being included\n // (e.g. selecting 'dateWithTimezone' won't pull in 'dateWithTimezone_tz')\n const selectedTopLevelKeys =\n Array.isArray(fields) && fields.length > 0\n ? new Set(fields.map((f) => f.split('.')[0]))\n : undefined\n\n const flattenWithFilter = (siblingDoc: Document, currentPrefix?: string) => {\n Object.entries(siblingDoc).forEach(([key, value]) => {\n // At the document root, skip keys that don't match any selected field\n if (!currentPrefix && selectedTopLevelKeys && !selectedTopLevelKeys.has(key)) {\n return\n }\n\n const newKey = currentPrefix ? `${currentPrefix}_${key}` : key\n const toCSVFn = getToCSVFunction(newKey, key)\n\n if (Array.isArray(value)) {\n if (toCSVFn) {\n try {\n const result = toCSVFn({\n columnName: newKey,\n data: row,\n doc,\n row,\n siblingDoc,\n value,\n })\n\n if (typeof result !== 'undefined') {\n row[newKey] = result\n return\n }\n\n for (const k in row) {\n if (k === newKey || k.startsWith(`${newKey}_`)) {\n return\n }\n }\n } catch (error) {\n throw new Error(\n `Error in toCSVFunction for array \"${newKey}\": ${JSON.stringify(value)}\\n${\n (error as Error).message\n }`,\n )\n }\n }\n\n value.forEach((item, index) => {\n if (typeof item === 'object' && item !== null) {\n const blockType = typeof item.blockType === 'string' ? item.blockType : undefined\n const itemPrefix = blockType ? `${newKey}_${index}_${blockType}` : `${newKey}_${index}`\n\n if (\n 'relationTo' in item &&\n 'value' in item &&\n typeof item.value === 'object' &&\n item.value !== null\n ) {\n row[`${itemPrefix}_relationTo`] = item.relationTo\n row[`${itemPrefix}_id`] = item.value.id\n return\n }\n\n flattenWithFilter(item, itemPrefix)\n } else {\n row[`${newKey}_${index}`] = item\n }\n })\n } else if (typeof value === 'object' && value !== null) {\n if (!toCSVFn) {\n flattenWithFilter(value, newKey)\n } else {\n try {\n const result = toCSVFn({\n columnName: newKey,\n data: row,\n doc,\n row,\n siblingDoc,\n value,\n })\n if (typeof result !== 'undefined') {\n row[newKey] = result\n }\n } catch (error) {\n throw new Error(\n `Error in toCSVFunction for nested object \"${newKey}\": ${JSON.stringify(value)}\\n${\n (error as Error).message\n }`,\n )\n }\n }\n } else {\n if (toCSVFn) {\n try {\n const result = toCSVFn({\n columnName: newKey,\n data: row,\n doc,\n row,\n siblingDoc,\n value,\n })\n if (typeof result !== 'undefined') {\n row[newKey] = result\n }\n } catch (error) {\n throw new Error(\n `Error in toCSVFunction for field \"${newKey}\": ${JSON.stringify(value)}\\n${\n (error as Error).message\n }`,\n )\n }\n } else {\n row[newKey] = value\n }\n }\n })\n }\n\n flattenWithFilter(doc, prefix)\n\n if (Array.isArray(fields) && fields.length > 0) {\n const orderedResult: Record<string, unknown> = {}\n\n // Build all field regexes once\n const fieldPatterns = fields.map((field) => ({\n field,\n regex: fieldToRegex(field),\n }))\n\n // Single pass through row keys - O(keys * fields) regex tests but only one iteration\n const rowKeys = Object.keys(row)\n\n // Process in field order to maintain user's specified ordering\n for (const { regex } of fieldPatterns) {\n for (const key of rowKeys) {\n // Skip if already added (a key might match multiple field patterns)\n if (key in orderedResult) {\n continue\n }\n\n if (regex.test(key)) {\n orderedResult[key] = row[key]\n }\n }\n }\n\n return orderedResult\n }\n\n return row\n}\n"],"names":["fieldToRegex","flattenObject","doc","fields","prefix","toCSVFunctions","row","getToCSVFunction","fullPath","baseFieldName","selectedTopLevelKeys","Array","isArray","length","Set","map","f","split","undefined","flattenWithFilter","siblingDoc","currentPrefix","Object","entries","forEach","key","value","has","newKey","toCSVFn","result","columnName","data","k","startsWith","error","Error","JSON","stringify","message","item","index","blockType","itemPrefix","relationTo","id","orderedResult","fieldPatterns","field","regex","rowKeys","keys","test"],"mappings":"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"}
@@ -20,12 +20,6 @@ export type GetSchemaColumnsArgs = {
20
20
  * Available locale codes from config. Required when locale='all'.
21
21
  */
22
22
  localeCodes?: string[];
23
- /**
24
- * Set of auto-generated timezone companion field names (from collectTimezoneCompanionFields).
25
- * These fields are excluded unless explicitly selected.
26
- * If not provided, no timezone filtering is applied.
27
- */
28
- timezoneCompanionFields?: Set<string>;
29
23
  };
30
24
  /**
31
25
  * Derives CSV column names from the collection schema.
@@ -39,11 +33,21 @@ export type GetSchemaColumnsArgs = {
39
33
  * - Works for empty exports
40
34
  * - Ensures proper column ordering
41
35
  */
42
- export declare const getSchemaColumns: ({ collectionConfig, disabledFields, fields: selectedFields, locale, localeCodes, timezoneCompanionFields, }: GetSchemaColumnsArgs) => string[];
36
+ export declare const getSchemaColumns: ({ collectionConfig, disabledFields, fields: selectedFields, locale, localeCodes, }: GetSchemaColumnsArgs) => string[];
43
37
  /**
44
38
  * Merges schema-derived columns with data-discovered columns.
45
39
  * Schema columns provide the base ordering, data columns add any additional
46
40
  * columns (e.g., array indices beyond 0, dynamic fields, derived columns from toCSV).
47
41
  */
48
42
  export declare const mergeColumns: (schemaColumns: string[], dataColumns: string[]) => string[];
43
+ /**
44
+ * Filters schema columns to only include those matching user-selected fields.
45
+ * Preserves the order specified by the user in selectedFields.
46
+ *
47
+ * Container fields (groups, arrays, blocks) don't produce their own column, so we prefix-expand
48
+ * to find their children (e.g., 'group' → 'group_name', 'group_age').
49
+ * Leaf fields (date, text, select) produce an exact column, so we only match exactly to avoid
50
+ * including siblings with similar prefixes (e.g., 'dateWithTimezone' won't pull 'dateWithTimezone_tz').
51
+ */
52
+ export declare function filterToSelectedFields(columns: string[], selectedFields: string[]): string[];
49
53
  //# sourceMappingURL=getSchemaColumns.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getSchemaColumns.d.ts","sourceRoot":"","sources":["../../src/utilities/getSchemaColumns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAIxD,MAAM,MAAM,oBAAoB,GAAG;IACjC;;OAEG;IACH,gBAAgB,EAAE,yBAAyB,CAAA;IAC3C;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB;;OAEG;IACH,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,CAAA;IACtB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CACtC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,gHAO1B,oBAAoB,KAAG,MAAM,EA4E/B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,kBAAmB,MAAM,EAAE,eAAe,MAAM,EAAE,KAAG,MAAM,EA+DnF,CAAA"}
1
+ {"version":3,"file":"getSchemaColumns.d.ts","sourceRoot":"","sources":["../../src/utilities/getSchemaColumns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAIxD,MAAM,MAAM,oBAAoB,GAAG;IACjC;;OAEG;IACH,gBAAgB,EAAE,yBAAyB,CAAA;IAC3C;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB;;OAEG;IACH,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,CAAA;IACtB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,uFAM1B,oBAAoB,KAAG,MAAM,EA4E/B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,kBAAmB,MAAM,EAAE,eAAe,MAAM,EAAE,KAAG,MAAM,EAyEnF,CAAA;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAmC5F"}
@@ -10,7 +10,7 @@ import { getFlattenedFieldKeys } from './getFlattenedFieldKeys.js';
10
10
  * - Provides consistent base columns
11
11
  * - Works for empty exports
12
12
  * - Ensures proper column ordering
13
- */ export const getSchemaColumns = ({ collectionConfig, disabledFields = [], fields: selectedFields, locale, localeCodes, timezoneCompanionFields })=>{
13
+ */ export const getSchemaColumns = ({ collectionConfig, disabledFields = [], fields: selectedFields, locale, localeCodes })=>{
14
14
  const hasVersions = Boolean(collectionConfig.versions);
15
15
  // Determine if we need locale expansion
16
16
  const expandLocales = locale === 'all' && localeCodes && localeCodes.length > 0;
@@ -30,7 +30,7 @@ import { getFlattenedFieldKeys } from './getFlattenedFieldKeys.js';
30
30
  ];
31
31
  // Filter to user-selected fields if specified
32
32
  if (selectedFields && selectedFields.length > 0) {
33
- schemaColumns = filterToSelectedFields(schemaColumns, selectedFields, timezoneCompanionFields);
33
+ schemaColumns = filterToSelectedFields(schemaColumns, selectedFields);
34
34
  }
35
35
  // Remove disabled fields
36
36
  if (disabledFields.length > 0) {
@@ -148,13 +148,26 @@ import { getFlattenedFieldKeys } from './getFlattenedFieldKeys.js';
148
148
  }
149
149
  }
150
150
  }
151
+ // Remove schema columns that were fully replaced by toCSV-derived columns (e.g. "user" → "user_id", "user_email")
152
+ for (const [schemaCol, derivedCols] of insertedDerived){
153
+ if (!dataColumns.includes(schemaCol) && derivedCols.length > 0) {
154
+ const idx = result.indexOf(schemaCol);
155
+ if (idx !== -1) {
156
+ result.splice(idx, 1);
157
+ }
158
+ }
159
+ }
151
160
  return result;
152
161
  };
153
162
  /**
154
163
  * Filters schema columns to only include those matching user-selected fields.
155
164
  * Preserves the order specified by the user in selectedFields.
156
- * Handles nested field selection (e.g., 'group.value' includes 'group_value' and 'group_value_*')
157
- */ function filterToSelectedFields(columns, selectedFields, timezoneCompanionFields) {
165
+ *
166
+ * Container fields (groups, arrays, blocks) don't produce their own column, so we prefix-expand
167
+ * to find their children (e.g., 'group' → 'group_name', 'group_age').
168
+ * Leaf fields (date, text, select) produce an exact column, so we only match exactly to avoid
169
+ * including siblings with similar prefixes (e.g., 'dateWithTimezone' won't pull 'dateWithTimezone_tz').
170
+ */ export function filterToSelectedFields(columns, selectedFields) {
158
171
  const result = [];
159
172
  const columnsSet = new Set(columns);
160
173
  // Convert selected fields to underscore notation patterns
@@ -166,27 +179,19 @@ import { getFlattenedFieldKeys } from './getFlattenedFieldKeys.js';
166
179
  prefix: `${underscored}_`
167
180
  };
168
181
  });
169
- // Track which timezone companion fields were explicitly selected
170
- const explicitlySelectedTzFields = new Set(selectedFields.filter((f)=>{
171
- const underscored = f.replace(/\./g, '_');
172
- return timezoneCompanionFields?.has(underscored);
173
- }).map((f)=>f.replace(/\./g, '_')));
174
182
  // Iterate through user-specified fields in order to preserve their ordering
175
183
  for (const pattern of patterns){
176
- // First add the exact match if it exists and not already added
177
- // (it may have been added as a nested field of a previous pattern)
178
- if (columnsSet.has(pattern.exact) && !result.includes(pattern.exact)) {
184
+ const hasExactColumn = columnsSet.has(pattern.exact);
185
+ if (hasExactColumn && !result.includes(pattern.exact)) {
179
186
  result.push(pattern.exact);
180
187
  }
181
- // Then add any columns with the prefix (nested fields)
182
- for (const column of columns){
183
- if (column !== pattern.exact && column.startsWith(pattern.prefix)) {
184
- // Skip auto-generated timezone companion fields unless explicitly selected
185
- if (timezoneCompanionFields?.has(column) && !explicitlySelectedTzFields.has(column)) {
186
- continue;
187
- }
188
- if (!result.includes(column)) {
189
- result.push(column);
188
+ // Only prefix-expand if no exact column match exists (containers need expansion, leaves don't)
189
+ if (!hasExactColumn) {
190
+ for (const column of columns){
191
+ if (column.startsWith(pattern.prefix)) {
192
+ if (!result.includes(column)) {
193
+ result.push(column);
194
+ }
190
195
  }
191
196
  }
192
197
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/getSchemaColumns.ts"],"sourcesContent":["import type { SanitizedCollectionConfig } from 'payload'\n\nimport { getFlattenedFieldKeys } from './getFlattenedFieldKeys.js'\n\nexport type GetSchemaColumnsArgs = {\n /**\n * The collection configuration to derive columns from\n */\n collectionConfig: SanitizedCollectionConfig\n /**\n * Array of disabled field paths from plugin config\n */\n disabledFields?: string[]\n /**\n * User-selected fields to export. If provided, only these fields (and their nested fields) will be included.\n */\n fields?: string[]\n /**\n * The locale to export. When 'all', localized fields are expanded to include all locale suffixes.\n */\n locale?: null | string\n /**\n * Available locale codes from config. Required when locale='all'.\n */\n localeCodes?: string[]\n /**\n * Set of auto-generated timezone companion field names (from collectTimezoneCompanionFields).\n * These fields are excluded unless explicitly selected.\n * If not provided, no timezone filtering is applied.\n */\n timezoneCompanionFields?: Set<string>\n}\n\n/**\n * Derives CSV column names from the collection schema.\n * This provides a base set of columns from field definitions.\n *\n * Note: For arrays/blocks with multiple items, the schema only generates index 0.\n * Additional indices from actual data should be merged with these columns.\n *\n * Benefits:\n * - Provides consistent base columns\n * - Works for empty exports\n * - Ensures proper column ordering\n */\nexport const getSchemaColumns = ({\n collectionConfig,\n disabledFields = [],\n fields: selectedFields,\n locale,\n localeCodes,\n timezoneCompanionFields,\n}: GetSchemaColumnsArgs): string[] => {\n const hasVersions = Boolean(collectionConfig.versions)\n\n // Determine if we need locale expansion\n const expandLocales = locale === 'all' && localeCodes && localeCodes.length > 0\n\n // Get all possible columns from schema (excludes system fields like id, createdAt, updatedAt)\n let schemaColumns = getFlattenedFieldKeys(\n collectionConfig.flattenedFields,\n '',\n expandLocales ? { localeCodes } : {},\n )\n\n // Add system fields that aren't in flattenedFields\n const systemFields = ['id', 'createdAt', 'updatedAt']\n schemaColumns = [...systemFields, ...schemaColumns]\n\n // Filter to user-selected fields if specified\n if (selectedFields && selectedFields.length > 0) {\n schemaColumns = filterToSelectedFields(schemaColumns, selectedFields, timezoneCompanionFields)\n }\n\n // Remove disabled fields\n if (disabledFields.length > 0) {\n const disabledSet = new Set<string>()\n for (const path of disabledFields) {\n // Convert dot notation to underscore and add to set\n disabledSet.add(path.replace(/\\./g, '_'))\n }\n schemaColumns = schemaColumns.filter((col) => {\n // Check if column matches any disabled path\n for (const disabled of disabledSet) {\n if (col === disabled || col.startsWith(`${disabled}_`)) {\n return false\n }\n }\n return true\n })\n }\n\n // When user has selected specific fields, preserve their ordering\n // filterToSelectedFields() already returns columns in user's specified order\n if (selectedFields && selectedFields.length > 0) {\n return schemaColumns\n }\n\n // No fields selected - apply default ordering (id first, timestamps last)\n const orderedColumns: string[] = []\n\n // 1. ID always first\n if (schemaColumns.includes('id')) {\n orderedColumns.push('id')\n }\n\n // 2. Status field for versioned collections\n if (hasVersions) {\n orderedColumns.push('_status')\n }\n\n // 3. All other fields (excluding id, timestamps, status)\n const excludeFromMiddle = new Set(['_status', 'createdAt', 'id', 'updatedAt'])\n for (const col of schemaColumns) {\n if (!excludeFromMiddle.has(col)) {\n orderedColumns.push(col)\n }\n }\n\n // 4. Timestamps at the end\n if (schemaColumns.includes('createdAt')) {\n orderedColumns.push('createdAt')\n }\n if (schemaColumns.includes('updatedAt')) {\n orderedColumns.push('updatedAt')\n }\n\n return orderedColumns\n}\n\n/**\n * Merges schema-derived columns with data-discovered columns.\n * Schema columns provide the base ordering, data columns add any additional\n * columns (e.g., array indices beyond 0, dynamic fields, derived columns from toCSV).\n */\nexport const mergeColumns = (schemaColumns: string[], dataColumns: string[]): string[] => {\n const result = [...schemaColumns]\n const schemaSet = new Set(schemaColumns)\n const insertedDerived = new Map<string, string[]>()\n\n // Add any data columns not in schema (preserves schema ordering, appends new ones)\n for (const col of dataColumns) {\n if (!schemaSet.has(col)) {\n let inserted = false\n\n // Check if this is a derived column from a schema column (e.g., field_id, field_email)\n // Pattern: schemaCol_suffix where suffix is NOT a number (array indices are handled separately)\n for (const schemaCol of schemaColumns) {\n if (col.startsWith(`${schemaCol}_`)) {\n const suffix = col.slice(schemaCol.length + 1)\n // Skip if suffix starts with a digit (array index pattern like field_0_*)\n if (!/^\\d/.test(suffix)) {\n const baseIdx = result.indexOf(schemaCol)\n if (baseIdx !== -1) {\n const derivedList = insertedDerived.get(schemaCol) || []\n const insertIdx = baseIdx + 1 + derivedList.length\n result.splice(insertIdx, 0, col)\n derivedList.push(col)\n insertedDerived.set(schemaCol, derivedList)\n schemaSet.add(col)\n inserted = true\n break\n }\n }\n }\n }\n\n if (!inserted) {\n // Check for array indices (e.g., field_1_*), insert after field_0_*\n const match = col.match(/^(.+?)_(\\d+)(_.*)?$/)\n if (match) {\n const [, basePath, index, suffix] = match\n if (basePath && index) {\n const prevIndex = parseInt(index, 10) - 1\n const prevCol = `${basePath}_${prevIndex}${suffix ?? ''}`\n const prevIdx = result.indexOf(prevCol)\n if (prevIdx !== -1) {\n // Insert after the previous index column\n result.splice(prevIdx + 1, 0, col)\n schemaSet.add(col)\n continue\n }\n }\n }\n\n // Otherwise append at the end (before timestamps)\n const createdAtIdx = result.indexOf('createdAt')\n if (createdAtIdx !== -1) {\n result.splice(createdAtIdx, 0, col)\n } else {\n result.push(col)\n }\n schemaSet.add(col)\n }\n }\n }\n\n return result\n}\n\n/**\n * Filters schema columns to only include those matching user-selected fields.\n * Preserves the order specified by the user in selectedFields.\n * Handles nested field selection (e.g., 'group.value' includes 'group_value' and 'group_value_*')\n */\nfunction filterToSelectedFields(\n columns: string[],\n selectedFields: string[],\n timezoneCompanionFields?: Set<string>,\n): string[] {\n const result: string[] = []\n const columnsSet = new Set(columns)\n\n // Convert selected fields to underscore notation patterns\n const patterns = selectedFields.map((field) => {\n const underscored = field.replace(/\\./g, '_')\n return {\n exact: underscored,\n original: field,\n prefix: `${underscored}_`,\n }\n })\n\n // Track which timezone companion fields were explicitly selected\n const explicitlySelectedTzFields = new Set(\n selectedFields\n .filter((f) => {\n const underscored = f.replace(/\\./g, '_')\n return timezoneCompanionFields?.has(underscored)\n })\n .map((f) => f.replace(/\\./g, '_')),\n )\n\n // Iterate through user-specified fields in order to preserve their ordering\n for (const pattern of patterns) {\n // First add the exact match if it exists and not already added\n // (it may have been added as a nested field of a previous pattern)\n if (columnsSet.has(pattern.exact) && !result.includes(pattern.exact)) {\n result.push(pattern.exact)\n }\n\n // Then add any columns with the prefix (nested fields)\n for (const column of columns) {\n if (column !== pattern.exact && column.startsWith(pattern.prefix)) {\n // Skip auto-generated timezone companion fields unless explicitly selected\n if (timezoneCompanionFields?.has(column) && !explicitlySelectedTzFields.has(column)) {\n continue\n }\n if (!result.includes(column)) {\n result.push(column)\n }\n }\n }\n }\n\n return result\n}\n"],"names":["getFlattenedFieldKeys","getSchemaColumns","collectionConfig","disabledFields","fields","selectedFields","locale","localeCodes","timezoneCompanionFields","hasVersions","Boolean","versions","expandLocales","length","schemaColumns","flattenedFields","systemFields","filterToSelectedFields","disabledSet","Set","path","add","replace","filter","col","disabled","startsWith","orderedColumns","includes","push","excludeFromMiddle","has","mergeColumns","dataColumns","result","schemaSet","insertedDerived","Map","inserted","schemaCol","suffix","slice","test","baseIdx","indexOf","derivedList","get","insertIdx","splice","set","match","basePath","index","prevIndex","parseInt","prevCol","prevIdx","createdAtIdx","columns","columnsSet","patterns","map","field","underscored","exact","original","prefix","explicitlySelectedTzFields","f","pattern","column"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utilities/getSchemaColumns.ts"],"sourcesContent":["import type { SanitizedCollectionConfig } from 'payload'\n\nimport { getFlattenedFieldKeys } from './getFlattenedFieldKeys.js'\n\nexport type GetSchemaColumnsArgs = {\n /**\n * The collection configuration to derive columns from\n */\n collectionConfig: SanitizedCollectionConfig\n /**\n * Array of disabled field paths from plugin config\n */\n disabledFields?: string[]\n /**\n * User-selected fields to export. If provided, only these fields (and their nested fields) will be included.\n */\n fields?: string[]\n /**\n * The locale to export. When 'all', localized fields are expanded to include all locale suffixes.\n */\n locale?: null | string\n /**\n * Available locale codes from config. Required when locale='all'.\n */\n localeCodes?: string[]\n}\n\n/**\n * Derives CSV column names from the collection schema.\n * This provides a base set of columns from field definitions.\n *\n * Note: For arrays/blocks with multiple items, the schema only generates index 0.\n * Additional indices from actual data should be merged with these columns.\n *\n * Benefits:\n * - Provides consistent base columns\n * - Works for empty exports\n * - Ensures proper column ordering\n */\nexport const getSchemaColumns = ({\n collectionConfig,\n disabledFields = [],\n fields: selectedFields,\n locale,\n localeCodes,\n}: GetSchemaColumnsArgs): string[] => {\n const hasVersions = Boolean(collectionConfig.versions)\n\n // Determine if we need locale expansion\n const expandLocales = locale === 'all' && localeCodes && localeCodes.length > 0\n\n // Get all possible columns from schema (excludes system fields like id, createdAt, updatedAt)\n let schemaColumns = getFlattenedFieldKeys(\n collectionConfig.flattenedFields,\n '',\n expandLocales ? { localeCodes } : {},\n )\n\n // Add system fields that aren't in flattenedFields\n const systemFields = ['id', 'createdAt', 'updatedAt']\n schemaColumns = [...systemFields, ...schemaColumns]\n\n // Filter to user-selected fields if specified\n if (selectedFields && selectedFields.length > 0) {\n schemaColumns = filterToSelectedFields(schemaColumns, selectedFields)\n }\n\n // Remove disabled fields\n if (disabledFields.length > 0) {\n const disabledSet = new Set<string>()\n for (const path of disabledFields) {\n // Convert dot notation to underscore and add to set\n disabledSet.add(path.replace(/\\./g, '_'))\n }\n schemaColumns = schemaColumns.filter((col) => {\n // Check if column matches any disabled path\n for (const disabled of disabledSet) {\n if (col === disabled || col.startsWith(`${disabled}_`)) {\n return false\n }\n }\n return true\n })\n }\n\n // When user has selected specific fields, preserve their ordering\n // filterToSelectedFields() already returns columns in user's specified order\n if (selectedFields && selectedFields.length > 0) {\n return schemaColumns\n }\n\n // No fields selected - apply default ordering (id first, timestamps last)\n const orderedColumns: string[] = []\n\n // 1. ID always first\n if (schemaColumns.includes('id')) {\n orderedColumns.push('id')\n }\n\n // 2. Status field for versioned collections\n if (hasVersions) {\n orderedColumns.push('_status')\n }\n\n // 3. All other fields (excluding id, timestamps, status)\n const excludeFromMiddle = new Set(['_status', 'createdAt', 'id', 'updatedAt'])\n for (const col of schemaColumns) {\n if (!excludeFromMiddle.has(col)) {\n orderedColumns.push(col)\n }\n }\n\n // 4. Timestamps at the end\n if (schemaColumns.includes('createdAt')) {\n orderedColumns.push('createdAt')\n }\n if (schemaColumns.includes('updatedAt')) {\n orderedColumns.push('updatedAt')\n }\n\n return orderedColumns\n}\n\n/**\n * Merges schema-derived columns with data-discovered columns.\n * Schema columns provide the base ordering, data columns add any additional\n * columns (e.g., array indices beyond 0, dynamic fields, derived columns from toCSV).\n */\nexport const mergeColumns = (schemaColumns: string[], dataColumns: string[]): string[] => {\n const result = [...schemaColumns]\n const schemaSet = new Set(schemaColumns)\n const insertedDerived = new Map<string, string[]>()\n\n // Add any data columns not in schema (preserves schema ordering, appends new ones)\n for (const col of dataColumns) {\n if (!schemaSet.has(col)) {\n let inserted = false\n\n // Check if this is a derived column from a schema column (e.g., field_id, field_email)\n // Pattern: schemaCol_suffix where suffix is NOT a number (array indices are handled separately)\n for (const schemaCol of schemaColumns) {\n if (col.startsWith(`${schemaCol}_`)) {\n const suffix = col.slice(schemaCol.length + 1)\n // Skip if suffix starts with a digit (array index pattern like field_0_*)\n if (!/^\\d/.test(suffix)) {\n const baseIdx = result.indexOf(schemaCol)\n if (baseIdx !== -1) {\n const derivedList = insertedDerived.get(schemaCol) || []\n const insertIdx = baseIdx + 1 + derivedList.length\n result.splice(insertIdx, 0, col)\n derivedList.push(col)\n insertedDerived.set(schemaCol, derivedList)\n schemaSet.add(col)\n inserted = true\n break\n }\n }\n }\n }\n\n if (!inserted) {\n // Check for array indices (e.g., field_1_*), insert after field_0_*\n const match = col.match(/^(.+?)_(\\d+)(_.*)?$/)\n if (match) {\n const [, basePath, index, suffix] = match\n if (basePath && index) {\n const prevIndex = parseInt(index, 10) - 1\n const prevCol = `${basePath}_${prevIndex}${suffix ?? ''}`\n const prevIdx = result.indexOf(prevCol)\n if (prevIdx !== -1) {\n // Insert after the previous index column\n result.splice(prevIdx + 1, 0, col)\n schemaSet.add(col)\n continue\n }\n }\n }\n\n // Otherwise append at the end (before timestamps)\n const createdAtIdx = result.indexOf('createdAt')\n if (createdAtIdx !== -1) {\n result.splice(createdAtIdx, 0, col)\n } else {\n result.push(col)\n }\n schemaSet.add(col)\n }\n }\n }\n\n // Remove schema columns that were fully replaced by toCSV-derived columns (e.g. \"user\" → \"user_id\", \"user_email\")\n for (const [schemaCol, derivedCols] of insertedDerived) {\n if (!dataColumns.includes(schemaCol) && derivedCols.length > 0) {\n const idx = result.indexOf(schemaCol)\n if (idx !== -1) {\n result.splice(idx, 1)\n }\n }\n }\n\n return result\n}\n\n/**\n * Filters schema columns to only include those matching user-selected fields.\n * Preserves the order specified by the user in selectedFields.\n *\n * Container fields (groups, arrays, blocks) don't produce their own column, so we prefix-expand\n * to find their children (e.g., 'group' → 'group_name', 'group_age').\n * Leaf fields (date, text, select) produce an exact column, so we only match exactly to avoid\n * including siblings with similar prefixes (e.g., 'dateWithTimezone' won't pull 'dateWithTimezone_tz').\n */\nexport function filterToSelectedFields(columns: string[], selectedFields: string[]): string[] {\n const result: string[] = []\n const columnsSet = new Set(columns)\n\n // Convert selected fields to underscore notation patterns\n const patterns = selectedFields.map((field) => {\n const underscored = field.replace(/\\./g, '_')\n return {\n exact: underscored,\n original: field,\n prefix: `${underscored}_`,\n }\n })\n\n // Iterate through user-specified fields in order to preserve their ordering\n for (const pattern of patterns) {\n const hasExactColumn = columnsSet.has(pattern.exact)\n\n if (hasExactColumn && !result.includes(pattern.exact)) {\n result.push(pattern.exact)\n }\n\n // Only prefix-expand if no exact column match exists (containers need expansion, leaves don't)\n if (!hasExactColumn) {\n for (const column of columns) {\n if (column.startsWith(pattern.prefix)) {\n if (!result.includes(column)) {\n result.push(column)\n }\n }\n }\n }\n }\n\n return result\n}\n"],"names":["getFlattenedFieldKeys","getSchemaColumns","collectionConfig","disabledFields","fields","selectedFields","locale","localeCodes","hasVersions","Boolean","versions","expandLocales","length","schemaColumns","flattenedFields","systemFields","filterToSelectedFields","disabledSet","Set","path","add","replace","filter","col","disabled","startsWith","orderedColumns","includes","push","excludeFromMiddle","has","mergeColumns","dataColumns","result","schemaSet","insertedDerived","Map","inserted","schemaCol","suffix","slice","test","baseIdx","indexOf","derivedList","get","insertIdx","splice","set","match","basePath","index","prevIndex","parseInt","prevCol","prevIdx","createdAtIdx","derivedCols","idx","columns","columnsSet","patterns","map","field","underscored","exact","original","prefix","pattern","hasExactColumn","column"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/plugin-import-export",
3
- "version": "3.77.0-canary.1",
3
+ "version": "3.77.0-canary.2",
4
4
  "description": "Import-Export plugin for Payload",
5
5
  "keywords": [
6
6
  "payload",
@@ -64,17 +64,17 @@
64
64
  "csv-parse": "5.6.0",
65
65
  "csv-stringify": "6.5.2",
66
66
  "qs-esm": "7.0.2",
67
- "@payloadcms/translations": "3.77.0-canary.1",
68
- "@payloadcms/ui": "3.77.0-canary.1"
67
+ "@payloadcms/translations": "3.77.0-canary.2",
68
+ "@payloadcms/ui": "3.77.0-canary.2"
69
69
  },
70
70
  "devDependencies": {
71
- "@payloadcms/ui": "3.77.0-canary.1",
72
- "payload": "3.77.0-canary.1",
73
- "@payloadcms/eslint-config": "3.28.0"
71
+ "@payloadcms/eslint-config": "3.28.0",
72
+ "@payloadcms/ui": "3.77.0-canary.2",
73
+ "payload": "3.77.0-canary.2"
74
74
  },
75
75
  "peerDependencies": {
76
- "@payloadcms/ui": "3.77.0-canary.1",
77
- "payload": "3.77.0-canary.1"
76
+ "@payloadcms/ui": "3.77.0-canary.2",
77
+ "payload": "3.77.0-canary.2"
78
78
  },
79
79
  "homepage:": "https://payloadcms.com",
80
80
  "scripts": {
@@ -1,24 +0,0 @@
1
- import type { FlattenedField } from 'payload';
2
- type FieldWithPresentational = {
3
- fields?: FlattenedField[];
4
- name?: string;
5
- tabs?: {
6
- fields: FlattenedField[];
7
- name?: string;
8
- }[];
9
- type: 'collapsible' | 'row' | 'tabs';
10
- } | FlattenedField;
11
- /**
12
- * Collects the names of auto-generated timezone companion fields from the schema.
13
- *
14
- * When a date field has `timezone: true`, Payload automatically generates a companion
15
- * select field and inserts it immediately after the date field in the fields array.
16
- * This function identifies those auto-generated fields by looking at the field sequence
17
- * rather than assuming a specific naming convention (since the name can be overridden).
18
- *
19
- * This is used to filter out timezone companions unless explicitly selected,
20
- * without incorrectly filtering user-defined fields that happen to end with `_tz`.
21
- */
22
- export declare const collectTimezoneCompanionFields: (fields: FieldWithPresentational[], prefix?: string) => Set<string>;
23
- export {};
24
- //# sourceMappingURL=collectTimezoneCompanionFields.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"collectTimezoneCompanionFields.d.ts","sourceRoot":"","sources":["../../src/utilities/collectTimezoneCompanionFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,KAAK,uBAAuB,GACxB;IACE,MAAM,CAAC,EAAE,cAAc,EAAE,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,cAAc,EAAE,CAAA;QACxB,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,EAAE,CAAA;IACH,IAAI,EAAE,aAAa,GAAG,KAAK,GAAG,MAAM,CAAA;CACrC,GACD,cAAc,CAAA;AAElB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,8BAA8B,WACjC,uBAAuB,EAAE,sBAEhC,GAAG,CAAC,MAAM,CAmFZ,CAAA"}
@@ -1,89 +0,0 @@
1
- /**
2
- * Collects the names of auto-generated timezone companion fields from the schema.
3
- *
4
- * When a date field has `timezone: true`, Payload automatically generates a companion
5
- * select field and inserts it immediately after the date field in the fields array.
6
- * This function identifies those auto-generated fields by looking at the field sequence
7
- * rather than assuming a specific naming convention (since the name can be overridden).
8
- *
9
- * This is used to filter out timezone companions unless explicitly selected,
10
- * without incorrectly filtering user-defined fields that happen to end with `_tz`.
11
- */ export const collectTimezoneCompanionFields = (fields, prefix = '')=>{
12
- const result = new Set();
13
- for(let i = 0; i < fields.length; i++){
14
- const field = fields[i];
15
- if (!field) {
16
- continue;
17
- }
18
- const name = 'name' in field && typeof field.name === 'string' ? field.name : undefined;
19
- const fullKey = name && prefix ? `${prefix}_${name}` : name ?? prefix;
20
- switch(field.type){
21
- case 'array':
22
- {
23
- // Recurse into array fields - companion fields inside arrays get the array prefix
24
- const subFields = collectTimezoneCompanionFields(field.fields, fullKey);
25
- for (const subField of subFields){
26
- result.add(subField);
27
- }
28
- break;
29
- }
30
- case 'blocks':
31
- {
32
- // Recurse into each block type
33
- for (const block of field.blocks){
34
- if (typeof block === 'string') {
35
- continue; // Skip block references
36
- }
37
- const blockPrefix = `${fullKey}_${block.slug}`;
38
- const blockFields = collectTimezoneCompanionFields(block.flattenedFields ?? block.fields, blockPrefix);
39
- for (const blockField of blockFields){
40
- result.add(blockField);
41
- }
42
- }
43
- break;
44
- }
45
- case 'collapsible':
46
- case 'group':
47
- case 'row':
48
- {
49
- const subFields = collectTimezoneCompanionFields(field.fields, fullKey);
50
- for (const subField of subFields){
51
- result.add(subField);
52
- }
53
- break;
54
- }
55
- case 'date':
56
- {
57
- // If this date field has timezone enabled, the next field should be the companion
58
- // (Payload splices it in right after the date field during sanitization)
59
- if ('timezone' in field && field.timezone) {
60
- const nextField = fields[i + 1];
61
- if (nextField && 'name' in nextField && nextField.type === 'select') {
62
- const companionName = prefix ? `${prefix}_${nextField.name}` : nextField.name;
63
- result.add(companionName);
64
- }
65
- }
66
- break;
67
- }
68
- case 'tabs':
69
- {
70
- for (const tab of field.tabs ?? []){
71
- let tabPrefix;
72
- if (tab.name) {
73
- tabPrefix = fullKey ? `${fullKey}_${tab.name}` : tab.name;
74
- } else {
75
- tabPrefix = fullKey;
76
- }
77
- const tabFields = collectTimezoneCompanionFields(tab.fields || [], tabPrefix);
78
- for (const tabField of tabFields){
79
- result.add(tabField);
80
- }
81
- }
82
- break;
83
- }
84
- }
85
- }
86
- return result;
87
- };
88
-
89
- //# sourceMappingURL=collectTimezoneCompanionFields.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/utilities/collectTimezoneCompanionFields.ts"],"sourcesContent":["import type { FlattenedField } from 'payload'\n\ntype FieldWithPresentational =\n | {\n fields?: FlattenedField[]\n name?: string\n tabs?: {\n fields: FlattenedField[]\n name?: string\n }[]\n type: 'collapsible' | 'row' | 'tabs'\n }\n | FlattenedField\n\n/**\n * Collects the names of auto-generated timezone companion fields from the schema.\n *\n * When a date field has `timezone: true`, Payload automatically generates a companion\n * select field and inserts it immediately after the date field in the fields array.\n * This function identifies those auto-generated fields by looking at the field sequence\n * rather than assuming a specific naming convention (since the name can be overridden).\n *\n * This is used to filter out timezone companions unless explicitly selected,\n * without incorrectly filtering user-defined fields that happen to end with `_tz`.\n */\nexport const collectTimezoneCompanionFields = (\n fields: FieldWithPresentational[],\n prefix = '',\n): Set<string> => {\n const result = new Set<string>()\n\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i]\n\n if (!field) {\n continue\n }\n\n const name = 'name' in field && typeof field.name === 'string' ? field.name : undefined\n const fullKey = name && prefix ? `${prefix}_${name}` : (name ?? prefix)\n\n switch (field.type) {\n case 'array': {\n // Recurse into array fields - companion fields inside arrays get the array prefix\n const subFields = collectTimezoneCompanionFields(field.fields as FlattenedField[], fullKey)\n for (const subField of subFields) {\n result.add(subField)\n }\n break\n }\n\n case 'blocks': {\n // Recurse into each block type\n for (const block of field.blocks) {\n if (typeof block === 'string') {\n continue // Skip block references\n }\n const blockPrefix = `${fullKey}_${block.slug}`\n const blockFields = collectTimezoneCompanionFields(\n block.flattenedFields ?? block.fields,\n blockPrefix,\n )\n for (const blockField of blockFields) {\n result.add(blockField)\n }\n }\n break\n }\n\n case 'collapsible':\n case 'group':\n case 'row': {\n const subFields = collectTimezoneCompanionFields(field.fields as FlattenedField[], fullKey)\n for (const subField of subFields) {\n result.add(subField)\n }\n break\n }\n\n case 'date': {\n // If this date field has timezone enabled, the next field should be the companion\n // (Payload splices it in right after the date field during sanitization)\n if ('timezone' in field && field.timezone) {\n const nextField = fields[i + 1]\n if (nextField && 'name' in nextField && nextField.type === 'select') {\n const companionName = prefix ? `${prefix}_${nextField.name}` : nextField.name\n result.add(companionName)\n }\n }\n break\n }\n\n case 'tabs': {\n for (const tab of field.tabs ?? []) {\n let tabPrefix: string\n if (tab.name) {\n tabPrefix = fullKey ? `${fullKey}_${tab.name}` : tab.name\n } else {\n tabPrefix = fullKey\n }\n const tabFields = collectTimezoneCompanionFields(tab.fields || [], tabPrefix)\n for (const tabField of tabFields) {\n result.add(tabField)\n }\n }\n break\n }\n }\n }\n\n return result\n}\n"],"names":["collectTimezoneCompanionFields","fields","prefix","result","Set","i","length","field","name","undefined","fullKey","type","subFields","subField","add","block","blocks","blockPrefix","slug","blockFields","flattenedFields","blockField","timezone","nextField","companionName","tab","tabs","tabPrefix","tabFields","tabField"],"mappings":"AAcA;;;;;;;;;;CAUC,GACD,OAAO,MAAMA,iCAAiC,CAC5CC,QACAC,SAAS,EAAE;IAEX,MAAMC,SAAS,IAAIC;IAEnB,IAAK,IAAIC,IAAI,GAAGA,IAAIJ,OAAOK,MAAM,EAAED,IAAK;QACtC,MAAME,QAAQN,MAAM,CAACI,EAAE;QAEvB,IAAI,CAACE,OAAO;YACV;QACF;QAEA,MAAMC,OAAO,UAAUD,SAAS,OAAOA,MAAMC,IAAI,KAAK,WAAWD,MAAMC,IAAI,GAAGC;QAC9E,MAAMC,UAAUF,QAAQN,SAAS,GAAGA,OAAO,CAAC,EAAEM,MAAM,GAAIA,QAAQN;QAEhE,OAAQK,MAAMI,IAAI;YAChB,KAAK;gBAAS;oBACZ,kFAAkF;oBAClF,MAAMC,YAAYZ,+BAA+BO,MAAMN,MAAM,EAAsBS;oBACnF,KAAK,MAAMG,YAAYD,UAAW;wBAChCT,OAAOW,GAAG,CAACD;oBACb;oBACA;gBACF;YAEA,KAAK;gBAAU;oBACb,+BAA+B;oBAC/B,KAAK,MAAME,SAASR,MAAMS,MAAM,CAAE;wBAChC,IAAI,OAAOD,UAAU,UAAU;4BAC7B,UAAS,wBAAwB;wBACnC;wBACA,MAAME,cAAc,GAAGP,QAAQ,CAAC,EAAEK,MAAMG,IAAI,EAAE;wBAC9C,MAAMC,cAAcnB,+BAClBe,MAAMK,eAAe,IAAIL,MAAMd,MAAM,EACrCgB;wBAEF,KAAK,MAAMI,cAAcF,YAAa;4BACpChB,OAAOW,GAAG,CAACO;wBACb;oBACF;oBACA;gBACF;YAEA,KAAK;YACL,KAAK;YACL,KAAK;gBAAO;oBACV,MAAMT,YAAYZ,+BAA+BO,MAAMN,MAAM,EAAsBS;oBACnF,KAAK,MAAMG,YAAYD,UAAW;wBAChCT,OAAOW,GAAG,CAACD;oBACb;oBACA;gBACF;YAEA,KAAK;gBAAQ;oBACX,kFAAkF;oBAClF,yEAAyE;oBACzE,IAAI,cAAcN,SAASA,MAAMe,QAAQ,EAAE;wBACzC,MAAMC,YAAYtB,MAAM,CAACI,IAAI,EAAE;wBAC/B,IAAIkB,aAAa,UAAUA,aAAaA,UAAUZ,IAAI,KAAK,UAAU;4BACnE,MAAMa,gBAAgBtB,SAAS,GAAGA,OAAO,CAAC,EAAEqB,UAAUf,IAAI,EAAE,GAAGe,UAAUf,IAAI;4BAC7EL,OAAOW,GAAG,CAACU;wBACb;oBACF;oBACA;gBACF;YAEA,KAAK;gBAAQ;oBACX,KAAK,MAAMC,OAAOlB,MAAMmB,IAAI,IAAI,EAAE,CAAE;wBAClC,IAAIC;wBACJ,IAAIF,IAAIjB,IAAI,EAAE;4BACZmB,YAAYjB,UAAU,GAAGA,QAAQ,CAAC,EAAEe,IAAIjB,IAAI,EAAE,GAAGiB,IAAIjB,IAAI;wBAC3D,OAAO;4BACLmB,YAAYjB;wBACd;wBACA,MAAMkB,YAAY5B,+BAA+ByB,IAAIxB,MAAM,IAAI,EAAE,EAAE0B;wBACnE,KAAK,MAAME,YAAYD,UAAW;4BAChCzB,OAAOW,GAAG,CAACe;wBACb;oBACF;oBACA;gBACF;QACF;IACF;IAEA,OAAO1B;AACT,EAAC"}