@sequoialabs/payload-plugin-reversia 0.1.3 → 0.1.4

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.
@@ -18,7 +18,8 @@ async function withRetry(fn) {
18
18
  }
19
19
  catch (error) {
20
20
  if (attempt < WRITE_CONFLICT_MAX_RETRIES && isWriteConflict(error)) {
21
- const delay = WRITE_CONFLICT_BASE_DELAY_MS * 2 ** attempt + Math.random() * WRITE_CONFLICT_BASE_DELAY_MS;
21
+ const delay = WRITE_CONFLICT_BASE_DELAY_MS * 2 ** attempt +
22
+ Math.random() * WRITE_CONFLICT_BASE_DELAY_MS;
22
23
  await new Promise((resolve) => setTimeout(resolve, delay));
23
24
  continue;
24
25
  }
@@ -65,7 +66,19 @@ function applyTranslations({ allowedFields, data, sourceDoc, previousDoc, }) {
65
66
  const previous = previousDoc ?? null;
66
67
  const source = cleanSource ?? null;
67
68
  const dataKeys = new Set(Object.keys(data));
68
- // Seed required fields that are empty in target and not being translated.
69
+ // Seed required fields not being translated so Payload's whole-document
70
+ // validation doesn't reject the update.
71
+ //
72
+ // Scalars: only seed when the target locale has no value at all (null /
73
+ // undefined / empty string). If the target already has something, leave it.
74
+ //
75
+ // Containers: always seed from source when not in `data`. The target might
76
+ // have a "structurally present but content-empty" value (e.g. Payload
77
+ // auto-creates 9 default block items from `defaultValue` but every block's
78
+ // required inner richText is null). A shallow null-check misses this; a
79
+ // deep check is impractical. Seeding writes source-locale content as a
80
+ // placeholder — once Reversia translates the field and sends it in `data`,
81
+ // the seed is overwritten with the real translation.
69
82
  for (const field of allowedFields) {
70
83
  if (!field.hasRequiredLeaf) {
71
84
  continue;
@@ -73,18 +86,22 @@ function applyTranslations({ allowedFields, data, sourceDoc, previousDoc, }) {
73
86
  if (dataKeys.has(field.name)) {
74
87
  continue; // Reversia is sending it — will be handled below
75
88
  }
76
- const targetValue = previous ? previous[field.name] : undefined;
77
- if (targetValue !== undefined && targetValue !== null) {
78
- continue; // Target already has a value — don't overwrite
79
- }
80
89
  const sourceValue = source ? source[field.name] : undefined;
81
90
  if (sourceValue === undefined || sourceValue === null) {
82
91
  continue; // Source is also empty — nothing we can do
83
92
  }
84
- // Seed from source so Payload's required validation doesn't reject.
85
- updateData[field.name] = field.isContainer
86
- ? deflatePopulatedRelationships(structuredClone(sourceValue))
87
- : sourceValue;
93
+ if (field.isContainer) {
94
+ // Always seed containers from source — inner required subfields may be
95
+ // empty even when the container itself is non-null in the target.
96
+ updateData[field.name] = deflatePopulatedRelationships(structuredClone(sourceValue));
97
+ }
98
+ else {
99
+ // Scalars: only seed when truly empty in target.
100
+ const targetValue = previous ? previous[field.name] : undefined;
101
+ if (targetValue === undefined || targetValue === null || targetValue === '') {
102
+ updateData[field.name] = sourceValue;
103
+ }
104
+ }
88
105
  }
89
106
  for (const [fieldName, translatedValue] of Object.entries(data)) {
90
107
  const field = fieldByName.get(fieldName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sequoialabs/payload-plugin-reversia",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "author": {
5
5
  "name": "Jean Walrave",
6
6
  "email": "contact@reversia.tech",