@payloadcms/figma 0.0.1-alpha.30 → 0.0.1-alpha.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/db-content-api/index.d.ts.map +1 -1
- package/dist/db-content-api/index.js +29 -8
- package/dist/db-content-api/index.js.map +1 -1
- package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts.map +1 -1
- package/dist/db-content-api/temp-utilities/unwrapDocument.js +11 -3
- package/dist/db-content-api/temp-utilities/unwrapDocument.js.map +1 -1
- package/dist/db-content-api/utilities/data/applyDefaults.d.ts +7 -0
- package/dist/db-content-api/utilities/data/applyDefaults.d.ts.map +1 -0
- package/dist/db-content-api/utilities/data/applyDefaults.js +59 -0
- package/dist/db-content-api/utilities/data/applyDefaults.js.map +1 -0
- package/dist/db-content-api/utilities/data/castFieldValue.d.ts +11 -0
- package/dist/db-content-api/utilities/data/castFieldValue.d.ts.map +1 -0
- package/dist/db-content-api/utilities/data/castFieldValue.js +66 -0
- package/dist/db-content-api/utilities/data/castFieldValue.js.map +1 -0
- package/dist/db-content-api/utilities/{data.d.ts → data/index.d.ts} +7 -3
- package/dist/db-content-api/utilities/data/index.d.ts.map +1 -0
- package/dist/db-content-api/utilities/{data.js → data/index.js} +54 -6
- package/dist/db-content-api/utilities/data/index.js.map +1 -0
- package/dist/db-content-api/utilities/data/stripFields.d.ts +48 -0
- package/dist/db-content-api/utilities/data/stripFields.d.ts.map +1 -0
- package/dist/db-content-api/utilities/data/stripFields.js +195 -0
- package/dist/db-content-api/utilities/data/stripFields.js.map +1 -0
- package/dist/db-content-api/utilities/where.d.ts.map +1 -1
- package/dist/db-content-api/utilities/where.js +46 -2
- package/dist/db-content-api/utilities/where.js.map +1 -1
- package/dist/exports/client.d.ts +1 -0
- package/dist/exports/client.d.ts.map +1 -1
- package/dist/exports/client.js +1 -0
- package/dist/exports/client.js.map +1 -1
- package/dist/plugin/build-config.d.ts.map +1 -1
- package/dist/plugin/build-config.js +14 -0
- package/dist/plugin/build-config.js.map +1 -1
- package/dist/storage-content-api/client-uploads/ClientUploadHandler.d.ts +9 -0
- package/dist/storage-content-api/client-uploads/ClientUploadHandler.d.ts.map +1 -0
- package/dist/storage-content-api/client-uploads/ClientUploadHandler.js +42 -0
- package/dist/storage-content-api/client-uploads/ClientUploadHandler.js.map +1 -0
- package/dist/storage-content-api/client-uploads/generateSignedURL.d.ts +13 -0
- package/dist/storage-content-api/client-uploads/generateSignedURL.d.ts.map +1 -0
- package/dist/storage-content-api/client-uploads/generateSignedURL.js +31 -0
- package/dist/storage-content-api/client-uploads/generateSignedURL.js.map +1 -0
- package/dist/storage-content-api/handleUpload.d.ts.map +1 -1
- package/dist/storage-content-api/handleUpload.js +13 -3
- package/dist/storage-content-api/handleUpload.js.map +1 -1
- package/dist/storage-content-api/staticHandler.d.ts.map +1 -1
- package/dist/storage-content-api/staticHandler.js +22 -2
- package/dist/storage-content-api/staticHandler.js.map +1 -1
- package/dist/utils/payload-config-modifier.d.ts.map +1 -1
- package/dist/utils/payload-config-modifier.js +16 -0
- package/dist/utils/payload-config-modifier.js.map +1 -1
- package/package.json +5 -2
- package/dist/db-content-api/utilities/data.d.ts.map +0 -1
- package/dist/db-content-api/utilities/data.js.map +0 -1
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import { traverseFields } from 'payload';
|
|
1
|
+
import { flattenAllFields, traverseFields } from 'payload';
|
|
2
|
+
import { applyDefaults } from './applyDefaults.js';
|
|
3
|
+
import { castFieldValue } from './castFieldValue.js';
|
|
4
|
+
import { stripFields } from './stripFields.js';
|
|
2
5
|
/**
|
|
3
6
|
* Transform data before sending to Content API (WRITE operations)
|
|
4
7
|
*
|
|
5
8
|
* Conversions applied:
|
|
9
|
+
* - Default values: Apply static defaults for undefined fields (when applyDefaults=true)
|
|
10
|
+
* - Type casting: Convert values to match field types (e.g., number -> string for text fields)
|
|
6
11
|
* - RichText fields: Objects -> JSON strings
|
|
7
12
|
*
|
|
8
13
|
* Note: Date fields are automatically converted to ISO strings by JSON.stringify()
|
|
9
|
-
*/ export function dataToContentAPI(payload, collectionSlug, data) {
|
|
14
|
+
*/ export function dataToContentAPI(payload, collectionSlug, data, options) {
|
|
10
15
|
if (!data || typeof data !== 'object') {
|
|
11
16
|
return data;
|
|
12
17
|
}
|
|
@@ -19,7 +24,12 @@ import { traverseFields } from 'payload';
|
|
|
19
24
|
if (!collectionConfig?.fields) {
|
|
20
25
|
return transformed;
|
|
21
26
|
}
|
|
22
|
-
//
|
|
27
|
+
// Apply static defaults recursively to handle nested structures (arrays, groups)
|
|
28
|
+
// This must happen before traverseFields to ensure defaults are in place
|
|
29
|
+
if (options?.applyDefaults) {
|
|
30
|
+
applyDefaults(transformed, collectionConfig.fields);
|
|
31
|
+
}
|
|
32
|
+
// Use Payload's traverseFields to iterate over all fields for transformations
|
|
23
33
|
const callback = ({ field, ref })=>{
|
|
24
34
|
if (!('name' in field) || !field.name) {
|
|
25
35
|
return;
|
|
@@ -28,8 +38,13 @@ import { traverseFields } from 'payload';
|
|
|
28
38
|
return;
|
|
29
39
|
}
|
|
30
40
|
const current = ref;
|
|
31
|
-
|
|
41
|
+
let value = current[field.name];
|
|
42
|
+
// Transform existing values
|
|
32
43
|
if (value !== null && value !== undefined) {
|
|
44
|
+
// Step 1: Apply type casting (e.g., number -> string for text fields)
|
|
45
|
+
value = castFieldValue(field, value);
|
|
46
|
+
current[field.name] = value;
|
|
47
|
+
// Step 2: Apply Content API specific transformations
|
|
33
48
|
// RichText: object -> JSON string
|
|
34
49
|
if (field.type === 'richText' && typeof value !== 'string') {
|
|
35
50
|
current[field.name] = JSON.stringify(value);
|
|
@@ -42,6 +57,23 @@ import { traverseFields } from 'payload';
|
|
|
42
57
|
fields: collectionConfig.fields,
|
|
43
58
|
ref: transformed
|
|
44
59
|
});
|
|
60
|
+
stripFields({
|
|
61
|
+
config: payload.config,
|
|
62
|
+
data: transformed,
|
|
63
|
+
fields: flattenAllFields({
|
|
64
|
+
cache: true,
|
|
65
|
+
fields: collectionConfig.fields
|
|
66
|
+
}),
|
|
67
|
+
reservedKeys: [
|
|
68
|
+
'id',
|
|
69
|
+
'globalType'
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
// Convert numeric ID to string for Content API
|
|
73
|
+
const customIDType = payload.collections?.[collectionSlug]?.customIDType;
|
|
74
|
+
if (customIDType === 'number') {
|
|
75
|
+
transformed.id = String(transformed.id);
|
|
76
|
+
}
|
|
45
77
|
return transformed;
|
|
46
78
|
}
|
|
47
79
|
/**
|
|
@@ -96,6 +128,23 @@ import { traverseFields } from 'payload';
|
|
|
96
128
|
fields: collectionConfig.fields,
|
|
97
129
|
ref: transformed
|
|
98
130
|
});
|
|
131
|
+
// Convert string ID to number if collection uses numeric custom ID
|
|
132
|
+
const customIDType = payload.collections?.[collectionSlug]?.customIDType;
|
|
133
|
+
if (customIDType === 'number') {
|
|
134
|
+
transformed.id = Number(transformed.id);
|
|
135
|
+
}
|
|
136
|
+
stripFields({
|
|
137
|
+
config: payload.config,
|
|
138
|
+
data: transformed,
|
|
139
|
+
fields: flattenAllFields({
|
|
140
|
+
cache: true,
|
|
141
|
+
fields: collectionConfig.fields
|
|
142
|
+
}),
|
|
143
|
+
reservedKeys: [
|
|
144
|
+
'id',
|
|
145
|
+
'globalType'
|
|
146
|
+
]
|
|
147
|
+
});
|
|
99
148
|
// Handle auth-specific fields that aren't in the field schema
|
|
100
149
|
// When these fields are null in DB, Content API omits them from response (undefined)
|
|
101
150
|
// But Payload expects them to be null, not undefined
|
|
@@ -107,7 +156,6 @@ import { traverseFields } from 'payload';
|
|
|
107
156
|
];
|
|
108
157
|
for (const fieldName of authFields){
|
|
109
158
|
if (!(fieldName in transformed)) {
|
|
110
|
-
;
|
|
111
159
|
transformed[fieldName] = null;
|
|
112
160
|
}
|
|
113
161
|
}
|
|
@@ -115,4 +163,4 @@ import { traverseFields } from 'payload';
|
|
|
115
163
|
return transformed;
|
|
116
164
|
}
|
|
117
165
|
|
|
118
|
-
//# sourceMappingURL=
|
|
166
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/db-content-api/utilities/data/index.ts"],"sourcesContent":["import type { CollectionConfig, GlobalConfig, Payload, TraverseFieldsCallback } from 'payload'\n\nimport { flattenAllFields, traverseFields } from 'payload'\n\nimport type { components } from '../../generated/content-api-types.js'\n\nimport { applyDefaults } from './applyDefaults.js'\nimport { castFieldValue } from './castFieldValue.js'\nimport { stripFields } from './stripFields.js'\n\ntype DataWithOperations = components['schemas']['DataWithOperations']\n\n/**\n * Transform data before sending to Content API (WRITE operations)\n *\n * Conversions applied:\n * - Default values: Apply static defaults for undefined fields (when applyDefaults=true)\n * - Type casting: Convert values to match field types (e.g., number -> string for text fields)\n * - RichText fields: Objects -> JSON strings\n *\n * Note: Date fields are automatically converted to ISO strings by JSON.stringify()\n */\nexport function dataToContentAPI(\n payload: Payload,\n collectionSlug: string,\n data: unknown,\n options?: { applyDefaults?: boolean },\n): DataWithOperations {\n if (!data || typeof data !== 'object') {\n return data as DataWithOperations\n }\n\n // Deep clone to avoid mutating original data\n const transformed = JSON.parse(JSON.stringify(data))\n\n // Get collection config\n const isGlobal = collectionSlug.startsWith('_global-')\n const actualSlug = isGlobal ? collectionSlug.substring(8) : collectionSlug\n const collectionConfig: CollectionConfig | GlobalConfig | undefined = isGlobal\n ? payload.config.globals?.find((g) => g.slug === actualSlug)\n : payload.config.collections.find((c) => c.slug === actualSlug)\n\n if (!collectionConfig?.fields) {\n return transformed as DataWithOperations\n }\n\n // Apply static defaults recursively to handle nested structures (arrays, groups)\n // This must happen before traverseFields to ensure defaults are in place\n if (options?.applyDefaults) {\n applyDefaults(transformed, collectionConfig.fields)\n }\n\n // Use Payload's traverseFields to iterate over all fields for transformations\n const callback: TraverseFieldsCallback = ({ field, ref }) => {\n if (!('name' in field) || !field.name) {\n return\n }\n if (!ref || typeof ref !== 'object') {\n return\n }\n\n const current = ref as Record<string, unknown>\n let value = current[field.name]\n\n // Transform existing values\n if (value !== null && value !== undefined) {\n // Step 1: Apply type casting (e.g., number -> string for text fields)\n value = castFieldValue(field, value)\n current[field.name] = value\n\n // Step 2: Apply Content API specific transformations\n // RichText: object -> JSON string\n if (field.type === 'richText' && typeof value !== 'string') {\n current[field.name] = JSON.stringify(value)\n }\n // Date fields are already handled by JSON.stringify() which converts Date -> ISO string\n }\n }\n\n traverseFields({ callback, fields: collectionConfig.fields, ref: transformed })\n\n stripFields({\n config: payload.config,\n data: transformed,\n fields: flattenAllFields({ cache: true, fields: collectionConfig.fields }),\n reservedKeys: ['id', 'globalType'],\n })\n\n // Convert numeric ID to string for Content API\n const customIDType = payload.collections?.[collectionSlug]?.customIDType\n if (customIDType === 'number') {\n transformed.id = String(transformed.id)\n }\n\n return transformed as DataWithOperations\n}\n\n/**\n * Transform data received from Content API (READ operations)\n *\n * Conversions applied:\n * - RichText fields: JSON strings -> Objects\n *\n * Note: Date fields come as ISO strings from Content API and stay as strings\n * (matching MongoDB and other adapters' behavior)\n */\nexport function dataFromContentAPI(\n payload: Payload,\n collectionSlug: string,\n data: unknown,\n): unknown {\n if (!data || typeof data !== 'object') {\n return data\n }\n\n // Deep clone to avoid mutating original data\n const transformed = JSON.parse(JSON.stringify(data))\n\n // Get collection config\n const isGlobal = collectionSlug.startsWith('_global-')\n const actualSlug = isGlobal ? collectionSlug.substring(8) : collectionSlug\n const collectionConfig: CollectionConfig | GlobalConfig | undefined = isGlobal\n ? payload.config.globals?.find((g) => g.slug === actualSlug)\n : payload.config.collections.find((c) => c.slug === actualSlug)\n\n if (!collectionConfig?.fields) {\n return transformed\n }\n\n // Use Payload's traverseFields to iterate over all fields\n const callback: TraverseFieldsCallback = ({ field, parentPath, ref }) => {\n if (!('name' in field) || !field.name) {\n return\n }\n if (!ref || typeof ref !== 'object') {\n return\n }\n\n const current = ref as Record<string, unknown>\n const value = current[field.name]\n\n if (value !== null && value !== undefined) {\n // RichText: JSON string -> object\n if (field.type === 'richText' && typeof value === 'string') {\n try {\n current[field.name] = JSON.parse(value)\n } catch (error) {\n const fieldPath = parentPath ? `${parentPath}.${field.name}` : field.name\n payload.logger.warn({\n err: error instanceof Error ? error : new Error(String(error)),\n msg: `Failed to parse richtext field '${fieldPath}' in collection '${collectionSlug}'`,\n })\n }\n }\n // Date fields: Already ISO strings from Content API, no conversion needed\n }\n }\n\n traverseFields({ callback, fields: collectionConfig.fields, ref: transformed })\n\n // Convert string ID to number if collection uses numeric custom ID\n const customIDType = payload.collections?.[collectionSlug]?.customIDType\n if (customIDType === 'number') {\n transformed.id = Number(transformed.id)\n }\n\n stripFields({\n config: payload.config,\n data: transformed,\n fields: flattenAllFields({ cache: true, fields: collectionConfig.fields }),\n reservedKeys: ['id', 'globalType'],\n })\n\n // Handle auth-specific fields that aren't in the field schema\n // When these fields are null in DB, Content API omits them from response (undefined)\n // But Payload expects them to be null, not undefined\n // Only add them if the collection has auth enabled\n if ('auth' in collectionConfig && collectionConfig.auth) {\n const authFields = ['resetPasswordExpiration', 'lockUntil']\n for (const fieldName of authFields) {\n if (!(fieldName in transformed)) {\n transformed[fieldName] = null\n }\n }\n }\n\n return transformed\n}\n"],"names":["flattenAllFields","traverseFields","applyDefaults","castFieldValue","stripFields","dataToContentAPI","payload","collectionSlug","data","options","transformed","JSON","parse","stringify","isGlobal","startsWith","actualSlug","substring","collectionConfig","config","globals","find","g","slug","collections","c","fields","callback","field","ref","name","current","value","undefined","type","cache","reservedKeys","customIDType","id","String","dataFromContentAPI","parentPath","error","fieldPath","logger","warn","err","Error","msg","Number","auth","authFields","fieldName"],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { FlattenedField, SanitizedConfig } from 'payload';
|
|
2
|
+
/**
|
|
3
|
+
* Strips fields from data that are not defined in the schema or are invalid.
|
|
4
|
+
*
|
|
5
|
+
* This function was copied from the MongoDB adapter's implementation:
|
|
6
|
+
* @see packages/db-mongodb/src/utilities/transform.ts (stripFields function)
|
|
7
|
+
*
|
|
8
|
+
* @description
|
|
9
|
+
* This utility performs deep sanitization of document data by:
|
|
10
|
+
* 1. **Removing undefined fields**: Strips any field not present in the collection's schema
|
|
11
|
+
* (e.g., sensitive fields like `password`, `apiKey`, or any extra fields not in config)
|
|
12
|
+
* 2. **Removing invalid locales**: Deletes locale keys that don't exist in `config.localization.localeCodes`
|
|
13
|
+
* (e.g., if data contains `{ "es-MX": "..." }` but only `"en"` is configured)
|
|
14
|
+
* 3. **Removing invalid blocks**: Filters out blocks with unknown `blockType` values
|
|
15
|
+
* (prevents data corruption from blocks that don't exist in the schema)
|
|
16
|
+
* 4. **Recursive sanitization**: Processes nested structures (arrays, groups, blocks, localized fields)
|
|
17
|
+
* to ensure deep data integrity
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* Unlike MongoDB's adapter which uses Mongoose schemas with `strict: true` (rejecting extra fields
|
|
21
|
+
* on write), Content API uses flexible JSONB storage that accepts any fields. Therefore, this
|
|
22
|
+
* function is called on **both read and write operations** to ensure data consistency.
|
|
23
|
+
*
|
|
24
|
+
* The MongoDB adapter also supports an `allowAdditionalKeys` option that allows reading/writing
|
|
25
|
+
* fields not in the schema. For now, Content API does not support this feature - we always
|
|
26
|
+
* sanitize data. If users request this functionality in the future, we can consider adding it.
|
|
27
|
+
*
|
|
28
|
+
* @todo
|
|
29
|
+
* 1. Consider moving this utility to `payload/shared` so both MongoDB and Content API adapters
|
|
30
|
+
* can use the same implementation, reducing code duplication and maintenance burden.
|
|
31
|
+
*
|
|
32
|
+
* 2. Performance optimization: This function iterates through all fields recursively.
|
|
33
|
+
* The `dataToContentAPI` and `dataFromContentAPI` functions in
|
|
34
|
+
* `packages/figma/src/db-content-api/utilities/data.ts` also iterate through fields
|
|
35
|
+
* to transform richText (object ↔ JSON string), custom IDs (number ↔ string), and dates.
|
|
36
|
+
* Consider combining both traversals into a single abstraction to avoid iterating twice.
|
|
37
|
+
*
|
|
38
|
+
* 3. Feature parity: MongoDB adapter has `allowAdditionalKeys` option. We currently always
|
|
39
|
+
* strip additional keys, but could add this as a configurable option if users need it.
|
|
40
|
+
*/
|
|
41
|
+
export declare const stripFields: ({ config, data, fields, parentIsLocalized, reservedKeys, }: {
|
|
42
|
+
config: SanitizedConfig;
|
|
43
|
+
data: any;
|
|
44
|
+
fields: FlattenedField[];
|
|
45
|
+
parentIsLocalized?: boolean;
|
|
46
|
+
reservedKeys?: string[];
|
|
47
|
+
}) => void;
|
|
48
|
+
//# sourceMappingURL=stripFields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripFields.d.ts","sourceRoot":"","sources":["../../../../src/db-content-api/utilities/data/stripFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAI9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,WAAW,+DAMrB;IACD,MAAM,EAAE,eAAe,CAAA;IAEvB,IAAI,EAAE,GAAG,CAAA;IACT,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACxB,SAmLA,CAAA"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { fieldShouldBeLocalized } from 'payload/shared';
|
|
2
|
+
/**
|
|
3
|
+
* Strips fields from data that are not defined in the schema or are invalid.
|
|
4
|
+
*
|
|
5
|
+
* This function was copied from the MongoDB adapter's implementation:
|
|
6
|
+
* @see packages/db-mongodb/src/utilities/transform.ts (stripFields function)
|
|
7
|
+
*
|
|
8
|
+
* @description
|
|
9
|
+
* This utility performs deep sanitization of document data by:
|
|
10
|
+
* 1. **Removing undefined fields**: Strips any field not present in the collection's schema
|
|
11
|
+
* (e.g., sensitive fields like `password`, `apiKey`, or any extra fields not in config)
|
|
12
|
+
* 2. **Removing invalid locales**: Deletes locale keys that don't exist in `config.localization.localeCodes`
|
|
13
|
+
* (e.g., if data contains `{ "es-MX": "..." }` but only `"en"` is configured)
|
|
14
|
+
* 3. **Removing invalid blocks**: Filters out blocks with unknown `blockType` values
|
|
15
|
+
* (prevents data corruption from blocks that don't exist in the schema)
|
|
16
|
+
* 4. **Recursive sanitization**: Processes nested structures (arrays, groups, blocks, localized fields)
|
|
17
|
+
* to ensure deep data integrity
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* Unlike MongoDB's adapter which uses Mongoose schemas with `strict: true` (rejecting extra fields
|
|
21
|
+
* on write), Content API uses flexible JSONB storage that accepts any fields. Therefore, this
|
|
22
|
+
* function is called on **both read and write operations** to ensure data consistency.
|
|
23
|
+
*
|
|
24
|
+
* The MongoDB adapter also supports an `allowAdditionalKeys` option that allows reading/writing
|
|
25
|
+
* fields not in the schema. For now, Content API does not support this feature - we always
|
|
26
|
+
* sanitize data. If users request this functionality in the future, we can consider adding it.
|
|
27
|
+
*
|
|
28
|
+
* @todo
|
|
29
|
+
* 1. Consider moving this utility to `payload/shared` so both MongoDB and Content API adapters
|
|
30
|
+
* can use the same implementation, reducing code duplication and maintenance burden.
|
|
31
|
+
*
|
|
32
|
+
* 2. Performance optimization: This function iterates through all fields recursively.
|
|
33
|
+
* The `dataToContentAPI` and `dataFromContentAPI` functions in
|
|
34
|
+
* `packages/figma/src/db-content-api/utilities/data.ts` also iterate through fields
|
|
35
|
+
* to transform richText (object ↔ JSON string), custom IDs (number ↔ string), and dates.
|
|
36
|
+
* Consider combining both traversals into a single abstraction to avoid iterating twice.
|
|
37
|
+
*
|
|
38
|
+
* 3. Feature parity: MongoDB adapter has `allowAdditionalKeys` option. We currently always
|
|
39
|
+
* strip additional keys, but could add this as a configurable option if users need it.
|
|
40
|
+
*/ export const stripFields = ({ config, data, fields, parentIsLocalized = false, reservedKeys = [] })=>{
|
|
41
|
+
for(const k in data){
|
|
42
|
+
if (!fields.some((field)=>field.name === k) && !reservedKeys.includes(k)) {
|
|
43
|
+
delete data[k];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
for (const field of fields){
|
|
47
|
+
reservedKeys = [];
|
|
48
|
+
const fieldData = data[field.name];
|
|
49
|
+
if (!fieldData || typeof fieldData !== 'object') {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const shouldLocalizeField = fieldShouldBeLocalized({
|
|
53
|
+
field,
|
|
54
|
+
parentIsLocalized
|
|
55
|
+
});
|
|
56
|
+
if (field.type === 'blocks') {
|
|
57
|
+
reservedKeys.push('blockType');
|
|
58
|
+
}
|
|
59
|
+
if ('flattenedFields' in field || 'blocks' in field) {
|
|
60
|
+
if (shouldLocalizeField && config.localization) {
|
|
61
|
+
for(const localeKey in fieldData){
|
|
62
|
+
if (!config.localization.localeCodes.some((code)=>code === localeKey)) {
|
|
63
|
+
delete fieldData[localeKey];
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const localeData = fieldData[localeKey];
|
|
67
|
+
if (!localeData || typeof localeData !== 'object') {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (field.type === 'array' || field.type === 'blocks') {
|
|
71
|
+
if (!Array.isArray(localeData)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
let hasNull = false;
|
|
75
|
+
for(let i = 0; i < localeData.length; i++){
|
|
76
|
+
const data = localeData[i];
|
|
77
|
+
let fields = null;
|
|
78
|
+
if (field.type === 'array') {
|
|
79
|
+
fields = field.flattenedFields;
|
|
80
|
+
} else {
|
|
81
|
+
let maybeBlock = undefined;
|
|
82
|
+
if (field.blockReferences) {
|
|
83
|
+
const maybeBlockReference = field.blockReferences.find((each)=>{
|
|
84
|
+
const slug = typeof each === 'string' ? each : each.slug;
|
|
85
|
+
return slug === data.blockType;
|
|
86
|
+
});
|
|
87
|
+
if (maybeBlockReference) {
|
|
88
|
+
if (typeof maybeBlockReference === 'object') {
|
|
89
|
+
maybeBlock = maybeBlockReference;
|
|
90
|
+
} else {
|
|
91
|
+
maybeBlock = config.blocks?.find((each)=>each.slug === maybeBlockReference);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (!maybeBlock) {
|
|
96
|
+
maybeBlock = field.blocks.find((each)=>each.slug === data.blockType);
|
|
97
|
+
}
|
|
98
|
+
if (maybeBlock) {
|
|
99
|
+
fields = maybeBlock.flattenedFields;
|
|
100
|
+
} else {
|
|
101
|
+
localeData[i] = null;
|
|
102
|
+
hasNull = true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!fields) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
stripFields({
|
|
109
|
+
config,
|
|
110
|
+
data,
|
|
111
|
+
fields,
|
|
112
|
+
parentIsLocalized: parentIsLocalized || field.localized,
|
|
113
|
+
reservedKeys
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
if (hasNull) {
|
|
117
|
+
fieldData[localeKey] = localeData.filter(Boolean);
|
|
118
|
+
}
|
|
119
|
+
continue;
|
|
120
|
+
} else {
|
|
121
|
+
stripFields({
|
|
122
|
+
config,
|
|
123
|
+
data: localeData,
|
|
124
|
+
fields: field.flattenedFields,
|
|
125
|
+
parentIsLocalized: parentIsLocalized || field.localized,
|
|
126
|
+
reservedKeys
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (field.type === 'array' || field.type === 'blocks') {
|
|
133
|
+
if (!Array.isArray(fieldData)) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
let hasNull = false;
|
|
137
|
+
for(let i = 0; i < fieldData.length; i++){
|
|
138
|
+
const data = fieldData[i];
|
|
139
|
+
let fields = null;
|
|
140
|
+
if (field.type === 'array') {
|
|
141
|
+
fields = field.flattenedFields;
|
|
142
|
+
} else {
|
|
143
|
+
let maybeBlock = undefined;
|
|
144
|
+
if (field.blockReferences) {
|
|
145
|
+
const maybeBlockReference = field.blockReferences.find((each)=>{
|
|
146
|
+
const slug = typeof each === 'string' ? each : each.slug;
|
|
147
|
+
return slug === data.blockType;
|
|
148
|
+
});
|
|
149
|
+
if (maybeBlockReference) {
|
|
150
|
+
if (typeof maybeBlockReference === 'object') {
|
|
151
|
+
maybeBlock = maybeBlockReference;
|
|
152
|
+
} else {
|
|
153
|
+
maybeBlock = config.blocks?.find((each)=>each.slug === maybeBlockReference);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (!maybeBlock) {
|
|
158
|
+
maybeBlock = field.blocks.find((each)=>each.slug === data.blockType);
|
|
159
|
+
}
|
|
160
|
+
if (maybeBlock) {
|
|
161
|
+
fields = maybeBlock.flattenedFields;
|
|
162
|
+
} else {
|
|
163
|
+
fieldData[i] = null;
|
|
164
|
+
hasNull = true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (!fields) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
stripFields({
|
|
171
|
+
config,
|
|
172
|
+
data,
|
|
173
|
+
fields,
|
|
174
|
+
parentIsLocalized: parentIsLocalized || field.localized,
|
|
175
|
+
reservedKeys
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
if (hasNull) {
|
|
179
|
+
data[field.name] = fieldData.filter(Boolean);
|
|
180
|
+
}
|
|
181
|
+
continue;
|
|
182
|
+
} else {
|
|
183
|
+
stripFields({
|
|
184
|
+
config,
|
|
185
|
+
data: fieldData,
|
|
186
|
+
fields: field.flattenedFields,
|
|
187
|
+
parentIsLocalized: parentIsLocalized || field.localized,
|
|
188
|
+
reservedKeys
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
//# sourceMappingURL=stripFields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/db-content-api/utilities/data/stripFields.ts"],"sourcesContent":["import type { FlattenedBlock, FlattenedField, SanitizedConfig } from 'payload'\n\nimport { fieldShouldBeLocalized } from 'payload/shared'\n\n/**\n * Strips fields from data that are not defined in the schema or are invalid.\n *\n * This function was copied from the MongoDB adapter's implementation:\n * @see packages/db-mongodb/src/utilities/transform.ts (stripFields function)\n *\n * @description\n * This utility performs deep sanitization of document data by:\n * 1. **Removing undefined fields**: Strips any field not present in the collection's schema\n * (e.g., sensitive fields like `password`, `apiKey`, or any extra fields not in config)\n * 2. **Removing invalid locales**: Deletes locale keys that don't exist in `config.localization.localeCodes`\n * (e.g., if data contains `{ \"es-MX\": \"...\" }` but only `\"en\"` is configured)\n * 3. **Removing invalid blocks**: Filters out blocks with unknown `blockType` values\n * (prevents data corruption from blocks that don't exist in the schema)\n * 4. **Recursive sanitization**: Processes nested structures (arrays, groups, blocks, localized fields)\n * to ensure deep data integrity\n *\n * @remarks\n * Unlike MongoDB's adapter which uses Mongoose schemas with `strict: true` (rejecting extra fields\n * on write), Content API uses flexible JSONB storage that accepts any fields. Therefore, this\n * function is called on **both read and write operations** to ensure data consistency.\n *\n * The MongoDB adapter also supports an `allowAdditionalKeys` option that allows reading/writing\n * fields not in the schema. For now, Content API does not support this feature - we always\n * sanitize data. If users request this functionality in the future, we can consider adding it.\n *\n * @todo\n * 1. Consider moving this utility to `payload/shared` so both MongoDB and Content API adapters\n * can use the same implementation, reducing code duplication and maintenance burden.\n *\n * 2. Performance optimization: This function iterates through all fields recursively.\n * The `dataToContentAPI` and `dataFromContentAPI` functions in\n * `packages/figma/src/db-content-api/utilities/data.ts` also iterate through fields\n * to transform richText (object ↔ JSON string), custom IDs (number ↔ string), and dates.\n * Consider combining both traversals into a single abstraction to avoid iterating twice.\n *\n * 3. Feature parity: MongoDB adapter has `allowAdditionalKeys` option. We currently always\n * strip additional keys, but could add this as a configurable option if users need it.\n */\nexport const stripFields = ({\n config,\n data,\n fields,\n parentIsLocalized = false,\n reservedKeys = [],\n}: {\n config: SanitizedConfig\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data: any\n fields: FlattenedField[]\n parentIsLocalized?: boolean\n reservedKeys?: string[]\n}) => {\n for (const k in data) {\n if (!fields.some((field) => field.name === k) && !reservedKeys.includes(k)) {\n delete data[k]\n }\n }\n\n for (const field of fields) {\n reservedKeys = []\n const fieldData = data[field.name]\n if (!fieldData || typeof fieldData !== 'object') {\n continue\n }\n\n const shouldLocalizeField = fieldShouldBeLocalized({ field, parentIsLocalized })\n\n if (field.type === 'blocks') {\n reservedKeys.push('blockType')\n }\n\n if ('flattenedFields' in field || 'blocks' in field) {\n if (shouldLocalizeField && config.localization) {\n for (const localeKey in fieldData) {\n if (!config.localization.localeCodes.some((code) => code === localeKey)) {\n delete fieldData[localeKey]\n continue\n }\n\n const localeData = fieldData[localeKey]\n\n if (!localeData || typeof localeData !== 'object') {\n continue\n }\n\n if (field.type === 'array' || field.type === 'blocks') {\n if (!Array.isArray(localeData)) {\n continue\n }\n\n let hasNull = false\n for (let i = 0; i < localeData.length; i++) {\n const data = localeData[i]\n let fields: FlattenedField[] | null = null\n\n if (field.type === 'array') {\n fields = field.flattenedFields\n } else {\n let maybeBlock: FlattenedBlock | undefined = undefined\n\n if (field.blockReferences) {\n const maybeBlockReference = field.blockReferences.find((each) => {\n const slug = typeof each === 'string' ? each : each.slug\n return slug === data.blockType\n })\n\n if (maybeBlockReference) {\n if (typeof maybeBlockReference === 'object') {\n maybeBlock = maybeBlockReference\n } else {\n maybeBlock = config.blocks?.find((each) => each.slug === maybeBlockReference)\n }\n }\n }\n\n if (!maybeBlock) {\n maybeBlock = field.blocks.find((each) => each.slug === data.blockType)\n }\n\n if (maybeBlock) {\n fields = maybeBlock.flattenedFields\n } else {\n localeData[i] = null\n hasNull = true\n }\n }\n\n if (!fields) {\n continue\n }\n\n stripFields({\n config,\n data,\n fields,\n parentIsLocalized: parentIsLocalized || field.localized,\n reservedKeys,\n })\n }\n\n if (hasNull) {\n fieldData[localeKey] = localeData.filter(Boolean)\n }\n\n continue\n } else {\n stripFields({\n config,\n data: localeData,\n fields: field.flattenedFields,\n parentIsLocalized: parentIsLocalized || field.localized,\n reservedKeys,\n })\n }\n }\n continue\n }\n\n if (field.type === 'array' || field.type === 'blocks') {\n if (!Array.isArray(fieldData)) {\n continue\n }\n\n let hasNull = false\n\n for (let i = 0; i < fieldData.length; i++) {\n const data = fieldData[i]\n let fields: FlattenedField[] | null = null\n\n if (field.type === 'array') {\n fields = field.flattenedFields\n } else {\n let maybeBlock: FlattenedBlock | undefined = undefined\n\n if (field.blockReferences) {\n const maybeBlockReference = field.blockReferences.find((each) => {\n const slug = typeof each === 'string' ? each : each.slug\n return slug === data.blockType\n })\n\n if (maybeBlockReference) {\n if (typeof maybeBlockReference === 'object') {\n maybeBlock = maybeBlockReference\n } else {\n maybeBlock = config.blocks?.find((each) => each.slug === maybeBlockReference)\n }\n }\n }\n\n if (!maybeBlock) {\n maybeBlock = field.blocks.find((each) => each.slug === data.blockType)\n }\n\n if (maybeBlock) {\n fields = maybeBlock.flattenedFields\n } else {\n fieldData[i] = null\n hasNull = true\n }\n }\n\n if (!fields) {\n continue\n }\n\n stripFields({\n config,\n data,\n fields,\n parentIsLocalized: parentIsLocalized || field.localized,\n reservedKeys,\n })\n }\n\n if (hasNull) {\n data[field.name] = fieldData.filter(Boolean)\n }\n\n continue\n } else {\n stripFields({\n config,\n data: fieldData,\n fields: field.flattenedFields,\n parentIsLocalized: parentIsLocalized || field.localized,\n reservedKeys,\n })\n }\n }\n }\n}\n"],"names":["fieldShouldBeLocalized","stripFields","config","data","fields","parentIsLocalized","reservedKeys","k","some","field","name","includes","fieldData","shouldLocalizeField","type","push","localization","localeKey","localeCodes","code","localeData","Array","isArray","hasNull","i","length","flattenedFields","maybeBlock","undefined","blockReferences","maybeBlockReference","find","each","slug","blockType","blocks","localized","filter","Boolean"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"where.d.ts","sourceRoot":"","sources":["../../../src/db-content-api/utilities/where.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,KAAK,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAA;AASvD,KAAK,cAAc,GAAG;IACpB,yEAAyE;IACzE,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,SAAS,GAAG,KAAK,EACxB,OAAO,GAAE,cAAmB,GAC3B,WAAW,
|
|
1
|
+
{"version":3,"file":"where.d.ts","sourceRoot":"","sources":["../../../src/db-content-api/utilities/where.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,KAAK,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAA;AASvD,KAAK,cAAc,GAAG;IACpB,yEAAyE;IACzE,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,SAAS,GAAG,KAAK,EACxB,OAAO,GAAE,cAAmB,GAC3B,WAAW,CA4Gb"}
|
|
@@ -13,7 +13,26 @@ export function convertPayloadWhereToContentAPI(where, options = {}) {
|
|
|
13
13
|
const nestedConditions = value.map((item)=>convertPayloadWhereToContentAPI(item, {
|
|
14
14
|
...options,
|
|
15
15
|
insideLogicalOperator: true
|
|
16
|
-
}))
|
|
16
|
+
}))// TODO: A better solution would be to make the `where` schema of `zod` in `content-api`
|
|
17
|
+
// more permissive. For now I'll do it this way because I have an idea to simplify
|
|
18
|
+
// everything we're doing with `where` (Post EAP) anyway.
|
|
19
|
+
// Filter out empty conditions { and: [] } that would be invalid
|
|
20
|
+
.filter((condition)=>{
|
|
21
|
+
if ('and' in condition) {
|
|
22
|
+
return condition.and.length > 0;
|
|
23
|
+
}
|
|
24
|
+
if ('or' in condition) {
|
|
25
|
+
return condition.or.length > 0;
|
|
26
|
+
}
|
|
27
|
+
return true // Keep path/operator/value conditions
|
|
28
|
+
;
|
|
29
|
+
});
|
|
30
|
+
// If filtering resulted in no conditions, return empty and
|
|
31
|
+
if (nestedConditions.length === 0) {
|
|
32
|
+
return {
|
|
33
|
+
and: []
|
|
34
|
+
};
|
|
35
|
+
}
|
|
17
36
|
return {
|
|
18
37
|
and: nestedConditions
|
|
19
38
|
};
|
|
@@ -22,7 +41,23 @@ export function convertPayloadWhereToContentAPI(where, options = {}) {
|
|
|
22
41
|
const nestedConditions = value.map((item)=>convertPayloadWhereToContentAPI(item, {
|
|
23
42
|
...options,
|
|
24
43
|
insideLogicalOperator: true
|
|
25
|
-
}))
|
|
44
|
+
}))// Filter out empty conditions { and: [] } or { or: [] } that would be invalid
|
|
45
|
+
.filter((condition)=>{
|
|
46
|
+
if ('and' in condition) {
|
|
47
|
+
return condition.and.length > 0;
|
|
48
|
+
}
|
|
49
|
+
if ('or' in condition) {
|
|
50
|
+
return condition.or.length > 0;
|
|
51
|
+
}
|
|
52
|
+
return true // Keep path/operator/value conditions
|
|
53
|
+
;
|
|
54
|
+
});
|
|
55
|
+
// If filtering resulted in no conditions, return empty and
|
|
56
|
+
if (nestedConditions.length === 0) {
|
|
57
|
+
return {
|
|
58
|
+
and: []
|
|
59
|
+
};
|
|
60
|
+
}
|
|
26
61
|
return {
|
|
27
62
|
or: nestedConditions
|
|
28
63
|
};
|
|
@@ -36,7 +71,16 @@ export function convertPayloadWhereToContentAPI(where, options = {}) {
|
|
|
36
71
|
// Convert field conditions: { fieldName: { operator: value } }
|
|
37
72
|
// to: { path: fieldName, operator, value }
|
|
38
73
|
const operators = value;
|
|
74
|
+
// Skip empty operator objects { fieldName: {} }
|
|
75
|
+
if (Object.keys(operators).length === 0) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
39
78
|
for (const [op, operatorValue] of Object.entries(operators)){
|
|
79
|
+
// Skip operators with undefined values (e.g., { equals: undefined })
|
|
80
|
+
// This can happen when Payload sends incomplete where clauses
|
|
81
|
+
if (operatorValue === undefined) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
40
84
|
let finalValue = operatorValue;
|
|
41
85
|
// Add wildcards for contains/like operators (Payload doesn't add them)
|
|
42
86
|
if ((op === 'contains' || op === 'like') && typeof operatorValue === 'string') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/db-content-api/utilities/where.ts"],"sourcesContent":["import type { Where } from 'payload'\n\nimport type { components } from '../generated/content-api-types.js'\n\ntype WhereClause = components['schemas']['WhereClause']\n\n// Payload's format: { fieldName: { operator: value }, and: [...], or: [...] }\n// Content API expects: { and: [{ path, operator, value }], or: [{ path, operator, value }] }\n//\n// The format stays different. This allows the Content API to evolve its filter schema,\n// for example to support composite types like Point, which are not lexicographically sortable.\n// Semantics must remain identical to Payload.\n\ntype ConvertOptions = {\n /** Internal flag to track if we're inside a logical operator (and/or) */\n insideLogicalOperator?: boolean\n /** If true, transform 'parent' field to 'documentId' (used for version queries) */\n parentToDocumentId?: boolean\n}\n\nexport function convertPayloadWhereToContentAPI(\n where: undefined | Where,\n options: ConvertOptions = {},\n): WhereClause {\n // Empty where {} should be { and: [] } not undefined\n // Content API requires a where clause structure even for \"no filter\"\n if (!where || Object.keys(where).length === 0) {\n return { and: [] }\n }\n\n // Extract the condition type (the variant with 'path', 'operator', 'value') from WhereClause union\n type WhereCondition = Extract<WhereClause, { path: string }>\n const conditions: WhereClause[] = []\n\n for (const [key, value] of Object.entries(where)) {\n if (key === 'and') {\n // Recursively convert nested 'and' conditions, preserving options\n const nestedConditions = (value as Where[]).map((item) =>\n
|
|
1
|
+
{"version":3,"sources":["../../../src/db-content-api/utilities/where.ts"],"sourcesContent":["import type { Where } from 'payload'\n\nimport type { components } from '../generated/content-api-types.js'\n\ntype WhereClause = components['schemas']['WhereClause']\n\n// Payload's format: { fieldName: { operator: value }, and: [...], or: [...] }\n// Content API expects: { and: [{ path, operator, value }], or: [{ path, operator, value }] }\n//\n// The format stays different. This allows the Content API to evolve its filter schema,\n// for example to support composite types like Point, which are not lexicographically sortable.\n// Semantics must remain identical to Payload.\n\ntype ConvertOptions = {\n /** Internal flag to track if we're inside a logical operator (and/or) */\n insideLogicalOperator?: boolean\n /** If true, transform 'parent' field to 'documentId' (used for version queries) */\n parentToDocumentId?: boolean\n}\n\nexport function convertPayloadWhereToContentAPI(\n where: undefined | Where,\n options: ConvertOptions = {},\n): WhereClause {\n // Empty where {} should be { and: [] } not undefined\n // Content API requires a where clause structure even for \"no filter\"\n if (!where || Object.keys(where).length === 0) {\n return { and: [] }\n }\n\n // Extract the condition type (the variant with 'path', 'operator', 'value') from WhereClause union\n type WhereCondition = Extract<WhereClause, { path: string }>\n const conditions: WhereClause[] = []\n\n for (const [key, value] of Object.entries(where)) {\n if (key === 'and') {\n // Recursively convert nested 'and' conditions, preserving options\n const nestedConditions = (value as Where[])\n .map((item) =>\n convertPayloadWhereToContentAPI(item, { ...options, insideLogicalOperator: true }),\n )\n // TODO: A better solution would be to make the `where` schema of `zod` in `content-api`\n // more permissive. For now I'll do it this way because I have an idea to simplify\n // everything we're doing with `where` (Post EAP) anyway.\n // Filter out empty conditions { and: [] } that would be invalid\n .filter((condition) => {\n if ('and' in condition) {\n return condition.and.length > 0\n }\n if ('or' in condition) {\n return condition.or.length > 0\n }\n return true // Keep path/operator/value conditions\n })\n\n // If filtering resulted in no conditions, return empty and\n if (nestedConditions.length === 0) {\n return { and: [] }\n }\n\n return { and: nestedConditions }\n } else if (key === 'or') {\n // Recursively convert nested 'or' conditions, preserving options\n const nestedConditions = (value as Where[])\n .map((item) =>\n convertPayloadWhereToContentAPI(item, { ...options, insideLogicalOperator: true }),\n )\n // Filter out empty conditions { and: [] } or { or: [] } that would be invalid\n .filter((condition) => {\n if ('and' in condition) {\n return condition.and.length > 0\n }\n if ('or' in condition) {\n return condition.or.length > 0\n }\n return true // Keep path/operator/value conditions\n })\n\n // If filtering resulted in no conditions, return empty and\n if (nestedConditions.length === 0) {\n return { and: [] }\n }\n\n return { or: nestedConditions }\n } else {\n // TODO: fix this in content api\n // WORKAROUND: Payload uses 'parent' for version queries, but Content API expects 'documentId'\n let fieldPath = key\n if (options.parentToDocumentId && key === 'parent') {\n fieldPath = 'documentId'\n }\n\n // Convert field conditions: { fieldName: { operator: value } }\n // to: { path: fieldName, operator, value }\n const operators = value as Record<string, unknown>\n\n // Skip empty operator objects { fieldName: {} }\n if (Object.keys(operators).length === 0) {\n continue\n }\n\n for (const [op, operatorValue] of Object.entries(operators)) {\n // Skip operators with undefined values (e.g., { equals: undefined })\n // This can happen when Payload sends incomplete where clauses\n if (operatorValue === undefined) {\n continue\n }\n\n let finalValue = operatorValue\n\n // Add wildcards for contains/like operators (Payload doesn't add them)\n if ((op === 'contains' || op === 'like') && typeof operatorValue === 'string') {\n finalValue = `%${operatorValue}%`\n }\n\n conditions.push({\n operator: op as WhereCondition['operator'],\n path: fieldPath,\n value: finalValue,\n } as WhereCondition)\n }\n }\n }\n\n // If inside a logical operator (and/or), return conditions directly\n // Otherwise, wrap in 'and' to match WhereClause type\n if (options.insideLogicalOperator && conditions.length === 1) {\n return conditions[0]\n }\n\n return { and: conditions }\n}\n"],"names":["convertPayloadWhereToContentAPI","where","options","Object","keys","length","and","conditions","key","value","entries","nestedConditions","map","item","insideLogicalOperator","filter","condition","or","fieldPath","parentToDocumentId","operators","op","operatorValue","undefined","finalValue","push","operator","path"],"mappings":"AAoBA,OAAO,SAASA,gCACdC,KAAwB,EACxBC,UAA0B,CAAC,CAAC;IAE5B,qDAAqD;IACrD,qEAAqE;IACrE,IAAI,CAACD,SAASE,OAAOC,IAAI,CAACH,OAAOI,MAAM,KAAK,GAAG;QAC7C,OAAO;YAAEC,KAAK,EAAE;QAAC;IACnB;IAIA,MAAMC,aAA4B,EAAE;IAEpC,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIN,OAAOO,OAAO,CAACT,OAAQ;QAChD,IAAIO,QAAQ,OAAO;YACjB,kEAAkE;YAClE,MAAMG,mBAAmB,AAACF,MACvBG,GAAG,CAAC,CAACC,OACJb,gCAAgCa,MAAM;oBAAE,GAAGX,OAAO;oBAAEY,uBAAuB;gBAAK,GAElF,wFAAwF;YACxF,kFAAkF;YAClF,yDAAyD;YACzD,gEAAgE;aAC/DC,MAAM,CAAC,CAACC;gBACP,IAAI,SAASA,WAAW;oBACtB,OAAOA,UAAUV,GAAG,CAACD,MAAM,GAAG;gBAChC;gBACA,IAAI,QAAQW,WAAW;oBACrB,OAAOA,UAAUC,EAAE,CAACZ,MAAM,GAAG;gBAC/B;gBACA,OAAO,KAAK,sCAAsC;;YACpD;YAEF,2DAA2D;YAC3D,IAAIM,iBAAiBN,MAAM,KAAK,GAAG;gBACjC,OAAO;oBAAEC,KAAK,EAAE;gBAAC;YACnB;YAEA,OAAO;gBAAEA,KAAKK;YAAiB;QACjC,OAAO,IAAIH,QAAQ,MAAM;YACvB,iEAAiE;YACjE,MAAMG,mBAAmB,AAACF,MACvBG,GAAG,CAAC,CAACC,OACJb,gCAAgCa,MAAM;oBAAE,GAAGX,OAAO;oBAAEY,uBAAuB;gBAAK,GAElF,8EAA8E;aAC7EC,MAAM,CAAC,CAACC;gBACP,IAAI,SAASA,WAAW;oBACtB,OAAOA,UAAUV,GAAG,CAACD,MAAM,GAAG;gBAChC;gBACA,IAAI,QAAQW,WAAW;oBACrB,OAAOA,UAAUC,EAAE,CAACZ,MAAM,GAAG;gBAC/B;gBACA,OAAO,KAAK,sCAAsC;;YACpD;YAEF,2DAA2D;YAC3D,IAAIM,iBAAiBN,MAAM,KAAK,GAAG;gBACjC,OAAO;oBAAEC,KAAK,EAAE;gBAAC;YACnB;YAEA,OAAO;gBAAEW,IAAIN;YAAiB;QAChC,OAAO;YACL,gCAAgC;YAChC,8FAA8F;YAC9F,IAAIO,YAAYV;YAChB,IAAIN,QAAQiB,kBAAkB,IAAIX,QAAQ,UAAU;gBAClDU,YAAY;YACd;YAEA,+DAA+D;YAC/D,2CAA2C;YAC3C,MAAME,YAAYX;YAElB,gDAAgD;YAChD,IAAIN,OAAOC,IAAI,CAACgB,WAAWf,MAAM,KAAK,GAAG;gBACvC;YACF;YAEA,KAAK,MAAM,CAACgB,IAAIC,cAAc,IAAInB,OAAOO,OAAO,CAACU,WAAY;gBAC3D,qEAAqE;gBACrE,8DAA8D;gBAC9D,IAAIE,kBAAkBC,WAAW;oBAC/B;gBACF;gBAEA,IAAIC,aAAaF;gBAEjB,uEAAuE;gBACvE,IAAI,AAACD,CAAAA,OAAO,cAAcA,OAAO,MAAK,KAAM,OAAOC,kBAAkB,UAAU;oBAC7EE,aAAa,CAAC,CAAC,EAAEF,cAAc,CAAC,CAAC;gBACnC;gBAEAf,WAAWkB,IAAI,CAAC;oBACdC,UAAUL;oBACVM,MAAMT;oBACNT,OAAOe;gBACT;YACF;QACF;IACF;IAEA,oEAAoE;IACpE,qDAAqD;IACrD,IAAItB,QAAQY,qBAAqB,IAAIP,WAAWF,MAAM,KAAK,GAAG;QAC5D,OAAOE,UAAU,CAAC,EAAE;IACtB;IAEA,OAAO;QAAED,KAAKC;IAAW;AAC3B"}
|
package/dist/exports/client.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { DefaultLoginButton } from '../oauth/components/LoginButton/index.js';
|
|
2
2
|
export { LogoutButton } from '../oauth/components/LogoutButton/index.js';
|
|
3
|
+
export { ContentApiClientUploadHandler } from '../storage-content-api/client-uploads/ClientUploadHandler.js';
|
|
3
4
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/exports/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAA;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAA"}
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/exports/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAA;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAA;AACxE,OAAO,EAAE,6BAA6B,EAAE,MAAM,8DAA8D,CAAA"}
|
package/dist/exports/client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { DefaultLoginButton } from '../oauth/components/LoginButton/index.js';
|
|
2
2
|
export { LogoutButton } from '../oauth/components/LogoutButton/index.js';
|
|
3
|
+
export { ContentApiClientUploadHandler } from '../storage-content-api/client-uploads/ClientUploadHandler.js';
|
|
3
4
|
|
|
4
5
|
//# sourceMappingURL=client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["export { DefaultLoginButton } from '../oauth/components/LoginButton/index.js'\nexport { LogoutButton } from '../oauth/components/LogoutButton/index.js'\n"],"names":["DefaultLoginButton","LogoutButton"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,2CAA0C;AAC7E,SAASC,YAAY,QAAQ,4CAA2C"}
|
|
1
|
+
{"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["export { DefaultLoginButton } from '../oauth/components/LoginButton/index.js'\nexport { LogoutButton } from '../oauth/components/LogoutButton/index.js'\nexport { ContentApiClientUploadHandler } from '../storage-content-api/client-uploads/ClientUploadHandler.js'\n"],"names":["DefaultLoginButton","LogoutButton","ContentApiClientUploadHandler"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,2CAA0C;AAC7E,SAASC,YAAY,QAAQ,4CAA2C;AACxE,SAASC,6BAA6B,QAAQ,+DAA8D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-config.d.ts","sourceRoot":"","sources":["../../src/plugin/build-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"build-config.d.ts","sourceRoot":"","sources":["../../src/plugin/build-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAiBtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;CAC1B,GAAG;IACF,KAAK,EAAE;QACL,eAAe,EAAE,MAAM,CAAA;QACvB,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAC3B,CAAA;CACF,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,QAAQ,GAAG,QAAQ,CAAC,GAC1C,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAA;AAE7B;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAyHpF"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage';
|
|
2
|
+
import { initClientUploads } from '@payloadcms/plugin-cloud-storage/utilities';
|
|
2
3
|
import { lexicalEditor } from '@payloadcms/richtext-lexical';
|
|
3
4
|
import { buildConfig as payloadBuildConfig } from 'payload';
|
|
4
5
|
import { getTokenStore } from '../auth/token-store.js';
|
|
5
6
|
import { contentAPIAdapter } from '../db-content-api/index.js';
|
|
6
7
|
import { health } from '../endpoints/health.js';
|
|
7
8
|
import { oAuth2Plugin } from '../oauth/index.js';
|
|
9
|
+
import { createStorageClient } from '../storage-content-api/client.js';
|
|
10
|
+
import { getGenerateSignedURLHandler } from '../storage-content-api/client-uploads/generateSignedURL.js';
|
|
8
11
|
import { contentApiStorageAdapter } from '../storage-content-api/index.js';
|
|
9
12
|
/**
|
|
10
13
|
* Figma platform wrapper for Payload's buildConfig.
|
|
@@ -76,6 +79,7 @@ import { contentApiStorageAdapter } from '../storage-content-api/index.js';
|
|
|
76
79
|
contentSystemId
|
|
77
80
|
};
|
|
78
81
|
const adapter = contentApiStorageAdapter(storageConfig);
|
|
82
|
+
const storageClient = createStorageClient(storageConfig);
|
|
79
83
|
const collectionsMap = uploadCollections.reduce((acc, c)=>{
|
|
80
84
|
acc[c.slug] = {
|
|
81
85
|
adapter,
|
|
@@ -83,6 +87,16 @@ import { contentApiStorageAdapter } from '../storage-content-api/index.js';
|
|
|
83
87
|
};
|
|
84
88
|
return acc;
|
|
85
89
|
}, {});
|
|
90
|
+
initClientUploads({
|
|
91
|
+
clientHandler: '@payloadcms/figma/client#ContentApiClientUploadHandler',
|
|
92
|
+
collections: collectionsMap,
|
|
93
|
+
config: config,
|
|
94
|
+
enabled: true,
|
|
95
|
+
serverHandler: getGenerateSignedURLHandler({
|
|
96
|
+
client: storageClient
|
|
97
|
+
}),
|
|
98
|
+
serverHandlerPath: '/content-api-storage-signed-url'
|
|
99
|
+
});
|
|
86
100
|
storagePlugin = cloudStoragePlugin({
|
|
87
101
|
collections: collectionsMap
|
|
88
102
|
});
|