@stackbit/cms-core 0.0.19-alpha.0 → 0.0.19-alpha.1

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.
@@ -17,10 +17,7 @@ import {
17
17
  } from '@stackbit/sdk';
18
18
  import { mapPromise, omitByNil } from '@stackbit/utils';
19
19
  import * as CSITypes from './content-source-interface';
20
- import {
21
- DocumentObjectField,
22
- isLocalizedField
23
- } from './content-source-interface';
20
+ import { isLocalizedField } from './content-source-interface';
24
21
  import * as ContentStoreTypes from './content-store-types';
25
22
  import { IMAGE_MODEL } from './common/common-schema';
26
23
  import { Timer } from './utils/timer';
@@ -411,7 +408,7 @@ export class ContentStore {
411
408
  const dataIndex = contentSourceData.documents.findIndex((existingDoc) => existingDoc.srcObjectId === document.srcObjectId);
412
409
  if (dataIndex === -1) {
413
410
  contentSourceData.documents.push(document);
414
- contentSourceData.csiDocuments.push(csiDocument)
411
+ contentSourceData.csiDocuments.push(csiDocument);
415
412
  } else {
416
413
  // the indexes of documents and csiDocuments are always the same as they are always updated at the same time
417
414
  contentSourceData.documents.splice(dataIndex, 1, document);
@@ -1283,30 +1280,34 @@ function mapCSIDocumentToStoreDocument({
1283
1280
  fields: mapCSIFieldsToStoreFields({
1284
1281
  csiDocumentFields: csiDocument.fields,
1285
1282
  modelFields: model.fields ?? [],
1286
- modelMap,
1287
- defaultLocaleCode
1283
+ context: {
1284
+ modelMap,
1285
+ defaultLocaleCode
1286
+ }
1288
1287
  })
1289
1288
  };
1290
1289
  }
1291
1290
 
1291
+ type MapContext = {
1292
+ modelMap: Record<string, Model>;
1293
+ defaultLocaleCode?: string;
1294
+ };
1295
+
1292
1296
  function mapCSIFieldsToStoreFields({
1293
1297
  csiDocumentFields,
1294
1298
  modelFields,
1295
- modelMap,
1296
- defaultLocaleCode
1299
+ context
1297
1300
  }: {
1298
1301
  csiDocumentFields: Record<string, CSITypes.DocumentField>;
1299
1302
  modelFields: Field[];
1300
- modelMap: Record<string, Model>;
1301
- defaultLocaleCode?: string;
1303
+ context: MapContext;
1302
1304
  }): Record<string, ContentStoreTypes.DocumentField> {
1303
1305
  return modelFields.reduce((result: Record<string, ContentStoreTypes.DocumentField>, modelField) => {
1304
1306
  const csiDocumentField = csiDocumentFields[modelField.name];
1305
- const docField = mapSourceFieldToStoreField({
1307
+ const docField = mapCSIFieldToStoreField({
1306
1308
  csiDocumentField,
1307
1309
  modelField,
1308
- modelMap,
1309
- defaultLocaleCode
1310
+ context
1310
1311
  });
1311
1312
  docField.label = modelField.label;
1312
1313
  result[modelField.name] = docField;
@@ -1314,16 +1315,14 @@ function mapCSIFieldsToStoreFields({
1314
1315
  }, {});
1315
1316
  }
1316
1317
 
1317
- function mapSourceFieldToStoreField({
1318
+ function mapCSIFieldToStoreField({
1318
1319
  csiDocumentField,
1319
1320
  modelField,
1320
- modelMap,
1321
- defaultLocaleCode
1321
+ context
1322
1322
  }: {
1323
1323
  csiDocumentField: CSITypes.DocumentField | undefined;
1324
1324
  modelField: FieldSpecificProps;
1325
- modelMap: Record<string, Model>;
1326
- defaultLocaleCode?: string;
1325
+ context: MapContext;
1327
1326
  }): ContentStoreTypes.DocumentField {
1328
1327
  if (!csiDocumentField) {
1329
1328
  const isUnset = ['object', 'model', 'reference', 'richText', 'markdown', 'image', 'file', 'json'].includes(modelField.type);
@@ -1336,11 +1335,11 @@ function mapSourceFieldToStoreField({
1336
1335
  // TODO: check if need to add "options" to "enum" and subtype/min/max to "number"
1337
1336
  switch (modelField.type) {
1338
1337
  case 'object':
1339
- return mapObjectField(csiDocumentField as CSITypes.DocumentObjectField, modelField, modelMap, defaultLocaleCode);
1338
+ return mapObjectField(csiDocumentField as CSITypes.DocumentObjectField, modelField, context);
1340
1339
  case 'model':
1341
- return mapModelField(csiDocumentField as CSITypes.DocumentModelField, modelField, modelMap, defaultLocaleCode);
1340
+ return mapModelField(csiDocumentField as CSITypes.DocumentModelField, modelField, context);
1342
1341
  case 'list':
1343
- return mapListField(csiDocumentField as CSITypes.DocumentListField, modelField, modelMap, defaultLocaleCode);
1342
+ return mapListField(csiDocumentField as CSITypes.DocumentListField, modelField, context);
1344
1343
  case 'richText':
1345
1344
  return mapRichTextField(csiDocumentField as CSITypes.DocumentRichTextField);
1346
1345
  case 'markdown':
@@ -1353,18 +1352,16 @@ function mapSourceFieldToStoreField({
1353
1352
  function mapObjectField(
1354
1353
  csiDocumentField: CSITypes.DocumentObjectField,
1355
1354
  modelField: FieldObjectProps,
1356
- modelMap: Record<string, Model>,
1357
- defaultLocaleCode?: string
1355
+ context: MapContext
1358
1356
  ): ContentStoreTypes.DocumentObjectField {
1359
1357
  if (!isLocalizedField(csiDocumentField)) {
1360
1358
  return {
1361
1359
  type: csiDocumentField.type,
1362
- srcObjectLabel: getObjectLabel(csiDocumentField.fields ?? {}, modelField ?? [], defaultLocaleCode),
1360
+ srcObjectLabel: getObjectLabel(csiDocumentField.fields ?? {}, modelField ?? [], context.defaultLocaleCode),
1363
1361
  fields: mapCSIFieldsToStoreFields({
1364
1362
  csiDocumentFields: csiDocumentField.fields ?? {},
1365
1363
  modelFields: modelField.fields ?? [],
1366
- modelMap,
1367
- defaultLocaleCode
1364
+ context
1368
1365
  })
1369
1366
  };
1370
1367
  }
@@ -1378,32 +1375,25 @@ function mapObjectField(
1378
1375
  fields: mapCSIFieldsToStoreFields({
1379
1376
  csiDocumentFields: locale.fields ?? {},
1380
1377
  modelFields: modelField.fields ?? [],
1381
- modelMap,
1382
- defaultLocaleCode
1378
+ context
1383
1379
  })
1384
1380
  };
1385
1381
  })
1386
1382
  };
1387
1383
  }
1388
1384
 
1389
- function mapModelField(
1390
- csiDocumentField: CSITypes.DocumentModelField,
1391
- modelField: FieldModelProps,
1392
- modelMap: Record<string, Model>,
1393
- defaultLocaleCode?: string
1394
- ): ContentStoreTypes.DocumentModelField {
1385
+ function mapModelField(csiDocumentField: CSITypes.DocumentModelField, modelField: FieldModelProps, context: MapContext): ContentStoreTypes.DocumentModelField {
1395
1386
  if (!isLocalizedField(csiDocumentField)) {
1396
- const model = modelMap[csiDocumentField.modelName]!;
1387
+ const model = context.modelMap[csiDocumentField.modelName]!;
1397
1388
  return {
1398
1389
  type: csiDocumentField.type,
1399
- srcObjectLabel: getObjectLabel(csiDocumentField.fields ?? {}, model, defaultLocaleCode),
1390
+ srcObjectLabel: getObjectLabel(csiDocumentField.fields ?? {}, model, context.defaultLocaleCode),
1400
1391
  srcModelName: csiDocumentField.modelName,
1401
1392
  srcModelLabel: model.label ?? _.startCase(model.name),
1402
1393
  fields: mapCSIFieldsToStoreFields({
1403
1394
  csiDocumentFields: csiDocumentField.fields ?? {},
1404
1395
  modelFields: model.fields ?? [],
1405
- modelMap,
1406
- defaultLocaleCode
1396
+ context
1407
1397
  })
1408
1398
  };
1409
1399
  }
@@ -1411,7 +1401,7 @@ function mapModelField(
1411
1401
  type: csiDocumentField.type,
1412
1402
  localized: true,
1413
1403
  locales: _.mapValues(csiDocumentField.locales, (locale) => {
1414
- const model = modelMap[locale.modelName]!;
1404
+ const model = context.modelMap[locale.modelName]!;
1415
1405
  return {
1416
1406
  locale: locale.locale,
1417
1407
  srcObjectLabel: getObjectLabel(locale.fields ?? {}, model, locale.locale),
@@ -1420,29 +1410,22 @@ function mapModelField(
1420
1410
  fields: mapCSIFieldsToStoreFields({
1421
1411
  csiDocumentFields: locale.fields ?? {},
1422
1412
  modelFields: model.fields ?? [],
1423
- modelMap,
1424
- defaultLocaleCode
1413
+ context
1425
1414
  })
1426
1415
  };
1427
1416
  })
1428
1417
  };
1429
1418
  }
1430
1419
 
1431
- function mapListField(
1432
- csiDocumentField: CSITypes.DocumentListField,
1433
- modelField: FieldListProps,
1434
- modelMap: Record<string, Model>,
1435
- defaultLocaleCode?: string
1436
- ): ContentStoreTypes.DocumentListField {
1420
+ function mapListField(csiDocumentField: CSITypes.DocumentListField, modelField: FieldListProps, context: MapContext): ContentStoreTypes.DocumentListField {
1437
1421
  if (!isLocalizedField(csiDocumentField)) {
1438
1422
  return {
1439
1423
  type: csiDocumentField.type,
1440
1424
  items: csiDocumentField.items.map((item) =>
1441
- mapSourceFieldToStoreField({
1425
+ mapCSIFieldToStoreField({
1442
1426
  csiDocumentField: item,
1443
1427
  modelField: modelField.items ?? { type: 'string' },
1444
- modelMap,
1445
- defaultLocaleCode
1428
+ context
1446
1429
  })
1447
1430
  )
1448
1431
  };
@@ -1454,11 +1437,10 @@ function mapListField(
1454
1437
  return {
1455
1438
  locale: locale.locale,
1456
1439
  items: (locale.items ?? []).map((item) =>
1457
- mapSourceFieldToStoreField({
1440
+ mapCSIFieldToStoreField({
1458
1441
  csiDocumentField: item,
1459
1442
  modelField: modelField.items ?? { type: 'string' },
1460
- modelMap,
1461
- defaultLocaleCode
1443
+ context
1462
1444
  })
1463
1445
  )
1464
1446
  };
@@ -1772,166 +1754,12 @@ async function createNestedObjectRecursively({
1772
1754
  userContext: unknown;
1773
1755
  contentSourceInstance: CSITypes.ContentSourceInterface;
1774
1756
  }): Promise<{
1775
- fields: Record<string, CSITypes.DocumentFieldNonLocalized>;
1757
+ fields: Record<string, CSITypes.UpdateOperationField>;
1776
1758
  newRefDocuments: CSITypes.Document[];
1777
1759
  }> {
1778
- const createNestedField = async ({
1779
- value,
1780
- modelField,
1781
- fieldPath
1782
- }: {
1783
- value: any;
1784
- modelField: FieldSpecificProps;
1785
- fieldPath: (string | number)[];
1786
- }): Promise<{ field: CSITypes.DocumentFieldNonLocalized; newRefDocuments: CSITypes.Document[] }> => {
1787
- if (modelField.type === 'object') {
1788
- const result = await createNestedObjectRecursively({
1789
- object: value,
1790
- modelFields: modelField.fields,
1791
- fieldPath,
1792
- modelMap,
1793
- locale,
1794
- userContext,
1795
- contentSourceInstance
1796
- });
1797
- return {
1798
- field: {
1799
- type: 'object',
1800
- fields: result.fields
1801
- },
1802
- newRefDocuments: result.newRefDocuments
1803
- };
1804
- } else if (modelField.type === 'model') {
1805
- let { $$type, ...rest } = value;
1806
- const modelNames = modelField.models;
1807
- // for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
1808
- // the 'type' property in default values
1809
- if (!$$type && 'type' in rest) {
1810
- $$type = rest.type;
1811
- rest = _.omit(rest, 'type');
1812
- }
1813
- const modelName = $$type ?? (modelNames.length === 1 ? modelNames[0] : null);
1814
- if (!modelName) {
1815
- throw new Error(`no $$type was specified for nested model`);
1816
- }
1817
- const model = modelMap[modelName];
1818
- if (!model) {
1819
- throw new Error(`no model with name '${modelName}' was found`);
1820
- }
1821
- const result = await createNestedObjectRecursively({
1822
- object: rest,
1823
- modelFields: model.fields ?? [],
1824
- fieldPath,
1825
- modelMap,
1826
- locale,
1827
- userContext,
1828
- contentSourceInstance
1829
- });
1830
- return {
1831
- field: {
1832
- type: 'model',
1833
- modelName: modelName,
1834
- fields: result.fields
1835
- },
1836
- newRefDocuments: result.newRefDocuments
1837
- };
1838
- } else if (modelField.type === 'image') {
1839
- let refId: string | undefined;
1840
- if (_.isPlainObject(value)) {
1841
- refId = value.$$ref;
1842
- } else {
1843
- refId = value;
1844
- }
1845
- if (!refId) {
1846
- throw new Error(`reference field must specify a value`);
1847
- }
1848
- return {
1849
- field: {
1850
- type: 'reference',
1851
- refType: 'asset',
1852
- refId: refId
1853
- },
1854
- newRefDocuments: []
1855
- };
1856
- } else if (modelField.type === 'reference') {
1857
- let { $$ref: refId = null, $$type: modelName = null, ...rest } = _.isPlainObject(value) ? value : { $$ref: value };
1858
- if (refId) {
1859
- return {
1860
- field: {
1861
- type: 'reference',
1862
- refType: 'document',
1863
- refId: refId
1864
- },
1865
- newRefDocuments: []
1866
- };
1867
- } else {
1868
- const modelNames = modelField.models;
1869
- if (!modelName) {
1870
- // for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
1871
- // the 'type' property in default values
1872
- if ('type' in rest) {
1873
- modelName = rest.type;
1874
- rest = _.omit(rest, 'type');
1875
- } else if (modelNames.length === 1) {
1876
- modelName = modelNames[0];
1877
- }
1878
- }
1879
- const model = modelMap[modelName];
1880
- if (!model) {
1881
- throw new Error(`no model with name '${modelName}' was found`);
1882
- }
1883
- const { document, newRefDocuments } = await createDocumentRecursively({
1884
- object: rest,
1885
- model: model,
1886
- modelMap,
1887
- locale,
1888
- userContext,
1889
- contentSourceInstance
1890
- });
1891
- return {
1892
- field: {
1893
- type: 'reference',
1894
- refType: 'document',
1895
- refId: document.id
1896
- },
1897
- newRefDocuments: [document, ...newRefDocuments]
1898
- };
1899
- }
1900
- } else if (modelField.type === 'list') {
1901
- if (!Array.isArray(value)) {
1902
- throw new Error(`value for list field must be array`);
1903
- }
1904
- const itemsField = modelField.items;
1905
- if (!itemsField) {
1906
- throw new Error(`list field does not define items`);
1907
- }
1908
- const arrayResult = await mapPromise(value, async (item, index) => {
1909
- return createNestedField({
1910
- value: item,
1911
- modelField: itemsField,
1912
- fieldPath: fieldPath.concat(index)
1913
- });
1914
- });
1915
- return {
1916
- field: {
1917
- type: 'list',
1918
- items: arrayResult.map((result) => result.field)
1919
- },
1920
- newRefDocuments: arrayResult.reduce((result: CSITypes.Document[], { newRefDocuments }) => result.concat(newRefDocuments), [])
1921
- };
1922
- }
1923
- return {
1924
- field: {
1925
- type: modelField.type,
1926
- value: value
1927
- } as CSITypes.DocumentFieldNonLocalized,
1928
- newRefDocuments: []
1929
- };
1930
- };
1931
-
1932
1760
  object = object ?? {};
1933
1761
  const result: {
1934
- fields: Record<string, CSITypes.DocumentFieldNonLocalized>;
1762
+ fields: Record<string, CSITypes.UpdateOperationField>;
1935
1763
  newRefDocuments: CSITypes.Document[];
1936
1764
  } = {
1937
1765
  fields: {},
@@ -1953,7 +1781,11 @@ async function createNestedObjectRecursively({
1953
1781
  const fieldResult = await createNestedField({
1954
1782
  value,
1955
1783
  modelField,
1956
- fieldPath: fieldPath.concat(fieldName)
1784
+ fieldPath: fieldPath.concat(fieldName),
1785
+ modelMap,
1786
+ locale,
1787
+ userContext,
1788
+ contentSourceInstance
1957
1789
  });
1958
1790
  result.fields[fieldName] = fieldResult.field;
1959
1791
  result.newRefDocuments = result.newRefDocuments.concat(fieldResult.newRefDocuments);
@@ -1966,6 +1798,172 @@ async function createNestedObjectRecursively({
1966
1798
  return result;
1967
1799
  }
1968
1800
 
1801
+ async function createNestedField({
1802
+ value,
1803
+ modelField,
1804
+ fieldPath,
1805
+ modelMap,
1806
+ locale,
1807
+ userContext,
1808
+ contentSourceInstance
1809
+ }: {
1810
+ value: any;
1811
+ modelField: FieldSpecificProps;
1812
+ fieldPath: (string | number)[];
1813
+ modelMap: Record<string, Model>;
1814
+ locale?: string;
1815
+ userContext: unknown;
1816
+ contentSourceInstance: CSITypes.ContentSourceInterface;
1817
+ }): Promise<{ field: CSITypes.UpdateOperationField; newRefDocuments: CSITypes.Document[] }> {
1818
+ if (modelField.type === 'object') {
1819
+ const result = await createNestedObjectRecursively({
1820
+ object: value,
1821
+ modelFields: modelField.fields,
1822
+ fieldPath,
1823
+ modelMap,
1824
+ locale,
1825
+ userContext,
1826
+ contentSourceInstance
1827
+ });
1828
+ return {
1829
+ field: {
1830
+ type: 'object',
1831
+ fields: result.fields
1832
+ },
1833
+ newRefDocuments: result.newRefDocuments
1834
+ };
1835
+ } else if (modelField.type === 'model') {
1836
+ let { $$type, ...rest } = value;
1837
+ const modelNames = modelField.models;
1838
+ // for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
1839
+ // the 'type' property in default values
1840
+ if (!$$type && 'type' in rest) {
1841
+ $$type = rest.type;
1842
+ rest = _.omit(rest, 'type');
1843
+ }
1844
+ const modelName = $$type ?? (modelNames.length === 1 ? modelNames[0] : null);
1845
+ if (!modelName) {
1846
+ throw new Error(`no $$type was specified for nested model`);
1847
+ }
1848
+ const model = modelMap[modelName];
1849
+ if (!model) {
1850
+ throw new Error(`no model with name '${modelName}' was found`);
1851
+ }
1852
+ const result = await createNestedObjectRecursively({
1853
+ object: rest,
1854
+ modelFields: model.fields ?? [],
1855
+ fieldPath,
1856
+ modelMap,
1857
+ locale,
1858
+ userContext,
1859
+ contentSourceInstance
1860
+ });
1861
+ return {
1862
+ field: {
1863
+ type: 'model',
1864
+ modelName: modelName,
1865
+ fields: result.fields
1866
+ },
1867
+ newRefDocuments: result.newRefDocuments
1868
+ };
1869
+ } else if (modelField.type === 'image') {
1870
+ let refId: string | undefined;
1871
+ if (_.isPlainObject(value)) {
1872
+ refId = value.$$ref;
1873
+ } else {
1874
+ refId = value;
1875
+ }
1876
+ if (!refId) {
1877
+ throw new Error(`reference field must specify a value`);
1878
+ }
1879
+ return {
1880
+ field: {
1881
+ type: 'reference',
1882
+ refType: 'asset',
1883
+ refId: refId
1884
+ },
1885
+ newRefDocuments: []
1886
+ };
1887
+ } else if (modelField.type === 'reference') {
1888
+ let { $$ref: refId = null, $$type: modelName = null, ...rest } = _.isPlainObject(value) ? value : { $$ref: value };
1889
+ if (refId) {
1890
+ return {
1891
+ field: {
1892
+ type: 'reference',
1893
+ refType: 'document',
1894
+ refId: refId
1895
+ },
1896
+ newRefDocuments: []
1897
+ };
1898
+ } else {
1899
+ const modelNames = modelField.models;
1900
+ if (!modelName) {
1901
+ // for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
1902
+ // the 'type' property in default values
1903
+ if ('type' in rest) {
1904
+ modelName = rest.type;
1905
+ rest = _.omit(rest, 'type');
1906
+ } else if (modelNames.length === 1) {
1907
+ modelName = modelNames[0];
1908
+ }
1909
+ }
1910
+ const model = modelMap[modelName];
1911
+ if (!model) {
1912
+ throw new Error(`no model with name '${modelName}' was found`);
1913
+ }
1914
+ const { document, newRefDocuments } = await createDocumentRecursively({
1915
+ object: rest,
1916
+ model: model,
1917
+ modelMap,
1918
+ locale,
1919
+ userContext,
1920
+ contentSourceInstance
1921
+ });
1922
+ return {
1923
+ field: {
1924
+ type: 'reference',
1925
+ refType: 'document',
1926
+ refId: document.id
1927
+ },
1928
+ newRefDocuments: [document, ...newRefDocuments]
1929
+ };
1930
+ }
1931
+ } else if (modelField.type === 'list') {
1932
+ if (!Array.isArray(value)) {
1933
+ throw new Error(`value for list field must be array`);
1934
+ }
1935
+ const itemsField = modelField.items;
1936
+ if (!itemsField) {
1937
+ throw new Error(`list field does not define items`);
1938
+ }
1939
+ const arrayResult = await mapPromise(value, async (item, index) => {
1940
+ return createNestedField({
1941
+ value: item,
1942
+ modelField: itemsField,
1943
+ fieldPath: fieldPath.concat(index),
1944
+ modelMap,
1945
+ locale,
1946
+ userContext,
1947
+ contentSourceInstance
1948
+ });
1949
+ });
1950
+ return {
1951
+ field: {
1952
+ type: 'list',
1953
+ items: arrayResult.map((result) => result.field)
1954
+ },
1955
+ newRefDocuments: arrayResult.reduce((result: CSITypes.Document[], { newRefDocuments }) => result.concat(newRefDocuments), [])
1956
+ };
1957
+ }
1958
+ return {
1959
+ field: {
1960
+ type: modelField.type,
1961
+ value: value
1962
+ },
1963
+ newRefDocuments: []
1964
+ };
1965
+ }
1966
+
1969
1967
  function getModelFieldForFieldAtPath(
1970
1968
  document: ContentStoreTypes.Document,
1971
1969
  model: Model,
@@ -2093,12 +2091,13 @@ async function convertOperationField({
2093
2091
  userContext: unknown;
2094
2092
  contentSourceInstance: CSITypes.ContentSourceInterface;
2095
2093
  }): Promise<CSITypes.UpdateOperationField> {
2096
- let result;
2094
+ // for insert operations, the modelField will be of the list, so get the modelField of the list items
2095
+ const modelFieldOrListItems: FieldSpecificProps = modelField.type === 'list' ? modelField.items! : modelField;
2097
2096
  switch (operationField.type) {
2098
- case 'object':
2099
- result = await createNestedObjectRecursively({
2097
+ case 'object': {
2098
+ const result = await createNestedObjectRecursively({
2100
2099
  object: operationField.object,
2101
- modelFields: (modelField as FieldObjectProps).fields,
2100
+ modelFields: (modelFieldOrListItems as FieldObjectProps).fields,
2102
2101
  fieldPath: fieldPath,
2103
2102
  modelMap,
2104
2103
  locale,
@@ -2109,12 +2108,13 @@ async function convertOperationField({
2109
2108
  type: operationField.type,
2110
2109
  fields: result.fields
2111
2110
  };
2112
- case 'model':
2111
+ }
2112
+ case 'model': {
2113
2113
  const model = modelMap[operationField.modelName];
2114
2114
  if (!model) {
2115
2115
  throw new Error(`error updating document, could not find document model: '${operationField.modelName}'`);
2116
2116
  }
2117
- result = await createNestedObjectRecursively({
2117
+ const result = await createNestedObjectRecursively({
2118
2118
  object: operationField.object,
2119
2119
  modelFields: model.fields!,
2120
2120
  fieldPath,
@@ -2128,6 +2128,54 @@ async function convertOperationField({
2128
2128
  modelName: operationField.modelName,
2129
2129
  fields: result.fields
2130
2130
  };
2131
+ }
2132
+ case 'list': {
2133
+ if (modelField.type !== 'list') {
2134
+ throw new Error(`'the operation field type '${operationField.type}' does not match the model field type '${modelField.type}'`);
2135
+ }
2136
+ const result = await mapPromise(operationField.items, async (item, index) => {
2137
+ const result = await createNestedField({
2138
+ value: item,
2139
+ modelField: modelField.items!,
2140
+ fieldPath,
2141
+ modelMap,
2142
+ locale,
2143
+ userContext,
2144
+ contentSourceInstance
2145
+ });
2146
+ return result.field;
2147
+ });
2148
+ return {
2149
+ type: operationField.type,
2150
+ items: result
2151
+ };
2152
+ }
2153
+ case 'string':
2154
+ if (typeof operationField.value !== 'string') {
2155
+ return {
2156
+ type: operationField.type,
2157
+ value: ''
2158
+ };
2159
+ }
2160
+ return operationField as CSITypes.UpdateOperationField;
2161
+ case 'enum':
2162
+ if (typeof operationField.value !== 'string') {
2163
+ if (modelFieldOrListItems.type !== 'enum') {
2164
+ throw new Error(`'the operation field type 'enum' does not match the model field type '${modelFieldOrListItems.type}'`);
2165
+ }
2166
+ const option = modelFieldOrListItems.options[0]!;
2167
+ const optionValue = typeof option === 'object' ? option.value : option;
2168
+ return {
2169
+ type: operationField.type,
2170
+ value: optionValue
2171
+ };
2172
+ }
2173
+ return operationField as CSITypes.UpdateOperationField;
2174
+ case 'image':
2175
+ if (typeof operationField.value !== 'string') {
2176
+ throw new Error('image value was not specified');
2177
+ }
2178
+ return operationField as CSITypes.UpdateOperationField;
2131
2179
  default:
2132
2180
  return operationField as CSITypes.UpdateOperationField;
2133
2181
  }