@stackbit/cms-core 0.1.2 → 0.1.3-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/content-source-interface.d.ts +3 -11
  2. package/dist/content-source-interface.d.ts.map +1 -1
  3. package/dist/content-source-interface.js.map +1 -1
  4. package/dist/content-store-types.d.ts +15 -24
  5. package/dist/content-store-types.d.ts.map +1 -1
  6. package/dist/content-store-utils.d.ts +9 -0
  7. package/dist/content-store-utils.d.ts.map +1 -0
  8. package/dist/content-store-utils.js +139 -0
  9. package/dist/content-store-utils.js.map +1 -0
  10. package/dist/content-store.d.ts +0 -1
  11. package/dist/content-store.d.ts.map +1 -1
  12. package/dist/content-store.js +95 -945
  13. package/dist/content-store.js.map +1 -1
  14. package/dist/utils/create-update-csi-docs.d.ts +68 -0
  15. package/dist/utils/create-update-csi-docs.d.ts.map +1 -0
  16. package/dist/utils/create-update-csi-docs.js +376 -0
  17. package/dist/utils/create-update-csi-docs.js.map +1 -0
  18. package/dist/utils/csi-to-store-docs-converter.d.ts +15 -0
  19. package/dist/utils/csi-to-store-docs-converter.d.ts.map +1 -0
  20. package/dist/utils/csi-to-store-docs-converter.js +287 -0
  21. package/dist/utils/csi-to-store-docs-converter.js.map +1 -0
  22. package/dist/utils/store-to-api-docs-converter.d.ts +5 -0
  23. package/dist/utils/store-to-api-docs-converter.d.ts.map +1 -0
  24. package/dist/utils/store-to-api-docs-converter.js +247 -0
  25. package/dist/utils/store-to-api-docs-converter.js.map +1 -0
  26. package/package.json +4 -4
  27. package/src/content-source-interface.ts +4 -13
  28. package/src/content-store-types.ts +12 -10
  29. package/src/content-store-utils.ts +149 -0
  30. package/src/content-store.ts +53 -1073
  31. package/src/index.ts +1 -1
  32. package/src/utils/create-update-csi-docs.ts +440 -0
  33. package/src/utils/csi-to-store-docs-converter.ts +365 -0
  34. package/src/utils/store-to-api-docs-converter.ts +246 -0
@@ -3,16 +3,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getContentSourceId = exports.ContentStore = void 0;
6
+ exports.ContentStore = void 0;
7
7
  const lodash_1 = __importDefault(require("lodash"));
8
- const slugify_1 = __importDefault(require("slugify"));
9
8
  const path_1 = __importDefault(require("path"));
10
9
  const sanitize_filename_1 = __importDefault(require("sanitize-filename"));
11
10
  const sdk_1 = require("@stackbit/sdk");
12
11
  const utils_1 = require("@stackbit/utils");
13
- const content_source_interface_1 = require("./content-source-interface");
14
- const common_schema_1 = require("./common/common-schema");
15
12
  const timer_1 = require("./utils/timer");
13
+ const content_source_interface_1 = require("./content-source-interface");
14
+ const csi_to_store_docs_converter_1 = require("./utils/csi-to-store-docs-converter");
15
+ const content_store_utils_1 = require("./content-store-utils");
16
+ const store_to_api_docs_converter_1 = require("./utils/store-to-api-docs-converter");
17
+ const create_update_csi_docs_1 = require("./utils/create-update-csi-docs");
16
18
  class ContentStore {
17
19
  constructor(options) {
18
20
  this.contentSources = [];
@@ -40,7 +42,7 @@ class ContentStore {
40
42
  thisArg: this,
41
43
  // Group the deferred calls by content source ID.
42
44
  groupResolver: ({ contentSourceInstance }) => {
43
- return getContentSourceIdForContentSource(contentSourceInstance);
45
+ return (0, content_store_utils_1.getContentSourceIdForContentSource)(contentSourceInstance);
44
46
  },
45
47
  // When the loadContentSourceData call is called multiple times with
46
48
  // different "init" values, ensure that the deferred call will be
@@ -145,7 +147,7 @@ class ContentStore {
145
147
  deletedAssets: []
146
148
  };
147
149
  for (const contentSourceInstance of this.contentSources) {
148
- const contentSourceId = getContentSourceIdForContentSource(contentSourceInstance);
150
+ const contentSourceId = (0, content_store_utils_1.getContentSourceIdForContentSource)(contentSourceInstance);
149
151
  this.logger.debug(`call onFilesChange for contentSource: ${contentSourceId}`);
150
152
  const { schemaChanged, contentChangeEvent } = (_b = (_a = contentSourceInstance.onFilesChange) === null || _a === void 0 ? void 0 : _a.call(contentSourceInstance, { updatedFiles: updatedFiles })) !== null && _b !== void 0 ? _b : {};
151
153
  this.logger.debug(`schemaChanged: ${schemaChanged}, has contentChangeEvent: ${!!contentChangeEvent}`);
@@ -185,8 +187,8 @@ class ContentStore {
185
187
  this.contentUpdatesWatchTimer.startTimer();
186
188
  }
187
189
  async loadContentSourceData({ contentSourceInstance, init }) {
188
- var _a, _b, _c, _d;
189
- const contentSourceId = getContentSourceIdForContentSource(contentSourceInstance);
190
+ var _a, _b, _c, _d, _e;
191
+ const contentSourceId = (0, content_store_utils_1.getContentSourceIdForContentSource)(contentSourceInstance);
190
192
  this.logger.debug('loadContentSourceData', { contentSourceId, init });
191
193
  if (init) {
192
194
  await contentSourceInstance.init({
@@ -219,10 +221,19 @@ class ContentStore {
219
221
  models = (_c = config === null || config === void 0 ? void 0 : config.models) !== null && _c !== void 0 ? _c : [];
220
222
  // TODO: load presets externally from config, and create additional map
221
223
  // that maps presetIds by model name instead of storing that map inside every model
222
- // TODO: adjust presets to have srcType and srcProjectId
223
- this.presets = config === null || config === void 0 ? void 0 : config.presets;
224
+ // Augment presets with srcType and srcProjectId if they don't exist
225
+ this.presets = lodash_1.default.reduce(Object.keys((_d = config === null || config === void 0 ? void 0 : config.presets) !== null && _d !== void 0 ? _d : {}), (accum, presetId) => {
226
+ var _a, _b, _c;
227
+ const preset = (_a = config === null || config === void 0 ? void 0 : config.presets) === null || _a === void 0 ? void 0 : _a[presetId];
228
+ lodash_1.default.set(accum, [presetId], {
229
+ ...preset,
230
+ srcType: (_b = preset === null || preset === void 0 ? void 0 : preset.srcType) !== null && _b !== void 0 ? _b : contentSourceInstance.getContentSourceType(),
231
+ srcProjectId: (_c = preset === null || preset === void 0 ? void 0 : preset.srcProjectId) !== null && _c !== void 0 ? _c : contentSourceInstance.getProjectId()
232
+ });
233
+ return accum;
234
+ }, {});
224
235
  }
225
- if ((_d = this.rawStackbitConfig) === null || _d === void 0 ? void 0 : _d.mapModels) {
236
+ if ((_e = this.rawStackbitConfig) === null || _e === void 0 ? void 0 : _e.mapModels) {
226
237
  models = this.rawStackbitConfig.mapModels({
227
238
  models: models,
228
239
  contentSourceType: contentSourceInstance.getContentSourceType(),
@@ -235,13 +246,13 @@ class ContentStore {
235
246
  const csiDocumentMap = lodash_1.default.keyBy(csiDocuments, 'id');
236
247
  const csiAssetMap = lodash_1.default.keyBy(csiAssets, 'id');
237
248
  const csiModelMap = lodash_1.default.keyBy(csiModels, 'name');
238
- const contentStoreDocuments = mapCSIDocumentsToStoreDocuments({
249
+ const contentStoreDocuments = (0, csi_to_store_docs_converter_1.mapCSIDocumentsToStoreDocuments)({
239
250
  csiDocuments,
240
251
  contentSourceInstance,
241
252
  modelMap,
242
253
  defaultLocaleCode
243
254
  });
244
- const contentStoreAssets = mapCSIAssetsToStoreAssets({
255
+ const contentStoreAssets = (0, csi_to_store_docs_converter_1.mapCSIAssetsToStoreAssets)({
245
256
  csiAssets,
246
257
  contentSourceInstance,
247
258
  defaultLocaleCode
@@ -353,13 +364,13 @@ class ContentStore {
353
364
  });
354
365
  });
355
366
  // map csi documents and assets to content store documents and assets
356
- const documents = mapCSIDocumentsToStoreDocuments({
367
+ const documents = (0, csi_to_store_docs_converter_1.mapCSIDocumentsToStoreDocuments)({
357
368
  csiDocuments: contentChangeEvent.documents,
358
369
  contentSourceInstance: contentSourceData.instance,
359
370
  modelMap: contentSourceData.modelMap,
360
371
  defaultLocaleCode: contentSourceData.defaultLocaleCode
361
372
  });
362
- const assets = mapCSIAssetsToStoreAssets({
373
+ const assets = (0, csi_to_store_docs_converter_1.mapCSIAssetsToStoreAssets)({
363
374
  csiAssets: contentChangeEvent.assets,
364
375
  contentSourceInstance: contentSourceData.instance,
365
376
  defaultLocaleCode: contentSourceData.defaultLocaleCode
@@ -431,25 +442,25 @@ class ContentStore {
431
442
  return (_a = this.presets) !== null && _a !== void 0 ? _a : {};
432
443
  }
433
444
  getContentSourceEnvironment({ srcProjectId, srcType }) {
434
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
445
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
435
446
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
436
447
  return contentSourceData.instance.getProjectEnvironment();
437
448
  }
438
449
  hasAccess({ srcType, srcProjectId, user }) {
439
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
450
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
440
451
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
441
- const userContext = getUserContextForSrcType(srcType, user);
452
+ const userContext = (0, content_store_utils_1.getUserContextForSrcType)(srcType, user);
442
453
  return contentSourceData.instance.hasAccess({ userContext });
443
454
  }
444
455
  hasChanges({ srcType, srcProjectId, documents }) {
445
456
  let result;
446
457
  if (srcType && srcProjectId) {
447
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
458
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
448
459
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
449
460
  result = [...contentSourceData.documents, ...contentSourceData.assets];
450
461
  }
451
462
  else if (documents && documents.length > 0) {
452
- const documentsBySourceId = lodash_1.default.groupBy(documents, (document) => getContentSourceId(document.srcType, document.srcProjectId));
463
+ const documentsBySourceId = lodash_1.default.groupBy(documents, (document) => (0, content_store_utils_1.getContentSourceId)(document.srcType, document.srcProjectId));
453
464
  result = lodash_1.default.reduce(documentsBySourceId, (result, documents, contentSourceId) => {
454
465
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
455
466
  for (const document of documents) {
@@ -479,7 +490,7 @@ class ContentStore {
479
490
  };
480
491
  }
481
492
  getDocument({ srcDocumentId, srcProjectId, srcType }) {
482
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
493
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
483
494
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
484
495
  return contentSourceData.documentMap[srcDocumentId];
485
496
  }
@@ -489,7 +500,7 @@ class ContentStore {
489
500
  }, []);
490
501
  }
491
502
  getAsset({ srcAssetId, srcProjectId, srcType }) {
492
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
503
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
493
504
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
494
505
  return contentSourceData.assetMap[srcAssetId];
495
506
  }
@@ -501,21 +512,21 @@ class ContentStore {
501
512
  getLocalizedApiObjects({ locale }) {
502
513
  return lodash_1.default.reduce(this.contentSourceDataById, (objects, contentSourceData) => {
503
514
  locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
504
- const documentObjects = mapDocumentsToLocalizedApiObjects(contentSourceData.documents, locale);
505
- const imageObjects = mapAssetsToLocalizedApiImages(contentSourceData.assets, locale);
515
+ const documentObjects = (0, store_to_api_docs_converter_1.mapDocumentsToLocalizedApiObjects)(contentSourceData.documents, locale);
516
+ const imageObjects = (0, store_to_api_docs_converter_1.mapAssetsToLocalizedApiImages)(contentSourceData.assets, locale);
506
517
  return objects.concat(documentObjects, imageObjects);
507
518
  }, []);
508
519
  }
509
520
  getApiAssets({ srcType, srcProjectId, pageSize = 20, pageNum = 1, searchQuery } = {}) {
510
521
  let assets;
511
522
  if (srcProjectId && srcType) {
512
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
523
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
513
524
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
514
- assets = mapStoreAssetsToAPIAssets(contentSourceData.assets, contentSourceData.defaultLocaleCode);
525
+ assets = (0, store_to_api_docs_converter_1.mapStoreAssetsToAPIAssets)(contentSourceData.assets, contentSourceData.defaultLocaleCode);
515
526
  }
516
527
  else {
517
528
  assets = lodash_1.default.reduce(this.contentSourceDataById, (result, contentSourceData) => {
518
- const assets = mapStoreAssetsToAPIAssets(contentSourceData.assets, contentSourceData.defaultLocaleCode);
529
+ const assets = (0, store_to_api_docs_converter_1.mapStoreAssetsToAPIAssets)(contentSourceData.assets, contentSourceData.defaultLocaleCode);
519
530
  return result.concat(assets);
520
531
  }, []);
521
532
  }
@@ -537,7 +548,7 @@ class ContentStore {
537
548
  }
538
549
  async createAndLinkDocument({ srcType, srcProjectId, srcDocumentId, fieldPath, modelName, object, index, locale, user }) {
539
550
  this.logger.debug('createAndLinkDocument', { srcType, srcProjectId, srcDocumentId, fieldPath, modelName, index, locale });
540
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
551
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
541
552
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
542
553
  // get the document that is being updated
543
554
  const document = contentSourceData.documentMap[srcDocumentId];
@@ -554,7 +565,7 @@ class ContentStore {
554
565
  }
555
566
  // get the 'reference' model field in the updated document that will be used to link the new document
556
567
  locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
557
- const modelField = getModelFieldForFieldAtPath(document, model, fieldPath, csiModelMap, locale);
568
+ const modelField = (0, content_store_utils_1.getModelFieldForFieldAtPath)(document, model, fieldPath, csiModelMap, locale);
558
569
  if (!modelField) {
559
570
  throw Error(`the "fieldPath" points to non existing model field: ${fieldPath.join('.')}`);
560
571
  }
@@ -579,7 +590,7 @@ class ContentStore {
579
590
  user: user
580
591
  });
581
592
  // update the document by linking the field to the created document
582
- const userContext = getUserContextForSrcType(srcType, user);
593
+ const userContext = (0, content_store_utils_1.getUserContextForSrcType)(srcType, user);
583
594
  const field = {
584
595
  type: 'reference',
585
596
  refType: 'document',
@@ -613,7 +624,7 @@ class ContentStore {
613
624
  async uploadAndLinkAsset({ srcType, srcProjectId, srcDocumentId, fieldPath, asset, index, locale, user }) {
614
625
  this.logger.debug('uploadAndLinkAsset', { srcType, srcProjectId, srcDocumentId, fieldPath, index, locale });
615
626
  // get the document that is being updated
616
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
627
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
617
628
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
618
629
  const document = contentSourceData.documentMap[srcDocumentId];
619
630
  const csiDocument = contentSourceData.csiDocumentMap[srcDocumentId];
@@ -629,7 +640,7 @@ class ContentStore {
629
640
  }
630
641
  // get the 'reference' model field in the updated document that will be used to link the new asset
631
642
  locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
632
- const modelField = getModelFieldForFieldAtPath(document, csiModel, fieldPath, csiModelMap, locale);
643
+ const modelField = (0, content_store_utils_1.getModelFieldForFieldAtPath)(document, csiModel, fieldPath, csiModelMap, locale);
633
644
  if (!modelField) {
634
645
  throw Error(`the "fieldPath" points to non existing model field: ${fieldPath.join('.')}`);
635
646
  }
@@ -638,7 +649,7 @@ class ContentStore {
638
649
  throw Error(`error in "uploadAndLinkAsset", this operation can only be used on reference and image fields: ${fieldPath.join('.')}`);
639
650
  }
640
651
  // upload the new asset
641
- const userContext = getUserContextForSrcType(srcType, user);
652
+ const userContext = (0, content_store_utils_1.getUserContextForSrcType)(srcType, user);
642
653
  const result = await contentSourceData.instance.uploadAsset({
643
654
  url: asset.url,
644
655
  fileName: asset.metadata.name,
@@ -679,22 +690,22 @@ class ContentStore {
679
690
  }
680
691
  async createDocument({ srcType, srcProjectId, modelName, object, locale, user }) {
681
692
  this.logger.debug('createDocument', { srcType, srcProjectId, modelName, locale });
682
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
693
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
683
694
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
684
695
  const modelMap = contentSourceData.modelMap;
685
- const model = modelMap[modelName];
686
- if (!model) {
687
- throw new Error(`no model with name '${modelName}' was found`);
688
- }
689
- locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
690
- const userContext = getUserContextForSrcType(srcType, user);
691
- const result = await createDocumentRecursively({
696
+ const csiModelMap = contentSourceData.csiModelMap;
697
+ const userContext = (0, content_store_utils_1.getUserContextForSrcType)(srcType, user);
698
+ const resolvedLocale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
699
+ const result = await (0, create_update_csi_docs_1.createDocumentRecursively)({
692
700
  object,
693
- model,
701
+ modelName,
694
702
  modelMap,
695
- locale,
696
- userContext,
697
- contentSourceInstance: contentSourceData.instance
703
+ createDocument: (0, create_update_csi_docs_1.getCreateDocumentThunk)({
704
+ locale: resolvedLocale,
705
+ csiModelMap,
706
+ userContext,
707
+ contentSourceInstance: contentSourceData.instance
708
+ })
698
709
  });
699
710
  this.logger.debug('created document', { srcType, srcProjectId, srcDocumentId: result.document.id, modelName });
700
711
  // do not update cache in contentSourceData.documents and documentMap,
@@ -706,9 +717,9 @@ class ContentStore {
706
717
  }
707
718
  async updateDocument({ srcType, srcProjectId, srcDocumentId, updateOperations, user }) {
708
719
  this.logger.debug('updateDocument');
709
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
720
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
710
721
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
711
- const userContext = getUserContextForSrcType(srcType, user);
722
+ const userContext = (0, content_store_utils_1.getUserContextForSrcType)(srcType, user);
712
723
  const document = contentSourceData.documentMap[srcDocumentId];
713
724
  const csiDocument = contentSourceData.csiDocumentMap[srcDocumentId];
714
725
  if (!document || !csiDocument) {
@@ -724,17 +735,20 @@ class ContentStore {
724
735
  const operations = await (0, utils_1.mapPromise)(updateOperations, async (updateOperation) => {
725
736
  var _a;
726
737
  const locale = (_a = updateOperation.locale) !== null && _a !== void 0 ? _a : contentSourceData.defaultLocaleCode;
727
- const modelField = getModelFieldForFieldAtPath(document, model, updateOperation.fieldPath, modelMap, locale);
738
+ const modelField = (0, content_store_utils_1.getModelFieldForFieldAtPath)(document, model, updateOperation.fieldPath, modelMap, locale);
728
739
  switch (updateOperation.opType) {
729
740
  case 'set':
730
- const field = await convertOperationField({
741
+ const field = await (0, create_update_csi_docs_1.convertOperationField)({
731
742
  operationField: updateOperation.field,
732
743
  fieldPath: updateOperation.fieldPath,
733
- locale: updateOperation.locale,
734
744
  modelField,
735
745
  modelMap,
736
- userContext,
737
- contentSourceInstance: contentSourceData.instance
746
+ createDocument: (0, create_update_csi_docs_1.getCreateDocumentThunk)({
747
+ locale: updateOperation.locale,
748
+ csiModelMap,
749
+ userContext,
750
+ contentSourceInstance: contentSourceData.instance
751
+ })
738
752
  });
739
753
  return {
740
754
  ...updateOperation,
@@ -744,14 +758,17 @@ class ContentStore {
744
758
  case 'unset':
745
759
  return { ...updateOperation, modelField };
746
760
  case 'insert':
747
- const item = await convertOperationField({
761
+ const item = await (0, create_update_csi_docs_1.convertOperationField)({
748
762
  operationField: updateOperation.item,
749
763
  fieldPath: updateOperation.fieldPath,
750
- locale: updateOperation.locale,
751
764
  modelField,
752
765
  modelMap,
753
- userContext,
754
- contentSourceInstance: contentSourceData.instance
766
+ createDocument: (0, create_update_csi_docs_1.getCreateDocumentThunk)({
767
+ locale: updateOperation.locale,
768
+ csiModelMap,
769
+ userContext,
770
+ contentSourceInstance: contentSourceData.instance
771
+ })
755
772
  });
756
773
  return {
757
774
  ...updateOperation,
@@ -778,22 +795,24 @@ class ContentStore {
778
795
  }
779
796
  async duplicateDocument({ srcType, srcProjectId, srcDocumentId, object, user }) {
780
797
  this.logger.debug('duplicateDocument');
781
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
798
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
782
799
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
783
800
  const document = contentSourceData.documentMap[srcDocumentId];
784
801
  if (!document) {
785
802
  throw new Error(`no document with id '${srcDocumentId}' was found in ${contentSourceData.id}`);
786
803
  }
787
804
  const modelMap = contentSourceData.modelMap;
805
+ const csiModelMap = contentSourceData.csiModelMap;
788
806
  const model = modelMap[document.srcModelName];
789
- if (!model) {
807
+ const csiModel = csiModelMap[document.srcModelName];
808
+ if (!model || !csiModel) {
790
809
  throw new Error(`no model with name '${document.srcModelName}' was found`);
791
810
  }
792
- const userContext = getUserContextForSrcType(srcType, user);
811
+ const userContext = (0, content_store_utils_1.getUserContextForSrcType)(srcType, user);
793
812
  // TODO: take the data from the provided 'object' and merge them with
794
813
  // DocumentFields of the existing Document:
795
814
  // Option 1: Map the DocumentFields of the existing Document into flat
796
- // object with '$$ref' and '$type' properties for references and
815
+ // object with '$$ref' and '$$type' properties for references and
797
816
  // nested objects (needs to be implemented), and then merge it with
798
817
  // the provided object recursively, and then pass that object to
799
818
  // createNestedObjectRecursively()
@@ -809,12 +828,14 @@ class ContentStore {
809
828
  modelFields: model.fields,
810
829
  modelMap: contentSourceData.modelMap
811
830
  });
831
+ // When passing model and modelMap to contentSourceInstance, we have to pass
832
+ // the original models (i.e., csiModel and csiModelMap) that we've received
833
+ // from that contentSourceInstance. We can't pass internal models as they
834
+ // might
812
835
  const documentResult = await contentSourceData.instance.createDocument({
813
836
  updateOperationFields,
814
- // TODO: pass csiModel
815
- model,
816
- // TODO: pass csiModelMap
817
- modelMap,
837
+ model: csiModel,
838
+ modelMap: csiModelMap,
818
839
  locale: contentSourceData.defaultLocaleCode,
819
840
  userContext
820
841
  });
@@ -822,10 +843,10 @@ class ContentStore {
822
843
  }
823
844
  async uploadAssets({ srcType, srcProjectId, assets, locale, user }) {
824
845
  this.logger.debug('uploadAssets');
825
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
846
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
826
847
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
827
848
  const sourceAssets = [];
828
- const userContext = getUserContextForSrcType(srcType, user);
849
+ const userContext = (0, content_store_utils_1.getUserContextForSrcType)(srcType, user);
829
850
  locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
830
851
  for (const asset of assets) {
831
852
  let base64 = undefined;
@@ -845,17 +866,17 @@ class ContentStore {
845
866
  });
846
867
  sourceAssets.push(sourceAsset);
847
868
  }
848
- const storeAssets = mapCSIAssetsToStoreAssets({
869
+ const storeAssets = (0, csi_to_store_docs_converter_1.mapCSIAssetsToStoreAssets)({
849
870
  csiAssets: sourceAssets,
850
871
  contentSourceInstance: contentSourceData.instance,
851
872
  defaultLocaleCode: contentSourceData.defaultLocaleCode
852
873
  });
853
- return mapStoreAssetsToAPIAssets(storeAssets, locale);
874
+ return (0, store_to_api_docs_converter_1.mapStoreAssetsToAPIAssets)(storeAssets, locale);
854
875
  }
855
876
  async deleteDocument({ srcType, srcProjectId, srcDocumentId, user }) {
856
877
  this.logger.debug('deleteDocument');
857
- const userContext = getUserContextForSrcType(srcType, user);
858
- const contentSourceId = getContentSourceId(srcType, srcProjectId);
878
+ const userContext = (0, content_store_utils_1.getUserContextForSrcType)(srcType, user);
879
+ const contentSourceId = (0, content_store_utils_1.getContentSourceId)(srcType, srcProjectId);
859
880
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
860
881
  const csiDocument = contentSourceData.csiDocumentMap[srcDocumentId];
861
882
  if (!csiDocument) {
@@ -869,13 +890,13 @@ class ContentStore {
869
890
  }
870
891
  async validateDocuments({ objects, locale, user }) {
871
892
  this.logger.debug('validateDocuments');
872
- const objectsBySourceId = lodash_1.default.groupBy(objects, (object) => getContentSourceId(object.srcType, object.srcProjectId));
893
+ const objectsBySourceId = lodash_1.default.groupBy(objects, (object) => (0, content_store_utils_1.getContentSourceId)(object.srcType, object.srcProjectId));
873
894
  let errors = [];
874
895
  for (const [contentSourceId, contentSourceObjects] of Object.entries(objectsBySourceId)) {
875
896
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
876
897
  locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
877
898
  const { documents, assets } = getCSIDocumentsAndAssetsFromContentSourceDataByIds(contentSourceData, contentSourceObjects);
878
- const userContext = getUserContextForSrcType(contentSourceData.type, user);
899
+ const userContext = (0, content_store_utils_1.getUserContextForSrcType)(contentSourceData.type, user);
879
900
  const internalValidationErrors = internalValidateContent(documents, assets, contentSourceData);
880
901
  const validationResult = await contentSourceData.instance.validateDocuments({ documents, assets, locale, userContext });
881
902
  errors = errors.concat(internalValidationErrors, validationResult.errors.map((validationError) => ({
@@ -906,10 +927,10 @@ class ContentStore {
906
927
  }
907
928
  async publishDocuments({ objects, user }) {
908
929
  this.logger.debug('publishDocuments');
909
- const objectsBySourceId = lodash_1.default.groupBy(objects, (object) => getContentSourceId(object.srcType, object.srcProjectId));
930
+ const objectsBySourceId = lodash_1.default.groupBy(objects, (object) => (0, content_store_utils_1.getContentSourceId)(object.srcType, object.srcProjectId));
910
931
  for (const [contentSourceId, contentSourceObjects] of Object.entries(objectsBySourceId)) {
911
932
  const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
912
- const userContext = getUserContextForSrcType(contentSourceData.type, user);
933
+ const userContext = (0, content_store_utils_1.getUserContextForSrcType)(contentSourceData.type, user);
913
934
  const { documents, assets } = getCSIDocumentsAndAssetsFromContentSourceDataByIds(contentSourceData, contentSourceObjects);
914
935
  await contentSourceData.instance.publishDocuments({ documents, assets, userContext });
915
936
  }
@@ -923,881 +944,10 @@ class ContentStore {
923
944
  }
924
945
  }
925
946
  exports.ContentStore = ContentStore;
926
- function getContentSourceId(contentSourceType, srcProjectId) {
927
- return contentSourceType + ':' + srcProjectId;
928
- }
929
- exports.getContentSourceId = getContentSourceId;
930
- function getUserContextForSrcType(srcType, user) {
931
- var _a;
932
- return (_a = user === null || user === void 0 ? void 0 : user.connections) === null || _a === void 0 ? void 0 : _a.find((connection) => connection.type === srcType);
933
- }
934
- function mapCSIAssetsToStoreAssets({ csiAssets, contentSourceInstance, defaultLocaleCode }) {
935
- const extra = {
936
- srcType: contentSourceInstance.getContentSourceType(),
937
- srcProjectId: contentSourceInstance.getProjectId(),
938
- srcProjectUrl: contentSourceInstance.getProjectManageUrl(),
939
- srcEnvironment: contentSourceInstance.getProjectEnvironment()
940
- };
941
- return csiAssets.map((csiAsset) => sourceAssetToStoreAsset({ csiAsset, defaultLocaleCode, extra }));
942
- }
943
- function sourceAssetToStoreAsset({ csiAsset, defaultLocaleCode, extra }) {
944
- return {
945
- type: 'asset',
946
- ...extra,
947
- srcObjectId: csiAsset.id,
948
- srcObjectUrl: csiAsset.manageUrl,
949
- srcObjectLabel: getObjectLabel(csiAsset.fields, common_schema_1.IMAGE_MODEL, defaultLocaleCode),
950
- srcModelName: common_schema_1.IMAGE_MODEL.name,
951
- srcModelLabel: common_schema_1.IMAGE_MODEL.label,
952
- isChanged: csiAsset.status === 'added' || csiAsset.status === 'modified',
953
- status: csiAsset.status,
954
- createdAt: csiAsset.createdAt,
955
- createdBy: csiAsset.createdBy,
956
- updatedAt: csiAsset.updatedAt,
957
- updatedBy: csiAsset.updatedBy,
958
- fields: {
959
- title: {
960
- label: 'Title',
961
- ...csiAsset.fields.title
962
- },
963
- file: {
964
- label: 'File',
965
- ...csiAsset.fields.file
966
- }
967
- }
968
- };
969
- }
970
- function mapCSIDocumentsToStoreDocuments({ csiDocuments, contentSourceInstance, modelMap, defaultLocaleCode }) {
971
- const extra = {
972
- srcType: contentSourceInstance.getContentSourceType(),
973
- srcProjectId: contentSourceInstance.getProjectId(),
974
- srcProjectUrl: contentSourceInstance.getProjectManageUrl(),
975
- srcEnvironment: contentSourceInstance.getProjectEnvironment()
976
- };
977
- return csiDocuments.map((csiDocument) => mapCSIDocumentToStoreDocument({ csiDocument, model: modelMap[csiDocument.modelName], modelMap, defaultLocaleCode, extra }));
978
- }
979
- function mapCSIDocumentToStoreDocument({ csiDocument, model, modelMap, defaultLocaleCode, extra }) {
980
- var _a, _b;
981
- return {
982
- type: 'document',
983
- ...extra,
984
- srcObjectId: csiDocument.id,
985
- srcObjectUrl: csiDocument.manageUrl,
986
- srcObjectLabel: getObjectLabel(csiDocument.fields, model, defaultLocaleCode),
987
- srcModelLabel: (_a = model.label) !== null && _a !== void 0 ? _a : lodash_1.default.startCase(csiDocument.modelName),
988
- srcModelName: csiDocument.modelName,
989
- isChanged: csiDocument.status === 'added' || csiDocument.status === 'modified',
990
- status: csiDocument.status,
991
- createdAt: csiDocument.createdAt,
992
- createdBy: csiDocument.createdBy,
993
- updatedAt: csiDocument.updatedAt,
994
- updatedBy: csiDocument.updatedBy,
995
- fields: mapCSIFieldsToStoreFields({
996
- csiDocumentFields: csiDocument.fields,
997
- modelFields: (_b = model.fields) !== null && _b !== void 0 ? _b : [],
998
- context: {
999
- modelMap,
1000
- defaultLocaleCode
1001
- }
1002
- })
1003
- };
1004
- }
1005
- function mapCSIFieldsToStoreFields({ csiDocumentFields, modelFields, context }) {
1006
- return modelFields.reduce((result, modelField) => {
1007
- const csiDocumentField = csiDocumentFields[modelField.name];
1008
- const docField = mapCSIFieldToStoreField({
1009
- csiDocumentField,
1010
- modelField,
1011
- context
1012
- });
1013
- docField.label = modelField.label;
1014
- result[modelField.name] = docField;
1015
- return result;
1016
- }, {});
1017
- }
1018
- function mapCSIFieldToStoreField({ csiDocumentField, modelField, context }) {
1019
- if (!csiDocumentField) {
1020
- const isUnset = ['object', 'model', 'reference', 'richText', 'markdown', 'image', 'file', 'json'].includes(modelField.type);
1021
- return {
1022
- type: modelField.type,
1023
- ...(isUnset ? { isUnset } : null),
1024
- ...(modelField.type === 'list' ? { items: [] } : null)
1025
- };
1026
- }
1027
- // TODO: check if need to add "options" to "enum" and subtype/min/max to "number"
1028
- switch (modelField.type) {
1029
- case 'object':
1030
- return mapObjectField(csiDocumentField, modelField, context);
1031
- case 'model':
1032
- return mapModelField(csiDocumentField, modelField, context);
1033
- case 'list':
1034
- return mapListField(csiDocumentField, modelField, context);
1035
- case 'richText':
1036
- return mapRichTextField(csiDocumentField);
1037
- case 'markdown':
1038
- return mapMarkdownField(csiDocumentField);
1039
- default:
1040
- return csiDocumentField;
1041
- }
1042
- }
1043
- function mapObjectField(csiDocumentField, modelField, context) {
1044
- var _a, _b, _c;
1045
- if (!(0, content_source_interface_1.isLocalizedField)(csiDocumentField)) {
1046
- return {
1047
- type: csiDocumentField.type,
1048
- srcObjectLabel: getObjectLabel((_a = csiDocumentField.fields) !== null && _a !== void 0 ? _a : {}, modelField !== null && modelField !== void 0 ? modelField : [], context.defaultLocaleCode),
1049
- fields: mapCSIFieldsToStoreFields({
1050
- csiDocumentFields: (_b = csiDocumentField.fields) !== null && _b !== void 0 ? _b : {},
1051
- modelFields: (_c = modelField.fields) !== null && _c !== void 0 ? _c : [],
1052
- context
1053
- })
1054
- };
1055
- }
1056
- return {
1057
- type: csiDocumentField.type,
1058
- localized: true,
1059
- locales: lodash_1.default.mapValues(csiDocumentField.locales, (locale) => {
1060
- var _a, _b, _c;
1061
- return {
1062
- locale: locale.locale,
1063
- srcObjectLabel: getObjectLabel((_a = locale.fields) !== null && _a !== void 0 ? _a : {}, modelField, locale.locale),
1064
- fields: mapCSIFieldsToStoreFields({
1065
- csiDocumentFields: (_b = locale.fields) !== null && _b !== void 0 ? _b : {},
1066
- modelFields: (_c = modelField.fields) !== null && _c !== void 0 ? _c : [],
1067
- context
1068
- })
1069
- };
1070
- })
1071
- };
1072
- }
1073
- function mapModelField(csiDocumentField, modelField, context) {
1074
- var _a, _b, _c, _d;
1075
- if (!(0, content_source_interface_1.isLocalizedField)(csiDocumentField)) {
1076
- const model = context.modelMap[csiDocumentField.modelName];
1077
- return {
1078
- type: csiDocumentField.type,
1079
- srcObjectLabel: getObjectLabel((_a = csiDocumentField.fields) !== null && _a !== void 0 ? _a : {}, model, context.defaultLocaleCode),
1080
- srcModelName: csiDocumentField.modelName,
1081
- srcModelLabel: (_b = model.label) !== null && _b !== void 0 ? _b : lodash_1.default.startCase(model.name),
1082
- fields: mapCSIFieldsToStoreFields({
1083
- csiDocumentFields: (_c = csiDocumentField.fields) !== null && _c !== void 0 ? _c : {},
1084
- modelFields: (_d = model.fields) !== null && _d !== void 0 ? _d : [],
1085
- context
1086
- })
1087
- };
1088
- }
1089
- return {
1090
- type: csiDocumentField.type,
1091
- localized: true,
1092
- locales: lodash_1.default.mapValues(csiDocumentField.locales, (locale) => {
1093
- var _a, _b, _c, _d;
1094
- const model = context.modelMap[locale.modelName];
1095
- return {
1096
- locale: locale.locale,
1097
- srcObjectLabel: getObjectLabel((_a = locale.fields) !== null && _a !== void 0 ? _a : {}, model, locale.locale),
1098
- srcModelName: locale.modelName,
1099
- srcModelLabel: (_b = model.label) !== null && _b !== void 0 ? _b : lodash_1.default.startCase(model.name),
1100
- fields: mapCSIFieldsToStoreFields({
1101
- csiDocumentFields: (_c = locale.fields) !== null && _c !== void 0 ? _c : {},
1102
- modelFields: (_d = model.fields) !== null && _d !== void 0 ? _d : [],
1103
- context
1104
- })
1105
- };
1106
- })
1107
- };
1108
- }
1109
- function mapListField(csiDocumentField, modelField, context) {
1110
- if (!(0, content_source_interface_1.isLocalizedField)(csiDocumentField)) {
1111
- return {
1112
- type: csiDocumentField.type,
1113
- items: csiDocumentField.items.map((item) => {
1114
- var _a;
1115
- return mapCSIFieldToStoreField({
1116
- csiDocumentField: item,
1117
- modelField: (_a = modelField.items) !== null && _a !== void 0 ? _a : { type: 'string' },
1118
- context
1119
- });
1120
- })
1121
- };
1122
- }
1123
- return {
1124
- type: csiDocumentField.type,
1125
- localized: true,
1126
- locales: lodash_1.default.mapValues(csiDocumentField.locales, (locale) => {
1127
- var _a;
1128
- return {
1129
- locale: locale.locale,
1130
- items: ((_a = locale.items) !== null && _a !== void 0 ? _a : []).map((item) => {
1131
- var _a;
1132
- return mapCSIFieldToStoreField({
1133
- csiDocumentField: item,
1134
- modelField: (_a = modelField.items) !== null && _a !== void 0 ? _a : { type: 'string' },
1135
- context
1136
- });
1137
- })
1138
- };
1139
- })
1140
- };
1141
- }
1142
- function mapRichTextField(csiDocumentField) {
1143
- if (!(0, content_source_interface_1.isLocalizedField)(csiDocumentField)) {
1144
- return {
1145
- ...csiDocumentField,
1146
- multiElement: true
1147
- };
1148
- }
1149
- return {
1150
- type: csiDocumentField.type,
1151
- localized: true,
1152
- locales: lodash_1.default.mapValues(csiDocumentField.locales, (locale) => {
1153
- return {
1154
- ...locale,
1155
- multiElement: true
1156
- };
1157
- })
1158
- };
1159
- }
1160
- function mapMarkdownField(csiDocumentField) {
1161
- if (!(0, content_source_interface_1.isLocalizedField)(csiDocumentField)) {
1162
- return {
1163
- type: 'markdown',
1164
- value: csiDocumentField.value,
1165
- multiElement: true
1166
- };
1167
- }
1168
- return {
1169
- type: 'markdown',
1170
- localized: true,
1171
- locales: lodash_1.default.mapValues(csiDocumentField.locales, (locale) => {
1172
- return {
1173
- ...locale,
1174
- multiElement: true
1175
- };
1176
- })
1177
- };
1178
- }
1179
947
  function mapStoreFieldsToOperationFields({ documentFields, modelFields, modelMap }) {
1180
948
  // TODO: implement
1181
949
  throw new Error(`duplicateDocument not implemented yet`);
1182
950
  }
1183
- function getContentSourceIdForContentSource(contentSource) {
1184
- return getContentSourceId(contentSource.getContentSourceType(), contentSource.getProjectId());
1185
- }
1186
- function extractTokensFromString(input) {
1187
- return input.match(/(?<={)[^}]+(?=})/g) || [];
1188
- }
1189
- function sanitizeSlug(slug) {
1190
- return slug
1191
- .split('/')
1192
- .map((part) => (0, slugify_1.default)(part, { lower: true }))
1193
- .join('/');
1194
- }
1195
- function getObjectLabel(documentFields, modelOrObjectField, locale) {
1196
- const labelField = modelOrObjectField.labelField;
1197
- let label = null;
1198
- if (labelField) {
1199
- const field = lodash_1.default.get(documentFields, labelField, null);
1200
- if (field && ['string', 'url', 'slug', 'text', 'markdown', 'number', 'enum', 'date', 'datetime', 'color', 'image', 'file'].includes(field.type)) {
1201
- if ((0, content_source_interface_1.isLocalizedField)(field) && locale) {
1202
- label = lodash_1.default.get(field, ['locales', locale, 'value'], null);
1203
- }
1204
- else if (!(0, content_source_interface_1.isLocalizedField)(field)) {
1205
- label = lodash_1.default.get(field, 'value', null);
1206
- }
1207
- }
1208
- }
1209
- if (!label) {
1210
- label = lodash_1.default.get(modelOrObjectField, 'label');
1211
- }
1212
- if (!label && lodash_1.default.has(modelOrObjectField, 'name')) {
1213
- label = lodash_1.default.startCase(lodash_1.default.get(modelOrObjectField, 'name'));
1214
- }
1215
- return label;
1216
- }
1217
- function mapDocumentsToLocalizedApiObjects(documents, locale) {
1218
- return documents.map((document) => documentToLocalizedApiObject(document, locale));
1219
- }
1220
- function documentToLocalizedApiObject(document, locale) {
1221
- const { type, fields, ...rest } = document;
1222
- return {
1223
- type: 'object',
1224
- ...rest,
1225
- fields: toLocalizedAPIFields(fields, locale)
1226
- };
1227
- }
1228
- function toLocalizedAPIFields(docFields, locale) {
1229
- return lodash_1.default.mapValues(docFields, (docField) => toLocalizedAPIField(docField, locale));
1230
- }
1231
- function toLocalizedAPIField(docField, locale, isListItem = false) {
1232
- const hasUnsetFlag = ['object', 'model', 'reference', 'richText', 'markdown', 'image', 'file', 'json'].includes(docField.type);
1233
- let docFieldLocalized;
1234
- let unset = false;
1235
- if (docField.localized) {
1236
- const { locales, localized, ...base } = docField;
1237
- const localeProps = locale ? locales[locale] : undefined;
1238
- docFieldLocalized = {
1239
- ...base,
1240
- ...localeProps,
1241
- ...(hasUnsetFlag && !localeProps ? { isUnset: true } : null)
1242
- };
1243
- }
1244
- else {
1245
- docFieldLocalized = docField;
1246
- }
1247
- locale = locale !== null && locale !== void 0 ? locale : docFieldLocalized.locale;
1248
- const commonProps = isListItem
1249
- ? null
1250
- : {
1251
- localized: !!docField.localized,
1252
- ...(locale ? { locale } : null)
1253
- };
1254
- if (docFieldLocalized.type === 'object' || docFieldLocalized.type === 'model') {
1255
- return {
1256
- ...docFieldLocalized,
1257
- type: 'object',
1258
- ...commonProps,
1259
- ...(docFieldLocalized.isUnset
1260
- ? null
1261
- : {
1262
- fields: toLocalizedAPIFields(docFieldLocalized.fields, locale)
1263
- })
1264
- };
1265
- }
1266
- else if (docFieldLocalized.type === 'reference') {
1267
- const { type, refType, ...rest } = docFieldLocalized;
1268
- // if reference field isUnset === true, it behaves like a regular object
1269
- if (rest.isUnset) {
1270
- return {
1271
- type: 'object',
1272
- ...rest,
1273
- ...commonProps
1274
- };
1275
- }
1276
- return {
1277
- type: 'unresolved_reference',
1278
- refType: refType === 'asset' ? 'image' : 'object',
1279
- ...rest,
1280
- ...commonProps
1281
- };
1282
- }
1283
- else if (docFieldLocalized.type === 'list') {
1284
- // items can be undefined if the requested locale doesn't exist on a localized field
1285
- const { items, ...rest } = docFieldLocalized;
1286
- return {
1287
- ...rest,
1288
- ...commonProps,
1289
- items: (items !== null && items !== void 0 ? items : []).map((field) => toLocalizedAPIField(field, locale, true))
1290
- };
1291
- }
1292
- else {
1293
- return {
1294
- ...docFieldLocalized,
1295
- ...commonProps
1296
- };
1297
- }
1298
- }
1299
- function mapAssetsToLocalizedApiImages(assets, locale) {
1300
- return assets.map((asset) => assetToLocalizedApiImage(asset, locale));
1301
- }
1302
- function assetToLocalizedApiImage(asset, locale) {
1303
- const { type, fields, ...rest } = asset;
1304
- return {
1305
- type: 'image',
1306
- ...rest,
1307
- fields: localizeAssetFields(fields, locale)
1308
- };
1309
- }
1310
- function localizeAssetFields(assetFields, locale) {
1311
- var _a, _b;
1312
- const fields = {
1313
- title: {
1314
- type: 'string',
1315
- value: null
1316
- },
1317
- url: {
1318
- type: 'string',
1319
- value: null
1320
- }
1321
- };
1322
- const titleFieldNonLocalized = getDocumentFieldForLocale(assetFields.title, locale);
1323
- fields.title.value = titleFieldNonLocalized === null || titleFieldNonLocalized === void 0 ? void 0 : titleFieldNonLocalized.value;
1324
- fields.title.locale = locale !== null && locale !== void 0 ? locale : titleFieldNonLocalized === null || titleFieldNonLocalized === void 0 ? void 0 : titleFieldNonLocalized.locale;
1325
- const assetFileField = assetFields.file;
1326
- if (assetFileField.localized) {
1327
- if (locale) {
1328
- fields.url.value = (_b = (_a = assetFileField.locales[locale]) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : null;
1329
- fields.url.locale = locale;
1330
- }
1331
- }
1332
- else {
1333
- fields.url.value = assetFileField.url;
1334
- fields.url.locale = assetFileField.locale;
1335
- }
1336
- return fields;
1337
- }
1338
- function mapStoreAssetsToAPIAssets(assets, locale) {
1339
- return assets.map((asset) => storeAssetToAPIAsset(asset, locale));
1340
- }
1341
- function storeAssetToAPIAsset(asset, locale) {
1342
- var _a, _b;
1343
- const assetTitleField = asset.fields.title;
1344
- const localizedTitleField = assetTitleField.localized ? assetTitleField.locales[locale] : assetTitleField;
1345
- const assetFileField = asset.fields.file;
1346
- const localizedFileField = assetFileField.localized ? assetFileField.locales[locale] : assetFileField;
1347
- return {
1348
- objectId: asset.srcObjectId,
1349
- createdAt: asset.createdAt,
1350
- url: localizedFileField.url,
1351
- ...(0, utils_1.omitByNil)({
1352
- title: localizedTitleField.value,
1353
- fileName: localizedFileField.fileName,
1354
- contentType: localizedFileField.contentType,
1355
- size: localizedFileField.size,
1356
- width: (_a = localizedFileField.dimensions) === null || _a === void 0 ? void 0 : _a.width,
1357
- height: (_b = localizedFileField.dimensions) === null || _b === void 0 ? void 0 : _b.height
1358
- })
1359
- };
1360
- }
1361
- /**
1362
- * Iterates recursively objects with $$type and $$ref, creating nested objects
1363
- * as needed and returns standard ContentSourceInterface Documents
1364
- */
1365
- async function createDocumentRecursively({ object, model, modelMap, locale, userContext, contentSourceInstance }) {
1366
- var _a;
1367
- if (model.type === 'page') {
1368
- const tokens = extractTokensFromString(String(model.urlPath));
1369
- const slugField = lodash_1.default.last(tokens);
1370
- if (object && slugField && slugField in object) {
1371
- const slugFieldValue = object[slugField];
1372
- object[slugField] = sanitizeSlug(slugFieldValue);
1373
- }
1374
- }
1375
- const nestedResult = await createNestedObjectRecursively({
1376
- object,
1377
- modelFields: (_a = model.fields) !== null && _a !== void 0 ? _a : [],
1378
- fieldPath: [],
1379
- modelMap,
1380
- locale,
1381
- userContext,
1382
- contentSourceInstance
1383
- });
1384
- const document = await contentSourceInstance.createDocument({
1385
- updateOperationFields: nestedResult.fields,
1386
- // TODO: pass csiModel
1387
- model,
1388
- // TODO: pass csiModelMap
1389
- modelMap,
1390
- locale,
1391
- userContext
1392
- });
1393
- return {
1394
- document: document,
1395
- newRefDocuments: nestedResult.newRefDocuments
1396
- };
1397
- }
1398
- async function createNestedObjectRecursively({ object, modelFields, fieldPath, modelMap, locale, userContext, contentSourceInstance }) {
1399
- object = object !== null && object !== void 0 ? object : {};
1400
- const result = {
1401
- fields: {},
1402
- newRefDocuments: []
1403
- };
1404
- const objectFieldNames = Object.keys(object);
1405
- for (const modelField of modelFields) {
1406
- const fieldName = modelField.name;
1407
- let value;
1408
- if (fieldName in object) {
1409
- value = object[fieldName];
1410
- lodash_1.default.pull(objectFieldNames, fieldName);
1411
- }
1412
- else if (modelField.const) {
1413
- value = modelField.const;
1414
- }
1415
- else if (!lodash_1.default.isNil(modelField.default)) {
1416
- value = modelField.default;
1417
- }
1418
- if (!lodash_1.default.isNil(value)) {
1419
- const fieldResult = await createNestedField({
1420
- value,
1421
- modelField,
1422
- fieldPath: fieldPath.concat(fieldName),
1423
- modelMap,
1424
- locale,
1425
- userContext,
1426
- contentSourceInstance
1427
- });
1428
- result.fields[fieldName] = fieldResult.field;
1429
- result.newRefDocuments = result.newRefDocuments.concat(fieldResult.newRefDocuments);
1430
- }
1431
- }
1432
- if (objectFieldNames.length > 0) {
1433
- throw new Error(`no model fields found when creating a document with fields: '${objectFieldNames.join(', ')}'`);
1434
- }
1435
- return result;
1436
- }
1437
- async function createNestedField({ value, modelField, fieldPath, modelMap, locale, userContext, contentSourceInstance }) {
1438
- var _a;
1439
- if (modelField.type === 'object') {
1440
- const result = await createNestedObjectRecursively({
1441
- object: value,
1442
- modelFields: modelField.fields,
1443
- fieldPath,
1444
- modelMap,
1445
- locale,
1446
- userContext,
1447
- contentSourceInstance
1448
- });
1449
- return {
1450
- field: {
1451
- type: 'object',
1452
- fields: result.fields
1453
- },
1454
- newRefDocuments: result.newRefDocuments
1455
- };
1456
- }
1457
- else if (modelField.type === 'model') {
1458
- let { $$type, ...rest } = value;
1459
- const modelNames = modelField.models;
1460
- // for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
1461
- // the 'type' property in default values
1462
- if (!$$type && 'type' in rest) {
1463
- $$type = rest.type;
1464
- rest = lodash_1.default.omit(rest, 'type');
1465
- }
1466
- const modelName = $$type !== null && $$type !== void 0 ? $$type : (modelNames.length === 1 ? modelNames[0] : null);
1467
- if (!modelName) {
1468
- throw new Error(`no $$type was specified for nested model`);
1469
- }
1470
- const model = modelMap[modelName];
1471
- if (!model) {
1472
- throw new Error(`no model with name '${modelName}' was found`);
1473
- }
1474
- const result = await createNestedObjectRecursively({
1475
- object: rest,
1476
- modelFields: (_a = model.fields) !== null && _a !== void 0 ? _a : [],
1477
- fieldPath,
1478
- modelMap,
1479
- locale,
1480
- userContext,
1481
- contentSourceInstance
1482
- });
1483
- return {
1484
- field: {
1485
- type: 'model',
1486
- modelName: modelName,
1487
- fields: result.fields
1488
- },
1489
- newRefDocuments: result.newRefDocuments
1490
- };
1491
- }
1492
- else if (modelField.type === 'image') {
1493
- let refId;
1494
- if (lodash_1.default.isPlainObject(value)) {
1495
- refId = value.$$ref;
1496
- }
1497
- else {
1498
- refId = value;
1499
- }
1500
- if (!refId) {
1501
- throw new Error(`reference field must specify a value`);
1502
- }
1503
- return {
1504
- field: {
1505
- type: 'reference',
1506
- refType: 'asset',
1507
- refId: refId
1508
- },
1509
- newRefDocuments: []
1510
- };
1511
- }
1512
- else if (modelField.type === 'reference') {
1513
- let { $$ref: refId = null, $$type: modelName = null, ...rest } = lodash_1.default.isPlainObject(value) ? value : { $$ref: value };
1514
- if (refId) {
1515
- return {
1516
- field: {
1517
- type: 'reference',
1518
- refType: 'document',
1519
- refId: refId
1520
- },
1521
- newRefDocuments: []
1522
- };
1523
- }
1524
- else {
1525
- const modelNames = modelField.models;
1526
- if (!modelName) {
1527
- // for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
1528
- // the 'type' property in default values
1529
- if ('type' in rest) {
1530
- modelName = rest.type;
1531
- rest = lodash_1.default.omit(rest, 'type');
1532
- }
1533
- else if (modelNames.length === 1) {
1534
- modelName = modelNames[0];
1535
- }
1536
- }
1537
- const model = modelMap[modelName];
1538
- if (!model) {
1539
- throw new Error(`no model with name '${modelName}' was found`);
1540
- }
1541
- const { document, newRefDocuments } = await createDocumentRecursively({
1542
- object: rest,
1543
- model: model,
1544
- modelMap,
1545
- locale,
1546
- userContext,
1547
- contentSourceInstance
1548
- });
1549
- return {
1550
- field: {
1551
- type: 'reference',
1552
- refType: 'document',
1553
- refId: document.id
1554
- },
1555
- newRefDocuments: [document, ...newRefDocuments]
1556
- };
1557
- }
1558
- }
1559
- else if (modelField.type === 'list') {
1560
- if (!Array.isArray(value)) {
1561
- throw new Error(`value for list field must be array`);
1562
- }
1563
- const itemsField = modelField.items;
1564
- if (!itemsField) {
1565
- throw new Error(`list field does not define items`);
1566
- }
1567
- const arrayResult = await (0, utils_1.mapPromise)(value, async (item, index) => {
1568
- return createNestedField({
1569
- value: item,
1570
- modelField: itemsField,
1571
- fieldPath: fieldPath.concat(index),
1572
- modelMap,
1573
- locale,
1574
- userContext,
1575
- contentSourceInstance
1576
- });
1577
- });
1578
- return {
1579
- field: {
1580
- type: 'list',
1581
- items: arrayResult.map((result) => result.field)
1582
- },
1583
- newRefDocuments: arrayResult.reduce((result, { newRefDocuments }) => result.concat(newRefDocuments), [])
1584
- };
1585
- }
1586
- return {
1587
- field: {
1588
- type: modelField.type,
1589
- value: value
1590
- },
1591
- newRefDocuments: []
1592
- };
1593
- }
1594
- function getModelFieldForFieldAtPath(document, model, fieldPath, modelMap, locale) {
1595
- if (lodash_1.default.isEmpty(fieldPath)) {
1596
- throw new Error('the fieldPath can not be empty');
1597
- }
1598
- function getField(docField, modelField, fieldPath) {
1599
- const fieldName = lodash_1.default.head(fieldPath);
1600
- if (typeof fieldName === 'undefined') {
1601
- throw new Error('the first fieldPath item must be string');
1602
- }
1603
- const childFieldPath = lodash_1.default.tail(fieldPath);
1604
- let childDocField;
1605
- let childModelField;
1606
- switch (docField.type) {
1607
- case 'object':
1608
- const localizedObjectField = getDocumentFieldForLocale(docField, locale);
1609
- if (!localizedObjectField) {
1610
- throw new Error(`locale for field was not found`);
1611
- }
1612
- if (localizedObjectField.isUnset) {
1613
- throw new Error(`field is not set`);
1614
- }
1615
- childDocField = localizedObjectField.fields[fieldName];
1616
- childModelField = lodash_1.default.find(modelField.fields, (field) => field.name === fieldName);
1617
- if (!childDocField || !childModelField) {
1618
- throw new Error(`field ${fieldName} doesn't exist`);
1619
- }
1620
- if (childFieldPath.length === 0) {
1621
- return childModelField;
1622
- }
1623
- return getField(childDocField, childModelField, childFieldPath);
1624
- case 'model':
1625
- const localizedModelField = getDocumentFieldForLocale(docField, locale);
1626
- if (!localizedModelField) {
1627
- throw new Error(`locale for field was not found`);
1628
- }
1629
- if (localizedModelField.isUnset) {
1630
- throw new Error(`field is not set`);
1631
- }
1632
- const modelName = localizedModelField.srcModelName;
1633
- const childModel = modelMap[modelName];
1634
- if (!childModel) {
1635
- throw new Error(`model ${modelName} doesn't exist`);
1636
- }
1637
- childModelField = lodash_1.default.find(childModel.fields, (field) => field.name === fieldName);
1638
- childDocField = localizedModelField.fields[fieldName];
1639
- if (!childDocField || !childModelField) {
1640
- throw new Error(`field ${fieldName} doesn't exist`);
1641
- }
1642
- if (childFieldPath.length === 0) {
1643
- return childModelField;
1644
- }
1645
- return getField(childDocField, childModelField, childFieldPath);
1646
- case 'list':
1647
- const localizedListField = getDocumentFieldForLocale(docField, locale);
1648
- if (!localizedListField) {
1649
- throw new Error(`locale for field was not found`);
1650
- }
1651
- const listItem = localizedListField.items && localizedListField.items[fieldName];
1652
- const listItemsModel = modelField.items;
1653
- if (!listItem || !listItemsModel) {
1654
- throw new Error(`field ${fieldName} doesn't exist`);
1655
- }
1656
- if (childFieldPath.length === 0) {
1657
- return modelField;
1658
- }
1659
- if (!Array.isArray(listItemsModel)) {
1660
- return getField(listItem, listItemsModel, childFieldPath);
1661
- }
1662
- else {
1663
- const fieldListItems = listItemsModel.find((listItemsModel) => listItemsModel.type === listItem.type);
1664
- if (!fieldListItems) {
1665
- throw new Error('cannot find matching field model');
1666
- }
1667
- return getField(listItem, fieldListItems, childFieldPath);
1668
- }
1669
- default:
1670
- if (!lodash_1.default.isEmpty(childFieldPath)) {
1671
- throw new Error('illegal fieldPath');
1672
- }
1673
- return modelField;
1674
- }
1675
- }
1676
- const fieldName = lodash_1.default.head(fieldPath);
1677
- const childFieldPath = lodash_1.default.tail(fieldPath);
1678
- if (typeof fieldName !== 'string') {
1679
- throw new Error('the first fieldPath item must be string');
1680
- }
1681
- const childDocField = document.fields[fieldName];
1682
- const childModelField = lodash_1.default.find(model.fields, { name: fieldName });
1683
- if (!childDocField || !childModelField) {
1684
- throw new Error(`field ${fieldName} doesn't exist`);
1685
- }
1686
- if (childFieldPath.length === 0) {
1687
- return childModelField;
1688
- }
1689
- return getField(childDocField, childModelField, childFieldPath);
1690
- }
1691
- async function convertOperationField({ operationField, fieldPath, modelField, modelMap, locale, userContext, contentSourceInstance }) {
1692
- // for insert operations, the modelField will be of the list, so get the modelField of the list items
1693
- const modelFieldOrListItems = modelField.type === 'list' ? modelField.items : modelField;
1694
- switch (operationField.type) {
1695
- case 'object': {
1696
- const result = await createNestedObjectRecursively({
1697
- object: operationField.object,
1698
- modelFields: modelFieldOrListItems.fields,
1699
- fieldPath: fieldPath,
1700
- modelMap,
1701
- locale,
1702
- userContext,
1703
- contentSourceInstance
1704
- });
1705
- return {
1706
- type: operationField.type,
1707
- fields: result.fields
1708
- };
1709
- }
1710
- case 'model': {
1711
- const model = modelMap[operationField.modelName];
1712
- if (!model) {
1713
- throw new Error(`error updating document, could not find document model: '${operationField.modelName}'`);
1714
- }
1715
- const result = await createNestedObjectRecursively({
1716
- object: operationField.object,
1717
- modelFields: model.fields,
1718
- fieldPath,
1719
- modelMap,
1720
- locale,
1721
- userContext,
1722
- contentSourceInstance
1723
- });
1724
- return {
1725
- type: operationField.type,
1726
- modelName: operationField.modelName,
1727
- fields: result.fields
1728
- };
1729
- }
1730
- case 'list': {
1731
- if (modelField.type !== 'list') {
1732
- throw new Error(`'the operation field type '${operationField.type}' does not match the model field type '${modelField.type}'`);
1733
- }
1734
- const result = await (0, utils_1.mapPromise)(operationField.items, async (item, index) => {
1735
- const result = await createNestedField({
1736
- value: item,
1737
- modelField: modelField.items,
1738
- fieldPath,
1739
- modelMap,
1740
- locale,
1741
- userContext,
1742
- contentSourceInstance
1743
- });
1744
- return result.field;
1745
- });
1746
- return {
1747
- type: operationField.type,
1748
- items: result
1749
- };
1750
- }
1751
- case 'string':
1752
- // When inserting new string value into a list, the client does not
1753
- // send value. Set an empty string value.
1754
- if (typeof operationField.value !== 'string') {
1755
- return {
1756
- type: operationField.type,
1757
- value: ''
1758
- };
1759
- }
1760
- return operationField;
1761
- case 'enum':
1762
- // When inserting new enum value into a list, the client does not
1763
- // send value. Set first option as the value.
1764
- if (typeof operationField.value !== 'string') {
1765
- if (modelFieldOrListItems.type !== 'enum') {
1766
- throw new Error(`'the operation field type 'enum' does not match the model field type '${modelFieldOrListItems.type}'`);
1767
- }
1768
- const option = modelFieldOrListItems.options[0];
1769
- const optionValue = typeof option === 'object' ? option.value : option;
1770
- return {
1771
- type: operationField.type,
1772
- value: optionValue
1773
- };
1774
- }
1775
- return operationField;
1776
- case 'image':
1777
- return operationField;
1778
- default:
1779
- return operationField;
1780
- }
1781
- }
1782
- function getDocumentFieldForLocale(docField, locale) {
1783
- if (docField.localized) {
1784
- if (!locale) {
1785
- return null;
1786
- }
1787
- const { localized, locales, ...base } = docField;
1788
- const localizedField = locales[locale];
1789
- if (!localizedField) {
1790
- return null;
1791
- }
1792
- return {
1793
- ...base,
1794
- ...localizedField
1795
- };
1796
- }
1797
- else {
1798
- return docField;
1799
- }
1800
- }
1801
951
  function getCSIDocumentsAndAssetsFromContentSourceDataByIds(contentSourceData, objects) {
1802
952
  const documents = [];
1803
953
  const assets = [];