@payloadcms/figma 0.1.0-alpha.0 → 0.1.0-internal.e071575

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 (34) hide show
  1. package/dist/db-content-api/generated/content-api-types.d.ts +644 -3
  2. package/dist/db-content-api/index.d.ts +3 -0
  3. package/dist/db-content-api/index.js +68 -123
  4. package/dist/db-content-api/utilities/clientVersionHeaders.d.ts +7 -0
  5. package/dist/db-content-api/utilities/clientVersionHeaders.js +15 -0
  6. package/dist/db-content-api/utilities/data/atomicOperations.d.ts +16 -0
  7. package/dist/db-content-api/utilities/data/atomicOperations.js +48 -0
  8. package/dist/db-content-api/utilities/data/convertRelationshipIds.d.ts +25 -0
  9. package/dist/db-content-api/utilities/data/convertRelationshipIds.js +109 -0
  10. package/dist/db-content-api/utilities/data/index.js +71 -55
  11. package/dist/db-content-api/utilities/data/isLocaleMap.d.ts +10 -0
  12. package/dist/db-content-api/utilities/data/isLocaleMap.js +13 -0
  13. package/dist/db-content-api/utilities/data/resolveFieldLocalization.d.ts +18 -0
  14. package/dist/db-content-api/utilities/data/resolveFieldLocalization.js +21 -0
  15. package/dist/db-content-api/utilities/data/validateRelationships.js +19 -12
  16. package/dist/db-content-api/utilities/joins.d.ts +6 -8
  17. package/dist/db-content-api/utilities/joins.js +8 -21
  18. package/dist/db-content-api/utilities/schema/buildDocumentSchema.d.ts +21 -4
  19. package/dist/db-content-api/utilities/schema/buildDocumentSchema.js +118 -36
  20. package/dist/db-content-api/utilities/where.d.ts +2 -12
  21. package/dist/db-content-api/utilities/where.js +1 -12
  22. package/dist/plugin/build-config.js +5 -1
  23. package/dist/plugin/sandbox-upload-fetch.d.ts +30 -0
  24. package/dist/plugin/sandbox-upload-fetch.js +59 -0
  25. package/dist/utils/load-payload-config.d.ts +2 -2
  26. package/package.json +6 -5
  27. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts +0 -10
  28. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +0 -71
  29. package/dist/db-content-api/utilities/meta/buildMeta.d.ts +0 -41
  30. package/dist/db-content-api/utilities/meta/buildMeta.js +0 -39
  31. package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +0 -16
  32. package/dist/db-content-api/utilities/meta/buildPathTypes.js +0 -243
  33. package/dist/db-content-api/utilities/meta/buildUniquePaths.d.ts +0 -12
  34. package/dist/db-content-api/utilities/meta/buildUniquePaths.js +0 -60
@@ -1,243 +0,0 @@
1
- import { resolveBlocks } from '../resolveBlocks.js';
2
- /**
3
- * Extracts all field paths from a where clause recursively
4
- */ function extractPathsFromWhere(where, paths = new Set()) {
5
- if (!where || typeof where !== 'object') {
6
- return paths;
7
- }
8
- // Handle 'and' operator
9
- if ('and' in where && Array.isArray(where.and)) {
10
- for (const clause of where.and){
11
- extractPathsFromWhere(clause, paths);
12
- }
13
- return paths;
14
- }
15
- // Handle 'or' operator
16
- if ('or' in where && Array.isArray(where.or)) {
17
- for (const clause of where.or){
18
- extractPathsFromWhere(clause, paths);
19
- }
20
- return paths;
21
- }
22
- // Handle regular conditions - keys are field paths
23
- for(const key in where){
24
- if (key === 'and' || key === 'or') {
25
- continue;
26
- }
27
- // Add the path
28
- paths.add(key.replace(/__/g, '.'));
29
- // Check if the value is a nested where clause (for relationships)
30
- const value = where[key];
31
- if (value && typeof value === 'object' && !('equals' in value) && !('in' in value)) {
32
- // Might be a nested where, recurse
33
- extractPathsFromWhere(value, paths);
34
- }
35
- }
36
- return paths;
37
- }
38
- /**
39
- * Determines the type of a field based on its configuration.
40
- * Returns PathTypeValue for fields that need special handling in Content API queries.
41
- */ function getFieldType(field) {
42
- // Array field
43
- if (field.type === 'array') {
44
- return 'array';
45
- }
46
- // Blocks field (array of objects)
47
- if (field.type === 'blocks') {
48
- return 'array';
49
- }
50
- // Relationship field - always include for JOIN support
51
- if (field.type === 'relationship') {
52
- const { hasMany = false, relationTo: collection } = field;
53
- return {
54
- type: 'relationship',
55
- collection,
56
- hasMany
57
- };
58
- }
59
- // Upload field - treated like relationship
60
- if (field.type === 'upload') {
61
- const { hasMany = false, relationTo: collection } = field;
62
- return {
63
- type: 'relationship',
64
- collection,
65
- hasMany
66
- };
67
- }
68
- // Join field - virtual reverse lookup
69
- if (field.type === 'join') {
70
- const { collection, on } = field;
71
- return {
72
- type: 'join',
73
- collection,
74
- hasMany: true,
75
- on
76
- };
77
- }
78
- // Text field with hasMany (array of strings)
79
- if (field.type === 'text' && 'hasMany' in field && field.hasMany) {
80
- return 'array';
81
- }
82
- // Number field with hasMany (array of numbers)
83
- if (field.type === 'number' && 'hasMany' in field && field.hasMany) {
84
- return 'array';
85
- }
86
- // Select field with hasMany (array)
87
- if (field.type === 'select' && 'hasMany' in field && field.hasMany) {
88
- return 'array';
89
- }
90
- // Objects (group, collapsible, row, tabs) don't need traversal
91
- return null;
92
- }
93
- /**
94
- * Finds a field in the collection schema by its path.
95
- * Supports nested paths like "access.read.users".
96
- * For localized array/blocks fields, locale key segments (e.g. "en") are skipped transparently,
97
- * so "localizedBlocks.en.richText" resolves to the richText field inside localizedBlocks.
98
- */ function findFieldByPath(payload, collectionSlug, path) {
99
- const collectionConfig = payload.config.collections.find((c)=>c.slug === collectionSlug);
100
- if (!collectionConfig) {
101
- return undefined;
102
- }
103
- const localeCodes = payload.config.localization ? payload.config.localization.localeCodes : [];
104
- const pathSegments = path.split('.');
105
- // Walk through the path segments to find the field
106
- let currentFields = collectionConfig.fields;
107
- let currentField = undefined;
108
- for(let i = 0; i < pathSegments.length; i++){
109
- const segment = pathSegments[i];
110
- // If this segment is a locale key for the previously found localized array/blocks field,
111
- // skip it transparently (the locale key is the wrapping object key, not a real field).
112
- if (localeCodes.includes(segment) && currentField && 'localized' in currentField && currentField.localized && (currentField.type === 'blocks' || currentField.type === 'array')) {
113
- if (i === pathSegments.length - 1) {
114
- // Last segment is a locale key → return the localized field (represents locale-specific array)
115
- return currentField;
116
- }
117
- continue;
118
- }
119
- // First try to find a direct match
120
- currentField = currentFields.find((f)=>'name' in f && f.name === segment);
121
- // If not found, check if any unnamed container fields (collapsible, row) contain it
122
- if (!currentField) {
123
- for (const field of currentFields){
124
- if (!('name' in field) || !field.name) {
125
- // This is an unnamed field, check its contents
126
- if ('fields' in field && field.type === 'collapsible' || 'fields' in field && field.type === 'row' || 'fields' in field && field.type === 'group') {
127
- currentField = field.fields.find((f)=>'name' in f && f.name === segment);
128
- if (currentField) {
129
- break;
130
- }
131
- } else if ('tabs' in field && field.type === 'tabs') {
132
- // Check all tabs
133
- for (const tab of field.tabs){
134
- // Named tab: the tab name itself is a path segment (acts like a group)
135
- if ('name' in tab && tab.name === segment) {
136
- currentField = {
137
- name: tab.name,
138
- type: 'group',
139
- fields: tab.fields
140
- };
141
- break;
142
- }
143
- // Unnamed tab: search its fields for the segment
144
- const found = tab.fields.find((f)=>'name' in f && f.name === segment);
145
- if (found) {
146
- currentField = found;
147
- break;
148
- }
149
- }
150
- if (currentField) {
151
- break;
152
- }
153
- }
154
- }
155
- }
156
- }
157
- if (!currentField) {
158
- return undefined;
159
- }
160
- // If we're not at the end, get nested fields
161
- if (i < pathSegments.length - 1) {
162
- if (currentField.type === 'group' && 'fields' in currentField) {
163
- currentFields = currentField.fields;
164
- } else if (currentField.type === 'array' && 'fields' in currentField) {
165
- currentFields = currentField.fields;
166
- } else if (currentField.type === 'blocks' && 'blocks' in currentField) {
167
- // Collect all fields from all block definitions to continue traversal
168
- const allBlockFields = [];
169
- for (const block of resolveBlocks(currentField.blocks, payload.config.blocks)){
170
- allBlockFields.push(...block.fields);
171
- }
172
- currentFields = allBlockFields;
173
- } else if ((currentField.type === 'relationship' || currentField.type === 'upload') && typeof currentField.relationTo === 'string') {
174
- // Traverse into the related collection's fields
175
- const { relationTo } = currentField;
176
- const relatedConfig = payload.config.collections.find((c)=>c.slug === relationTo);
177
- if (relatedConfig) {
178
- currentFields = relatedConfig.fields;
179
- } else {
180
- return undefined;
181
- }
182
- } else {
183
- // Field doesn't have nested fields, can't continue
184
- return undefined;
185
- }
186
- }
187
- }
188
- return currentField;
189
- }
190
- /**
191
- * Builds pathTypes metadata for Content API request.
192
- * Returns a record of paths with their types for proper query generation.
193
- *
194
- * Includes:
195
- * - Array fields (type: "array")
196
- * - Relationship fields (type: { type: "relationship", collection, hasMany })
197
- * - Join fields (type: { type: "join", collection, hasMany, on })
198
- *
199
- * Localized array/blocks fields (stored as locale maps) are handled specially:
200
- * - The localized field itself is NOT marked as 'array' (it's a locale map object)
201
- * - The locale-specific path (e.g. "localizedBlocks.en") IS marked as 'array'
202
- */ export function buildPathTypes(payload, collectionSlug, where) {
203
- if (!where) {
204
- return {};
205
- }
206
- const localeCodes = payload.config.localization ? payload.config.localization.localeCodes : [];
207
- const pathTypes = {};
208
- const paths = extractPathsFromWhere(where);
209
- for (const path of paths){
210
- // For each path, we need to check all segments to see if any intermediate ones are arrays/relationships
211
- const segments = path.split('.');
212
- for(let i = 0; i < segments.length; i++){
213
- const partialPath = segments.slice(0, i + 1).join('.');
214
- // Skip if we already have this path
215
- if (partialPath in pathTypes) {
216
- continue;
217
- }
218
- // If the current segment is a locale code and the parent field is a localized array/blocks,
219
- // mark this locale-specific path as 'array' (the per-locale content is the actual array).
220
- if (i > 0 && localeCodes.includes(segments[i])) {
221
- const parentPath = segments.slice(0, i).join('.');
222
- const parentField = findFieldByPath(payload, collectionSlug, parentPath);
223
- if (parentField && 'localized' in parentField && parentField.localized && (parentField.type === 'blocks' || parentField.type === 'array')) {
224
- pathTypes[partialPath] = 'array';
225
- continue;
226
- }
227
- }
228
- const field = findFieldByPath(payload, collectionSlug, partialPath);
229
- if (field) {
230
- // Localized array/blocks fields are stored as locale maps (not arrays).
231
- // Skip them here — the locale-specific path (e.g. "localizedBlocks.en") is marked above.
232
- if ('localized' in field && field.localized && (field.type === 'blocks' || field.type === 'array')) {
233
- continue;
234
- }
235
- const fieldType = getFieldType(field);
236
- if (fieldType !== null) {
237
- pathTypes[partialPath] = fieldType;
238
- }
239
- }
240
- }
241
- }
242
- return pathTypes;
243
- }
@@ -1,12 +0,0 @@
1
- import type { Payload } from 'payload';
2
- import type { components } from '../../generated/content-api-types.js';
3
- type UniquePath = components['schemas']['UniquePath'];
4
- /**
5
- * Builds a UniquePath[] from the collection's field config by collecting
6
- * all fields with `unique: true` that have a non-null value in the data.
7
- *
8
- * Fields with null/undefined values are excluded to match sparse unique index
9
- * behavior (multiple documents can have null for a unique field).
10
- */
11
- export declare function buildUniquePaths(payload: Payload, collectionSlug: string, data: Record<string, unknown>): UniquePath[];
12
- export {};
@@ -1,60 +0,0 @@
1
- /**
2
- * Builds a UniquePath[] from the collection's field config by collecting
3
- * all fields with `unique: true` that have a non-null value in the data.
4
- *
5
- * Fields with null/undefined values are excluded to match sparse unique index
6
- * behavior (multiple documents can have null for a unique field).
7
- */ export function buildUniquePaths(payload, collectionSlug, data) {
8
- const isGlobal = collectionSlug.startsWith('_global-');
9
- const actualSlug = isGlobal ? collectionSlug.substring(8) : collectionSlug;
10
- const config = isGlobal ? payload.config.globals?.find((g)=>g.slug === actualSlug) : payload.config.collections.find((c)=>c.slug === actualSlug);
11
- if (!config?.fields) {
12
- return [];
13
- }
14
- const unique = [];
15
- collectUniqueFields(config.fields, '', data, unique);
16
- return unique;
17
- }
18
- function getValueAtPath(data, path) {
19
- const segments = path.split('.');
20
- let current = data;
21
- for (const segment of segments){
22
- if (current == null || typeof current !== 'object') {
23
- return undefined;
24
- }
25
- current = current[segment];
26
- }
27
- return current;
28
- }
29
- function collectUniqueFields(fields, prefix, data, result) {
30
- for (const field of fields){
31
- if (field.type === 'row' || field.type === 'collapsible') {
32
- collectUniqueFields(field.fields, prefix, data, result);
33
- continue;
34
- }
35
- if (field.type === 'tabs') {
36
- for (const tab of field.tabs){
37
- const tabPrefix = 'name' in tab && tab.name ? `${prefix}${tab.name}.` : prefix;
38
- collectUniqueFields(tab.fields, tabPrefix, data, result);
39
- }
40
- continue;
41
- }
42
- if (!('name' in field) || !field.name) {
43
- continue;
44
- }
45
- const path = prefix + field.name;
46
- if ('unique' in field && field.unique) {
47
- const value = getValueAtPath(data, path);
48
- if (value != null) {
49
- result.push({
50
- paths: [
51
- path
52
- ]
53
- });
54
- }
55
- }
56
- if (field.type === 'group' && 'fields' in field) {
57
- collectUniqueFields(field.fields, `${path}.`, data, result);
58
- }
59
- }
60
- }