gt-sanity 2.0.15 → 2.0.16

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 (48) hide show
  1. package/dist/index.cjs +146 -78
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +45 -29
  4. package/dist/index.d.ts +45 -29
  5. package/dist/index.js +146 -78
  6. package/dist/index.js.map +1 -1
  7. package/package.json +2 -2
  8. package/src/adapter/core.ts +8 -7
  9. package/src/adapter/types.ts +1 -1
  10. package/src/components/TranslationsProvider.tsx +22 -7
  11. package/src/configuration/baseDocumentLevelConfig/documentLevelPatch.test.ts +10 -2
  12. package/src/configuration/baseDocumentLevelConfig/documentLevelPatch.ts +17 -6
  13. package/src/configuration/baseDocumentLevelConfig/helpers/createI18nDocAndPatchMetadata.ts +1 -1
  14. package/src/configuration/baseDocumentLevelConfig/helpers/patchI18nDoc.test.ts +2 -1
  15. package/src/configuration/baseDocumentLevelConfig/helpers/patchI18nDoc.ts +3 -3
  16. package/src/hooks/useSecrets.ts +1 -1
  17. package/src/index.ts +3 -2
  18. package/src/sanity-api/resolveRefs.ts +21 -10
  19. package/src/serialization/BaseDocumentMerger.ts +56 -32
  20. package/src/serialization/BaseSerializationConfig.ts +30 -11
  21. package/src/serialization/__tests__/BaseDocumentDeserializer/baseDeserialization.test.ts +75 -69
  22. package/src/serialization/__tests__/BaseDocumentDeserializer/documentLevelDeserialization.test.ts +10 -14
  23. package/src/serialization/__tests__/BaseDocumentDeserializer/fieldLevelDeserialization.test.ts +10 -14
  24. package/src/serialization/__tests__/BaseDocumentMerger/baseMerge.test.ts +5 -9
  25. package/src/serialization/__tests__/BaseDocumentMerger/documentLevelMerge.test.ts +17 -19
  26. package/src/serialization/__tests__/BaseDocumentMerger/fieldLevelMerge.test.ts +33 -26
  27. package/src/serialization/__tests__/BaseDocumentMerger/utils.ts +20 -23
  28. package/src/serialization/__tests__/BaseDocumentSerializer/baseSerialization.test.ts +23 -23
  29. package/src/serialization/__tests__/BaseDocumentSerializer/documentLevelSerialization.test.ts +6 -6
  30. package/src/serialization/__tests__/BaseDocumentSerializer/fieldLevelSerialization.test.ts +8 -8
  31. package/src/serialization/__tests__/BaseDocumentSerializer/utils.ts +12 -10
  32. package/src/serialization/__tests__/__fixtures__/inlineSchema.ts +4 -1
  33. package/src/serialization/__tests__/__fixtures__/schema.ts +15 -6
  34. package/src/serialization/__tests__/global.setup.ts +7 -3
  35. package/src/serialization/__tests__/helpers.ts +11 -11
  36. package/src/serialization/data.ts +3 -3
  37. package/src/serialization/deserialize/BaseDocumentDeserializer.ts +41 -29
  38. package/src/serialization/index.ts +6 -1
  39. package/src/serialization/serialize/fieldFilters.ts +52 -30
  40. package/src/serialization/serialize/index.ts +48 -21
  41. package/src/serialization/types.ts +32 -17
  42. package/src/types.ts +1 -1
  43. package/src/utils/__tests__/documentIds.test.ts +2 -1
  44. package/src/utils/__tests__/forEachMatchingField.test.ts +1 -1
  45. package/src/utils/applyDocuments.ts +16 -14
  46. package/src/utils/batchProcessor.ts +21 -18
  47. package/src/utils/importUtils.ts +16 -10
  48. package/src/utils/serialize.ts +2 -1
package/dist/index.cjs CHANGED
@@ -43,7 +43,7 @@ class GTConfig {
43
43
  additionalDeserializers;
44
44
  additionalBlockDeserializers;
45
45
  static instance;
46
- constructor(secretsNamespace, languageField, sourceLocale, locales, singletons, singletonMapping, ignoreFields, dedupeFields, skipFields, translateDocuments, additionalStopTypes = [], additionalSerializers = {}, additionalDeserializers = {}, additionalBlockDeserializers = []) {
46
+ constructor(secretsNamespace, languageField, sourceLocale, locales, singletons, singletonMapping, ignoreFields, dedupeFields, skipFields, translateDocuments, additionalStopTypes = [], additionalSerializers = {}, additionalDeserializers = { types: {} }, additionalBlockDeserializers = []) {
47
47
  this.secretsNamespace = secretsNamespace, this.languageField = languageField, this.sourceLocale = sourceLocale, this.locales = locales, this.singletons = singletons, this.singletonMapping = singletonMapping, this.ignoreFields = ignoreFields, this.dedupeFields = dedupeFields, this.skipFields = skipFields, this.translateDocuments = translateDocuments, this.additionalStopTypes = additionalStopTypes, this.additionalSerializers = additionalSerializers, this.additionalDeserializers = additionalDeserializers, this.additionalBlockDeserializers = additionalBlockDeserializers;
48
48
  }
49
49
  static getInstance() {
@@ -59,12 +59,12 @@ class GTConfig {
59
59
  [],
60
60
  [],
61
61
  [],
62
- {},
62
+ { types: {} },
63
63
  {},
64
64
  []
65
65
  )), this.instance;
66
66
  }
67
- init(secretsNamespace, languageField, sourceLocale, locales, singletons, singletonMapping, ignoreFields, dedupeFields, skipFields, translateDocuments, additionalStopTypes = [], additionalSerializers = {}, additionalDeserializers = {}, additionalBlockDeserializers = []) {
67
+ init(secretsNamespace, languageField, sourceLocale, locales, singletons, singletonMapping, ignoreFields, dedupeFields, skipFields, translateDocuments, additionalStopTypes = [], additionalSerializers = {}, additionalDeserializers = { types: {} }, additionalBlockDeserializers = []) {
68
68
  this.secretsNamespace = secretsNamespace, this.languageField = languageField, this.sourceLocale = sourceLocale, this.locales = locales, this.singletons = singletons, this.singletonMapping = singletonMapping, this.ignoreFields = ignoreFields, this.dedupeFields = dedupeFields, this.skipFields = skipFields, this.translateDocuments = translateDocuments, this.additionalStopTypes = additionalStopTypes, this.additionalSerializers = additionalSerializers, this.additionalDeserializers = additionalDeserializers, this.additionalBlockDeserializers = additionalBlockDeserializers;
69
69
  }
70
70
  getSecretsNamespace() {
@@ -122,31 +122,37 @@ const pluginConfig = GTConfig.getInstance(), theme = theme$1.buildTheme(), BaseT
122
122
  !loadingSecrets && secrets && children
123
123
  ] });
124
124
  return /* @__PURE__ */ jsxRuntime.jsx(ui.ThemeProvider, { theme, children: /* @__PURE__ */ jsxRuntime.jsx(ui.ToastProvider, { paddingY: 7, children: showContainer ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding, children: content }) : content }) });
125
- }, reconcileArray = (origArray, translatedArray) => {
125
+ }, isRecord$4 = (value) => typeof value == "object" && value !== null && !Array.isArray(value), reconcileArray = (origArray, translatedArray) => {
126
126
  if (translatedArray && translatedArray.some((el) => typeof el == "string"))
127
127
  return translatedArray;
128
128
  const combined = JSON.parse(JSON.stringify(origArray));
129
- return translatedArray.forEach((block) => {
130
- if (!block._key)
129
+ return translatedArray.forEach((translatedItem) => {
130
+ if (!isRecord$4(translatedItem) || !translatedItem._key)
131
131
  return;
132
132
  const foundBlockIdx = origArray.findIndex(
133
- (origBlock) => origBlock._key === block._key
133
+ (origBlock) => isRecord$4(origBlock) && origBlock._key === translatedItem._key
134
134
  );
135
135
  foundBlockIdx < 0 ? console.warn(
136
136
  `This block no longer exists on the original document. Was it removed? ${JSON.stringify(
137
- block
137
+ translatedItem
138
138
  )}`
139
- ) : origArray[foundBlockIdx]._type === "block" || origArray[foundBlockIdx]._type === "span" ? combined[foundBlockIdx] = block : Array.isArray(origArray[foundBlockIdx]) ? combined[foundBlockIdx] = reconcileArray(origArray[foundBlockIdx], block) : combined[foundBlockIdx] = reconcileObject(
139
+ ) : isRecord$4(origArray[foundBlockIdx]) && (origArray[foundBlockIdx]._type === "block" || origArray[foundBlockIdx]._type === "span") ? combined[foundBlockIdx] = translatedItem : isRecord$4(origArray[foundBlockIdx]) && (combined[foundBlockIdx] = reconcileObject(
140
140
  origArray[foundBlockIdx],
141
- block
142
- );
141
+ translatedItem
142
+ ));
143
143
  }), combined;
144
144
  }, reconcileObject = (origObject, translatedObject) => {
145
145
  if (typeof translatedObject != "object" || !Object.keys(translatedObject).length)
146
146
  return origObject;
147
147
  const updatedObj = JSON.parse(JSON.stringify(origObject));
148
148
  return Object.entries(translatedObject).forEach(([key, value]) => {
149
- !value || key[0] === "_" || (typeof value == "string" ? updatedObj[key] = value : Array.isArray(value) ? updatedObj[key] = reconcileArray(origObject[key] ?? [], value) : updatedObj[key] = reconcileObject(origObject[key] ?? {}, value));
149
+ !value || key[0] === "_" || (typeof value == "string" ? updatedObj[key] = value : Array.isArray(value) ? updatedObj[key] = reconcileArray(
150
+ Array.isArray(origObject[key]) ? origObject[key] : [],
151
+ value
152
+ ) : isRecord$4(value) && (updatedObj[key] = reconcileObject(
153
+ isRecord$4(origObject[key]) ? origObject[key] : {},
154
+ value
155
+ )));
150
156
  }), updatedObj;
151
157
  }, fieldLevelMerge = (translatedFields, baseDoc, localeId, baseLang = "en") => {
152
158
  const merged = {};
@@ -161,8 +167,11 @@ const pluginConfig = GTConfig.getInstance(), theme = theme$1.buildTheme(), BaseT
161
167
  translatedFields
162
168
  )[0].value;
163
169
  let valToPatch;
164
- typeof translatedVal == "string" ? valToPatch = translatedVal : Array.isArray(translatedVal) && translatedVal.length ? valToPatch = reconcileArray(origVal ?? [], translatedVal) : typeof translatedVal == "object" && Object.keys(translatedVal).length && (valToPatch = reconcileObject(
165
- origVal ?? {},
170
+ typeof translatedVal == "string" ? valToPatch = translatedVal : Array.isArray(translatedVal) && translatedVal.length ? valToPatch = reconcileArray(
171
+ origVal ?? [],
172
+ translatedVal
173
+ ) : typeof translatedVal == "object" && Object.keys(translatedVal).length && (valToPatch = reconcileObject(
174
+ isRecord$4(origVal) ? origVal : {},
166
175
  translatedVal
167
176
  ));
168
177
  const destinationPath = [
@@ -173,7 +182,10 @@ const pluginConfig = GTConfig.getInstance(), theme = theme$1.buildTheme(), BaseT
173
182
  ];
174
183
  merged[mutator.arrayToJSONMatchPath(destinationPath)] = valToPatch;
175
184
  }), merged;
176
- }, documentLevelMerge = (translatedFields, baseDoc) => reconcileObject(baseDoc, translatedFields), BaseDocumentMerger = {
185
+ }, documentLevelMerge = (translatedFields, baseDoc) => reconcileObject(
186
+ baseDoc,
187
+ translatedFields
188
+ ), BaseDocumentMerger = {
177
189
  fieldLevelMerge,
178
190
  documentLevelMerge,
179
191
  reconcileArray,
@@ -240,7 +252,7 @@ function decode(base64) {
240
252
  bytes[i] = binary.charCodeAt(i);
241
253
  return new TextDecoder().decode(bytes);
242
254
  }
243
- const defaultStopTypes = [
255
+ const isRecord$3 = (value) => typeof value == "object" && value !== null && !Array.isArray(value), defaultStopTypes = [
244
256
  "reference",
245
257
  "date",
246
258
  "datetime",
@@ -283,13 +295,19 @@ const defaultStopTypes = [
283
295
  }, customDeserializers = { types: {} }, customBlockDeserializers = [
284
296
  // handle marks with data-gt-internal
285
297
  {
286
- deserialize(el, next2) {
298
+ deserialize(node2, next2) {
299
+ if (node2.nodeType !== 1)
300
+ return;
301
+ const el = node2;
287
302
  if (!el.hasChildNodes() || !el.getAttribute("data-gt-internal"))
288
303
  return;
289
304
  const { html, data } = detachGTData(el.outerHTML), block = blockTools.htmlToBlocks(html, blockContentType)[0], children = next2(el.childNodes);
290
305
  let markDefs = [];
291
- return "markDefs" in block && (markDefs = block.markDefs ?? []), data?.markDef && markDefs.push(data.markDef), children && children.forEach((child) => {
292
- child.marks = data?.markDef?._key ? [...child.marks || [], data.markDef._key] : [...child.marks || []];
306
+ return "markDefs" in block && (markDefs = block.markDefs ?? []), data?.markDef && markDefs.push(data.markDef), Array.isArray(children) && children.forEach((child) => {
307
+ if (!isRecord$3(child))
308
+ return;
309
+ const marks = Array.isArray(child.marks) ? child.marks : [];
310
+ child.marks = data?.markDef?._key ? [...marks, data.markDef._key] : marks;
293
311
  }), {
294
312
  ...block,
295
313
  markDefs,
@@ -299,7 +317,10 @@ const defaultStopTypes = [
299
317
  },
300
318
  //handle undeclared styles
301
319
  {
302
- deserialize(el, next2) {
320
+ deserialize(node2, next2) {
321
+ if (node2.nodeType !== 1)
322
+ return;
323
+ const el = node2;
303
324
  if (!el.hasChildNodes() || el.getAttribute("data-type") !== "unknown-block-style")
304
325
  return;
305
326
  const style = el.getAttribute("data-style") ?? "";
@@ -312,7 +333,10 @@ const defaultStopTypes = [
312
333
  },
313
334
  //handle list items
314
335
  {
315
- deserialize(el, next2) {
336
+ deserialize(node2, next2) {
337
+ if (node2.nodeType !== 1)
338
+ return;
339
+ const el = node2;
316
340
  if (!el.hasChildNodes() || el.tagName.toLowerCase() !== "li")
317
341
  return;
318
342
  const tagsToStyle = {
@@ -346,7 +370,7 @@ const defaultStopTypes = [
346
370
  };
347
371
  }
348
372
  }
349
- ], META_FIELDS$1 = ["_key", "_type", "_id"], languageObjectFieldFilter = (obj, baseLang) => {
373
+ ], META_FIELDS$1 = ["_key", "_type", "_id"], isRecord$2 = (value) => typeof value == "object" && value !== null && !Array.isArray(value), languageObjectFieldFilter = (obj, baseLang) => {
350
374
  const filterToLangField = (childObj) => {
351
375
  const filteredObj = {};
352
376
  return filteredObj[baseLang] = childObj[baseLang], META_FIELDS$1.forEach((field) => {
@@ -360,24 +384,29 @@ const defaultStopTypes = [
360
384
  for (const key in childObj)
361
385
  if (childObj.hasOwnProperty(key)) {
362
386
  const value = childObj[key];
363
- if (value.hasOwnProperty(baseLang))
387
+ if (isRecord$2(value) && Object.hasOwn(value, baseLang))
364
388
  filteredObj[key] = filterToLangField(value);
365
389
  else if (Array.isArray(value) && value.length && typeof value[0] == "object") {
366
- const validLangObjects = value.reduce((validArr, objInArray) => {
367
- if (objInArray._type === "block")
368
- validArr.push(objInArray);
369
- else if (objInArray.hasOwnProperty(baseLang))
370
- validArr.push(filterToLangField(objInArray));
371
- else {
372
- const filtered = findBaseLang(objInArray);
373
- Object.keys(filtered).filter(
374
- (objInArrayKey) => META_FIELDS$1.indexOf(objInArrayKey) === -1
375
- ).length && validArr.push(filtered);
376
- }
377
- return validArr;
378
- }, []);
390
+ const validLangObjects = value.reduce(
391
+ (validArr, objInArray) => {
392
+ if (!isRecord$2(objInArray))
393
+ return validArr;
394
+ if (objInArray._type === "block")
395
+ validArr.push(objInArray);
396
+ else if (Object.hasOwn(objInArray, baseLang))
397
+ validArr.push(filterToLangField(objInArray));
398
+ else {
399
+ const filtered = findBaseLang(objInArray);
400
+ Object.keys(filtered).filter(
401
+ (objInArrayKey) => META_FIELDS$1.indexOf(objInArrayKey) === -1
402
+ ).length && validArr.push(filtered);
403
+ }
404
+ return validArr;
405
+ },
406
+ []
407
+ );
379
408
  validLangObjects.length && (filteredObj[key] = validLangObjects);
380
- } else if (typeof value == "object") {
409
+ } else if (isRecord$2(value)) {
381
410
  const nestedLangObj = findBaseLang(value);
382
411
  Object.keys(nestedLangObj).filter(
383
412
  (nestedObjKey) => META_FIELDS$1.indexOf(nestedObjKey) === -1
@@ -388,18 +417,24 @@ const defaultStopTypes = [
388
417
  };
389
418
  return findBaseLang(obj);
390
419
  }, fieldFilter = (obj, objFields, stopTypes) => {
391
- const filteredObj = { _type: obj._type }, fieldFilterFunc = (field) => field.localize === !1 ? !1 : field.type === "string" || field.type === "text" || Array.isArray(obj[field.name]) ? !0 : !stopTypes.includes(field.type);
420
+ const filteredObj = {
421
+ _type: typeof obj._type == "string" ? obj._type : ""
422
+ }, fieldFilterFunc = (field) => {
423
+ const fieldMetadata = field, fieldType = typeof fieldMetadata.type == "string" ? fieldMetadata.type : fieldMetadata.type?.name;
424
+ return fieldMetadata.localize === !1 ? !1 : fieldType === "string" || fieldType === "text" || Array.isArray(obj[field.name]) ? !0 : !!(fieldType && !stopTypes.includes(fieldType));
425
+ };
392
426
  return [
393
427
  ...META_FIELDS$1,
394
428
  ...objFields.filter(fieldFilterFunc).map((field) => field.name)
395
429
  ].forEach((field) => {
396
430
  obj[field] && (filteredObj[field] = obj[field]);
397
431
  }), filteredObj;
398
- }, META_FIELDS = ["_key", "_type", "_id", "_weak"], BaseDocumentSerializer = (schemas) => {
432
+ }, META_FIELDS = ["_key", "_type", "_id", "_weak"], isRecord$1 = (value) => typeof value == "object" && value !== null && !Array.isArray(value), BaseDocumentSerializer = (schemas) => {
399
433
  const getSchema = (name) => schemas?._original?.types.find((s) => s.name === name), serializeObject = (obj, stopTypes, serializers) => {
400
434
  if (stopTypes.includes(obj._type))
401
435
  return "";
402
- if (serializers.types && Object.keys(serializers.types).includes(obj._type))
436
+ const typeSerializers = isRecord$1(serializers.types) ? serializers.types : {};
437
+ if (Object.keys(typeSerializers).includes(obj._type))
403
438
  return toHtml.toHTML([obj], { components: serializers });
404
439
  if (obj._type === "span" || obj._type === "block")
405
440
  return toHtml.toHTML(obj, { components: serializers });
@@ -420,9 +455,9 @@ const defaultStopTypes = [
420
455
  else if (Array.isArray(value))
421
456
  htmlField = serializeArray(value, fieldName, stopTypes, {
422
457
  ...serializers,
423
- types: { ...serializers.types }
458
+ types: { ...typeSerializers }
424
459
  });
425
- else {
460
+ else if (isRecord$1(value)) {
426
461
  const embeddedObject = value, embeddedObjectSchema = getSchema(embeddedObject._type);
427
462
  let toTranslate = embeddedObject;
428
463
  embeddedObjectSchema && embeddedObjectSchema.fields && (toTranslate = fieldFilter(
@@ -432,7 +467,7 @@ const defaultStopTypes = [
432
467
  ));
433
468
  const objHTML = serializeObject(toTranslate, stopTypes, {
434
469
  ...serializers,
435
- types: { ...serializers.types }
470
+ types: { ...typeSerializers }
436
471
  });
437
472
  htmlField = `<div class="${fieldName}" data-level="field">${objHTML}</div>`;
438
473
  }
@@ -450,7 +485,7 @@ const defaultStopTypes = [
450
485
  components: {
451
486
  ...serializers,
452
487
  types: {
453
- ...serializers.types,
488
+ ...typeSerializers,
454
489
  ...newSerializationMethods
455
490
  }
456
491
  }
@@ -463,9 +498,13 @@ const defaultStopTypes = [
463
498
  return serializedBlock;
464
499
  }, serializeArray = (fieldContent, fieldName, stopTypes, serializers) => {
465
500
  const output = fieldContent.filter(
466
- (block) => !stopTypes.includes(block._type)
501
+ (block) => typeof block == "string" || typeof block._type != "string" || !stopTypes.includes(block._type)
467
502
  ).map((block) => {
468
- const schema2 = getSchema(block._type);
503
+ if (typeof block == "string")
504
+ return block;
505
+ const schema2 = getSchema(
506
+ typeof block._type == "string" ? block._type : ""
507
+ );
469
508
  return schema2 && schema2.fields ? fieldFilter(block, schema2.fields, stopTypes) : block;
470
509
  }).map((obj) => typeof obj == "string" ? `<span>${obj}</span>` : serializeObject(obj, stopTypes, serializers));
471
510
  return `<div class="${fieldName}" data-type="array">${output.join("")}</div>`;
@@ -483,12 +522,14 @@ const defaultStopTypes = [
483
522
  serializedFields[key] = value;
484
523
  else if (Array.isArray(value))
485
524
  serializedFields[key] = serializeArray(
486
- value,
525
+ value.filter(
526
+ (item) => typeof item == "string" || isRecord$1(item)
527
+ ),
487
528
  key,
488
529
  stopTypes,
489
530
  serializers
490
531
  );
491
- else if (value && !stopTypes.find((stopType) => stopType == value?._type)) {
532
+ else if (value && isRecord$1(value) && !stopTypes.find((stopType) => stopType == value?._type)) {
492
533
  const serialized = serializeObject(
493
534
  value,
494
535
  stopTypes,
@@ -534,13 +575,22 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
534
575
  return Array.from(arrayHTML.children).forEach((child) => {
535
576
  let deserializedObject;
536
577
  try {
537
- child.tagName?.toLowerCase() === "span" ? deserializedObject = preprocess(child.innerHTML) : child.className || child.getAttribute("data-type") === "object" ? (deserializedObject = deserializeObject(
538
- child,
539
- deserializers,
540
- blockDeserializers
541
- ), deserializedObject._key = child.id) : (deserializedObject = blockTools.htmlToBlocks(child.outerHTML, blockContentType, {
542
- rules: blockDeserializers
543
- }), deserializedObject = mergeBlocks(deserializedObject), deserializedObject._key = child.id);
578
+ if (child.tagName?.toLowerCase() === "span")
579
+ deserializedObject = preprocess(child.innerHTML);
580
+ else if (child.className || child.getAttribute("data-type") === "object")
581
+ deserializedObject = deserializeObject(
582
+ child,
583
+ deserializers,
584
+ blockDeserializers
585
+ ), deserializedObject && typeof deserializedObject == "object" && !Array.isArray(deserializedObject) && (deserializedObject._key = child.id);
586
+ else {
587
+ const blocks = blockTools.htmlToBlocks(child.outerHTML, blockContentType, {
588
+ rules: blockDeserializers
589
+ });
590
+ deserializedObject = mergeBlocks(
591
+ blocks
592
+ ), deserializedObject._key = child.id;
593
+ }
544
594
  } catch (e) {
545
595
  console.debug(
546
596
  `Tried to deserialize block: ${child.outerHTML} in an array but failed to identify it! Error: ${e}`
@@ -549,7 +599,7 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
549
599
  output.push(deserializedObject);
550
600
  }), output;
551
601
  }, deserializeObject = (objectHTML, deserializers = customDeserializers, blockDeserializers = customBlockDeserializers) => {
552
- const deserialize = deserializers.types[objectHTML.className];
602
+ const deserialize = deserializers.types?.[objectHTML.className];
553
603
  if (deserialize)
554
604
  return deserialize(objectHTML);
555
605
  const output = {};
@@ -576,7 +626,7 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
576
626
  if (HTMLnode?.getAttribute("data-level") === "field" && (HTMLnode = HTMLnode.children[0]), !HTMLnode)
577
627
  return {};
578
628
  let output;
579
- const deserialize = deserializers.types[HTMLnode.className];
629
+ const deserialize = deserializers.types?.[HTMLnode.className];
580
630
  return deserialize ? output = deserialize(HTMLnode) : HTMLnode.getAttribute("data-type") === "object" ? output = deserializeObject(HTMLnode, deserializers, blockDeserializers) : HTMLnode.getAttribute("data-type") === "array" ? output = deserializeArray(HTMLnode, deserializers, blockDeserializers) : (output = {}, console.debug(
581
631
  `Tried to deserialize block ${HTMLnode.outerHTML} but failed to identify it!`
582
632
  )), output;
@@ -615,7 +665,7 @@ function forEachMatchingField(documentId, document2, fields, callback) {
615
665
  });
616
666
  results && results.length > 0 && results.forEach(
617
667
  (result) => {
618
- type !== void 0 ? typeof result.value == "object" && result.value !== null && result.value._type === type && callback(result) : callback(result);
668
+ type !== void 0 ? typeof result.value == "object" && result.value !== null && !Array.isArray(result.value) && result.value._type === type && callback(result) : callback(result);
619
669
  }
620
670
  );
621
671
  } catch (error) {
@@ -649,10 +699,17 @@ function applyDocuments(documentId, sourceDocument, targetDocument, ignore, skip
649
699
  }), deleteMatchingFields(documentId, mergedDocument, skip), mergedDocument;
650
700
  }
651
701
  function dedupeFieldValue(value, localeId) {
652
- return localeId ? typeof value == "string" ? appendLocaleSuffix(value, localeId) : value && typeof value == "object" && !Array.isArray(value) && typeof value.current == "string" ? {
653
- ...value,
654
- current: appendLocaleSuffix(value.current, localeId)
655
- } : value : value;
702
+ if (!localeId) return value;
703
+ if (typeof value == "string")
704
+ return appendLocaleSuffix(value, localeId);
705
+ if (value && typeof value == "object" && !Array.isArray(value) && typeof value.current == "string") {
706
+ const slug = value;
707
+ return {
708
+ ...slug,
709
+ current: appendLocaleSuffix(slug.current, localeId)
710
+ };
711
+ }
712
+ return value;
656
713
  }
657
714
  function appendLocaleSuffix(value, localeId) {
658
715
  if (!value) return value;
@@ -976,7 +1033,9 @@ const documentLevelPatch = async (docInfo, translatedFields, localeId, client, l
976
1033
  baseDoc,
977
1034
  client,
978
1035
  baseLanguage
979
- )).translations.find((translation) => translation.language === localeId)?.value?._ref;
1036
+ )).translations.find(
1037
+ (translation) => translation.language === localeId
1038
+ )?.value?._ref;
980
1039
  i18nDocId && (i18nDoc = await findLatestDraft(i18nDocId, client)), mergeWithTargetLocale && i18nDoc ? baseDoc = i18nDoc : docInfo.documentId && docInfo.versionId && (baseDoc = await findDocumentAtRevision(
981
1040
  docInfo.documentId,
982
1041
  docInfo.versionId,
@@ -1002,7 +1061,9 @@ const documentLevelPatch = async (docInfo, translatedFields, localeId, client, l
1002
1061
  baseDoc,
1003
1062
  client,
1004
1063
  baseLanguage
1005
- ), freshI18nDocId = freshTranslationMetadata.translations.find((translation) => translation.language === localeId)?.value?._ref;
1064
+ ), freshI18nDocId = freshTranslationMetadata.translations.find(
1065
+ (translation) => translation.language === localeId
1066
+ )?.value?._ref;
1006
1067
  if (freshI18nDocId) {
1007
1068
  const freshI18nDoc = await findLatestDraft(freshI18nDocId, client);
1008
1069
  await patchI18nDoc(
@@ -1039,6 +1100,7 @@ async function importDocument(docInfo, localeId, document2, context, mergeWithTa
1039
1100
  mergeWithTargetLocale
1040
1101
  );
1041
1102
  }
1103
+ const isRecord = (value) => typeof value == "object" && value !== null && !Array.isArray(value), isReference = (value) => isRecord(value) && value._type === "reference" && typeof value._ref == "string";
1042
1104
  async function resolveRefs(doc, locale, client) {
1043
1105
  const references = findReferences(doc);
1044
1106
  if (references.length === 0)
@@ -1054,9 +1116,9 @@ function findReferences(obj, path = []) {
1054
1116
  if (!obj || typeof obj != "object")
1055
1117
  return [];
1056
1118
  const references = [];
1057
- return obj._ref && references.push({ ref: obj, path }), Array.isArray(obj) ? obj.forEach((item, index) => {
1119
+ return isReference(obj) && references.push({ ref: obj, path }), Array.isArray(obj) ? obj.forEach((item, index) => {
1058
1120
  references.push(...findReferences(item, [...path, index.toString()]));
1059
- }) : Object.keys(obj).forEach((key) => {
1121
+ }) : isRecord(obj) && Object.keys(obj).forEach((key) => {
1060
1122
  references.push(...findReferences(obj[key], [...path, key]));
1061
1123
  }), references;
1062
1124
  }
@@ -1080,7 +1142,7 @@ function updateDocumentReferences(doc, translatedRefs) {
1080
1142
  function updateReferencesRecursive(obj, translatedRefs) {
1081
1143
  if (!obj || typeof obj != "object")
1082
1144
  return obj;
1083
- if (obj._ref && translatedRefs.has(obj._ref))
1145
+ if (isReference(obj) && translatedRefs.has(obj._ref))
1084
1146
  return {
1085
1147
  ...obj,
1086
1148
  _ref: translatedRefs.get(obj._ref)
@@ -1089,7 +1151,10 @@ function updateReferencesRecursive(obj, translatedRefs) {
1089
1151
  return obj.map((item) => updateReferencesRecursive(item, translatedRefs));
1090
1152
  const updated = {};
1091
1153
  return Object.keys(obj).forEach((key) => {
1092
- updated[key] = updateReferencesRecursive(obj[key], translatedRefs);
1154
+ updated[key] = updateReferencesRecursive(
1155
+ obj[key],
1156
+ translatedRefs
1157
+ );
1093
1158
  }), updated;
1094
1159
  }
1095
1160
  async function findTranslatedDocumentForLocale(sourceDocumentId, localeId, client) {
@@ -1202,16 +1267,19 @@ async function getReadyFilesForImport(translationStatuses, options = {}) {
1202
1267
  async function importTranslations(readyFiles, secrets, translationContext, options = {}) {
1203
1268
  if (readyFiles.length === 0)
1204
1269
  return { successCount: 0, failureCount: 0, successfulImports: [] };
1205
- const importItems = (await downloadTranslations(readyFiles, secrets)).map((file) => ({
1206
- docInfo: {
1207
- documentId: file.fileId,
1208
- versionId: file.versionId
1209
- },
1210
- locale: file.locale,
1211
- data: file.data,
1212
- translationContext,
1213
- key: `${file.branchId}:${file.fileId}:${file.versionId}:${file.locale}`
1214
- })), result = await processImportBatch(importItems, {
1270
+ const importItems = (await downloadTranslations(readyFiles, secrets)).map((file) => {
1271
+ const data = typeof file.data == "string" ? file.data : JSON.stringify(file.data ?? "");
1272
+ return {
1273
+ docInfo: {
1274
+ documentId: file.fileId,
1275
+ versionId: file.versionId
1276
+ },
1277
+ locale: file.locale,
1278
+ data,
1279
+ translationContext,
1280
+ key: `${file.branchId}:${file.fileId}:${file.versionId}:${file.locale}`
1281
+ };
1282
+ }), result = await processImportBatch(importItems, {
1215
1283
  onProgress: options.onProgress,
1216
1284
  onItemSuccess: (item, key) => {
1217
1285
  options.onImportSuccess?.(key);