@stackbit/cms-core 0.1.3-alpha.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/content-source-interface.d.ts +14 -9
- package/dist/content-source-interface.d.ts.map +1 -1
- package/dist/content-source-interface.js.map +1 -1
- package/dist/content-store-types.d.ts +24 -25
- package/dist/content-store-types.d.ts.map +1 -1
- package/dist/content-store.d.ts +4 -17
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +949 -147
- package/dist/content-store.js.map +1 -1
- package/dist/encoder.d.ts.map +1 -1
- package/dist/encoder.js +5 -1
- package/dist/encoder.js.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -6
- package/src/content-source-interface.ts +15 -6
- package/src/content-store-types.ts +10 -23
- package/src/content-store.ts +1079 -137
- package/src/encoder.ts +6 -2
- package/src/index.ts +1 -3
- package/dist/content-store-utils.d.ts +0 -9
- package/dist/content-store-utils.d.ts.map +0 -1
- package/dist/content-store-utils.js +0 -139
- package/dist/content-store-utils.js.map +0 -1
- package/dist/types/search-filter.d.ts +0 -42
- package/dist/types/search-filter.d.ts.map +0 -1
- package/dist/types/search-filter.js +0 -3
- package/dist/types/search-filter.js.map +0 -1
- package/dist/utils/create-update-csi-docs.d.ts +0 -68
- package/dist/utils/create-update-csi-docs.d.ts.map +0 -1
- package/dist/utils/create-update-csi-docs.js +0 -376
- package/dist/utils/create-update-csi-docs.js.map +0 -1
- package/dist/utils/csi-to-store-docs-converter.d.ts +0 -15
- package/dist/utils/csi-to-store-docs-converter.d.ts.map +0 -1
- package/dist/utils/csi-to-store-docs-converter.js +0 -287
- package/dist/utils/csi-to-store-docs-converter.js.map +0 -1
- package/dist/utils/search-utils.d.ts +0 -21
- package/dist/utils/search-utils.d.ts.map +0 -1
- package/dist/utils/search-utils.js +0 -323
- package/dist/utils/search-utils.js.map +0 -1
- package/dist/utils/store-to-api-docs-converter.d.ts +0 -5
- package/dist/utils/store-to-api-docs-converter.d.ts.map +0 -1
- package/dist/utils/store-to-api-docs-converter.js +0 -247
- package/dist/utils/store-to-api-docs-converter.js.map +0 -1
- package/src/content-store-utils.ts +0 -149
- package/src/types/search-filter.ts +0 -53
- package/src/utils/create-update-csi-docs.ts +0 -440
- package/src/utils/csi-to-store-docs-converter.ts +0 -365
- package/src/utils/search-utils.ts +0 -436
- package/src/utils/store-to-api-docs-converter.ts +0 -246
package/dist/content-store.js
CHANGED
|
@@ -3,19 +3,16 @@ 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.ContentStore = void 0;
|
|
6
|
+
exports.getContentSourceId = exports.ContentStore = void 0;
|
|
7
7
|
const lodash_1 = __importDefault(require("lodash"));
|
|
8
|
+
const slugify_1 = __importDefault(require("slugify"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
10
|
const sanitize_filename_1 = __importDefault(require("sanitize-filename"));
|
|
10
11
|
const sdk_1 = require("@stackbit/sdk");
|
|
11
12
|
const utils_1 = require("@stackbit/utils");
|
|
12
|
-
const timer_1 = require("./utils/timer");
|
|
13
|
-
const search_utils_1 = require("./utils/search-utils");
|
|
14
13
|
const content_source_interface_1 = require("./content-source-interface");
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const store_to_api_docs_converter_1 = require("./utils/store-to-api-docs-converter");
|
|
18
|
-
const create_update_csi_docs_1 = require("./utils/create-update-csi-docs");
|
|
14
|
+
const common_schema_1 = require("./common/common-schema");
|
|
15
|
+
const timer_1 = require("./utils/timer");
|
|
19
16
|
class ContentStore {
|
|
20
17
|
constructor(options) {
|
|
21
18
|
this.contentSources = [];
|
|
@@ -43,7 +40,7 @@ class ContentStore {
|
|
|
43
40
|
thisArg: this,
|
|
44
41
|
// Group the deferred calls by content source ID.
|
|
45
42
|
groupResolver: ({ contentSourceInstance }) => {
|
|
46
|
-
return
|
|
43
|
+
return getContentSourceIdForContentSource(contentSourceInstance);
|
|
47
44
|
},
|
|
48
45
|
// When the loadContentSourceData call is called multiple times with
|
|
49
46
|
// different "init" values, ensure that the deferred call will be
|
|
@@ -148,9 +145,9 @@ class ContentStore {
|
|
|
148
145
|
deletedAssets: []
|
|
149
146
|
};
|
|
150
147
|
for (const contentSourceInstance of this.contentSources) {
|
|
151
|
-
const contentSourceId =
|
|
148
|
+
const contentSourceId = getContentSourceIdForContentSource(contentSourceInstance);
|
|
152
149
|
this.logger.debug(`call onFilesChange for contentSource: ${contentSourceId}`);
|
|
153
|
-
const { schemaChanged, contentChangeEvent } = (_b =
|
|
150
|
+
const { schemaChanged, contentChangeEvent } = (_b = (_a = contentSourceInstance.onFilesChange) === null || _a === void 0 ? void 0 : _a.call(contentSourceInstance, { updatedFiles: updatedFiles })) !== null && _b !== void 0 ? _b : {};
|
|
154
151
|
this.logger.debug(`schemaChanged: ${schemaChanged}, has contentChangeEvent: ${!!contentChangeEvent}`);
|
|
155
152
|
// if schema is changed, there is no need to return contentChanges
|
|
156
153
|
// because schema changes reloads everything and implies content changes
|
|
@@ -188,8 +185,8 @@ class ContentStore {
|
|
|
188
185
|
this.contentUpdatesWatchTimer.startTimer();
|
|
189
186
|
}
|
|
190
187
|
async loadContentSourceData({ contentSourceInstance, init }) {
|
|
191
|
-
var _a, _b, _c, _d
|
|
192
|
-
const contentSourceId =
|
|
188
|
+
var _a, _b, _c, _d;
|
|
189
|
+
const contentSourceId = getContentSourceIdForContentSource(contentSourceInstance);
|
|
193
190
|
this.logger.debug('loadContentSourceData', { contentSourceId, init });
|
|
194
191
|
if (init) {
|
|
195
192
|
await contentSourceInstance.init({
|
|
@@ -222,19 +219,10 @@ class ContentStore {
|
|
|
222
219
|
models = (_c = config === null || config === void 0 ? void 0 : config.models) !== null && _c !== void 0 ? _c : [];
|
|
223
220
|
// TODO: load presets externally from config, and create additional map
|
|
224
221
|
// that maps presetIds by model name instead of storing that map inside every model
|
|
225
|
-
//
|
|
226
|
-
this.presets =
|
|
227
|
-
var _a, _b, _c;
|
|
228
|
-
const preset = (_a = config === null || config === void 0 ? void 0 : config.presets) === null || _a === void 0 ? void 0 : _a[presetId];
|
|
229
|
-
lodash_1.default.set(accum, [presetId], {
|
|
230
|
-
...preset,
|
|
231
|
-
srcType: (_b = preset === null || preset === void 0 ? void 0 : preset.srcType) !== null && _b !== void 0 ? _b : contentSourceInstance.getContentSourceType(),
|
|
232
|
-
srcProjectId: (_c = preset === null || preset === void 0 ? void 0 : preset.srcProjectId) !== null && _c !== void 0 ? _c : contentSourceInstance.getProjectId()
|
|
233
|
-
});
|
|
234
|
-
return accum;
|
|
235
|
-
}, {});
|
|
222
|
+
// TODO: adjust presets to have srcType and srcProjectId
|
|
223
|
+
this.presets = config === null || config === void 0 ? void 0 : config.presets;
|
|
236
224
|
}
|
|
237
|
-
if ((
|
|
225
|
+
if ((_d = this.rawStackbitConfig) === null || _d === void 0 ? void 0 : _d.mapModels) {
|
|
238
226
|
models = this.rawStackbitConfig.mapModels({
|
|
239
227
|
models: models,
|
|
240
228
|
contentSourceType: contentSourceInstance.getContentSourceType(),
|
|
@@ -247,13 +235,13 @@ class ContentStore {
|
|
|
247
235
|
const csiDocumentMap = lodash_1.default.keyBy(csiDocuments, 'id');
|
|
248
236
|
const csiAssetMap = lodash_1.default.keyBy(csiAssets, 'id');
|
|
249
237
|
const csiModelMap = lodash_1.default.keyBy(csiModels, 'name');
|
|
250
|
-
const contentStoreDocuments =
|
|
238
|
+
const contentStoreDocuments = mapCSIDocumentsToStoreDocuments({
|
|
251
239
|
csiDocuments,
|
|
252
240
|
contentSourceInstance,
|
|
253
241
|
modelMap,
|
|
254
242
|
defaultLocaleCode
|
|
255
243
|
});
|
|
256
|
-
const contentStoreAssets =
|
|
244
|
+
const contentStoreAssets = mapCSIAssetsToStoreAssets({
|
|
257
245
|
csiAssets,
|
|
258
246
|
contentSourceInstance,
|
|
259
247
|
defaultLocaleCode
|
|
@@ -365,13 +353,13 @@ class ContentStore {
|
|
|
365
353
|
});
|
|
366
354
|
});
|
|
367
355
|
// map csi documents and assets to content store documents and assets
|
|
368
|
-
const documents =
|
|
356
|
+
const documents = mapCSIDocumentsToStoreDocuments({
|
|
369
357
|
csiDocuments: contentChangeEvent.documents,
|
|
370
358
|
contentSourceInstance: contentSourceData.instance,
|
|
371
359
|
modelMap: contentSourceData.modelMap,
|
|
372
360
|
defaultLocaleCode: contentSourceData.defaultLocaleCode
|
|
373
361
|
});
|
|
374
|
-
const assets =
|
|
362
|
+
const assets = mapCSIAssetsToStoreAssets({
|
|
375
363
|
csiAssets: contentChangeEvent.assets,
|
|
376
364
|
contentSourceInstance: contentSourceData.instance,
|
|
377
365
|
defaultLocaleCode: contentSourceData.defaultLocaleCode
|
|
@@ -443,56 +431,25 @@ class ContentStore {
|
|
|
443
431
|
return (_a = this.presets) !== null && _a !== void 0 ? _a : {};
|
|
444
432
|
}
|
|
445
433
|
getContentSourceEnvironment({ srcProjectId, srcType }) {
|
|
446
|
-
const contentSourceId =
|
|
434
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
447
435
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
448
436
|
return contentSourceData.instance.getProjectEnvironment();
|
|
449
437
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
contentSourceDataArr = [contentSourceData];
|
|
456
|
-
}
|
|
457
|
-
else {
|
|
458
|
-
contentSourceDataArr = Object.values(this.contentSourceDataById);
|
|
459
|
-
}
|
|
460
|
-
return (0, utils_1.reducePromise)(contentSourceDataArr, async (accum, contentSourceData) => {
|
|
461
|
-
const srcType = contentSourceData.type;
|
|
462
|
-
const srcProjectId = contentSourceData.projectId;
|
|
463
|
-
const userContext = (0, content_store_utils_1.getUserContextForSrcType)(srcType, user);
|
|
464
|
-
let result = await contentSourceData.instance.hasAccess({ userContext });
|
|
465
|
-
// backwards compatibility with older CSI version
|
|
466
|
-
if (typeof result === 'boolean') {
|
|
467
|
-
result = {
|
|
468
|
-
hasConnection: result,
|
|
469
|
-
hasPermissions: result
|
|
470
|
-
};
|
|
471
|
-
}
|
|
472
|
-
return {
|
|
473
|
-
hasConnection: accum.hasConnection && result.hasConnection,
|
|
474
|
-
hasPermissions: accum.hasPermissions && result.hasPermissions,
|
|
475
|
-
contentSources: accum.contentSources.concat({
|
|
476
|
-
srcType,
|
|
477
|
-
srcProjectId,
|
|
478
|
-
...result
|
|
479
|
-
})
|
|
480
|
-
};
|
|
481
|
-
}, {
|
|
482
|
-
hasConnection: true,
|
|
483
|
-
hasPermissions: true,
|
|
484
|
-
contentSources: []
|
|
485
|
-
});
|
|
438
|
+
hasAccess({ srcType, srcProjectId, user }) {
|
|
439
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
440
|
+
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
441
|
+
const userContext = getUserContextForSrcType(srcType, user);
|
|
442
|
+
return contentSourceData.instance.hasAccess({ userContext });
|
|
486
443
|
}
|
|
487
444
|
hasChanges({ srcType, srcProjectId, documents }) {
|
|
488
445
|
let result;
|
|
489
446
|
if (srcType && srcProjectId) {
|
|
490
|
-
const contentSourceId =
|
|
447
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
491
448
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
492
449
|
result = [...contentSourceData.documents, ...contentSourceData.assets];
|
|
493
450
|
}
|
|
494
451
|
else if (documents && documents.length > 0) {
|
|
495
|
-
const documentsBySourceId = lodash_1.default.groupBy(documents, (document) =>
|
|
452
|
+
const documentsBySourceId = lodash_1.default.groupBy(documents, (document) => getContentSourceId(document.srcType, document.srcProjectId));
|
|
496
453
|
result = lodash_1.default.reduce(documentsBySourceId, (result, documents, contentSourceId) => {
|
|
497
454
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
498
455
|
for (const document of documents) {
|
|
@@ -522,7 +479,7 @@ class ContentStore {
|
|
|
522
479
|
};
|
|
523
480
|
}
|
|
524
481
|
getDocument({ srcDocumentId, srcProjectId, srcType }) {
|
|
525
|
-
const contentSourceId =
|
|
482
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
526
483
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
527
484
|
return contentSourceData.documentMap[srcDocumentId];
|
|
528
485
|
}
|
|
@@ -532,7 +489,7 @@ class ContentStore {
|
|
|
532
489
|
}, []);
|
|
533
490
|
}
|
|
534
491
|
getAsset({ srcAssetId, srcProjectId, srcType }) {
|
|
535
|
-
const contentSourceId =
|
|
492
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
536
493
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
537
494
|
return contentSourceData.assetMap[srcAssetId];
|
|
538
495
|
}
|
|
@@ -544,21 +501,21 @@ class ContentStore {
|
|
|
544
501
|
getLocalizedApiObjects({ locale }) {
|
|
545
502
|
return lodash_1.default.reduce(this.contentSourceDataById, (objects, contentSourceData) => {
|
|
546
503
|
locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
|
|
547
|
-
const documentObjects =
|
|
548
|
-
const imageObjects =
|
|
504
|
+
const documentObjects = mapDocumentsToLocalizedApiObjects(contentSourceData.documents, locale);
|
|
505
|
+
const imageObjects = mapAssetsToLocalizedApiImages(contentSourceData.assets, locale);
|
|
549
506
|
return objects.concat(documentObjects, imageObjects);
|
|
550
507
|
}, []);
|
|
551
508
|
}
|
|
552
509
|
getApiAssets({ srcType, srcProjectId, pageSize = 20, pageNum = 1, searchQuery } = {}) {
|
|
553
510
|
let assets;
|
|
554
511
|
if (srcProjectId && srcType) {
|
|
555
|
-
const contentSourceId =
|
|
512
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
556
513
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
557
|
-
assets =
|
|
514
|
+
assets = mapStoreAssetsToAPIAssets(contentSourceData.assets, contentSourceData.defaultLocaleCode);
|
|
558
515
|
}
|
|
559
516
|
else {
|
|
560
517
|
assets = lodash_1.default.reduce(this.contentSourceDataById, (result, contentSourceData) => {
|
|
561
|
-
const assets =
|
|
518
|
+
const assets = mapStoreAssetsToAPIAssets(contentSourceData.assets, contentSourceData.defaultLocaleCode);
|
|
562
519
|
return result.concat(assets);
|
|
563
520
|
}, []);
|
|
564
521
|
}
|
|
@@ -580,7 +537,7 @@ class ContentStore {
|
|
|
580
537
|
}
|
|
581
538
|
async createAndLinkDocument({ srcType, srcProjectId, srcDocumentId, fieldPath, modelName, object, index, locale, user }) {
|
|
582
539
|
this.logger.debug('createAndLinkDocument', { srcType, srcProjectId, srcDocumentId, fieldPath, modelName, index, locale });
|
|
583
|
-
const contentSourceId =
|
|
540
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
584
541
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
585
542
|
// get the document that is being updated
|
|
586
543
|
const document = contentSourceData.documentMap[srcDocumentId];
|
|
@@ -597,7 +554,7 @@ class ContentStore {
|
|
|
597
554
|
}
|
|
598
555
|
// get the 'reference' model field in the updated document that will be used to link the new document
|
|
599
556
|
locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
|
|
600
|
-
const modelField =
|
|
557
|
+
const modelField = getModelFieldForFieldAtPath(document, model, fieldPath, csiModelMap, locale);
|
|
601
558
|
if (!modelField) {
|
|
602
559
|
throw Error(`the "fieldPath" points to non existing model field: ${fieldPath.join('.')}`);
|
|
603
560
|
}
|
|
@@ -622,7 +579,7 @@ class ContentStore {
|
|
|
622
579
|
user: user
|
|
623
580
|
});
|
|
624
581
|
// update the document by linking the field to the created document
|
|
625
|
-
const userContext =
|
|
582
|
+
const userContext = getUserContextForSrcType(srcType, user);
|
|
626
583
|
const field = {
|
|
627
584
|
type: 'reference',
|
|
628
585
|
refType: 'document',
|
|
@@ -656,7 +613,7 @@ class ContentStore {
|
|
|
656
613
|
async uploadAndLinkAsset({ srcType, srcProjectId, srcDocumentId, fieldPath, asset, index, locale, user }) {
|
|
657
614
|
this.logger.debug('uploadAndLinkAsset', { srcType, srcProjectId, srcDocumentId, fieldPath, index, locale });
|
|
658
615
|
// get the document that is being updated
|
|
659
|
-
const contentSourceId =
|
|
616
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
660
617
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
661
618
|
const document = contentSourceData.documentMap[srcDocumentId];
|
|
662
619
|
const csiDocument = contentSourceData.csiDocumentMap[srcDocumentId];
|
|
@@ -672,7 +629,7 @@ class ContentStore {
|
|
|
672
629
|
}
|
|
673
630
|
// get the 'reference' model field in the updated document that will be used to link the new asset
|
|
674
631
|
locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
|
|
675
|
-
const modelField =
|
|
632
|
+
const modelField = getModelFieldForFieldAtPath(document, csiModel, fieldPath, csiModelMap, locale);
|
|
676
633
|
if (!modelField) {
|
|
677
634
|
throw Error(`the "fieldPath" points to non existing model field: ${fieldPath.join('.')}`);
|
|
678
635
|
}
|
|
@@ -681,7 +638,7 @@ class ContentStore {
|
|
|
681
638
|
throw Error(`error in "uploadAndLinkAsset", this operation can only be used on reference and image fields: ${fieldPath.join('.')}`);
|
|
682
639
|
}
|
|
683
640
|
// upload the new asset
|
|
684
|
-
const userContext =
|
|
641
|
+
const userContext = getUserContextForSrcType(srcType, user);
|
|
685
642
|
const result = await contentSourceData.instance.uploadAsset({
|
|
686
643
|
url: asset.url,
|
|
687
644
|
fileName: asset.metadata.name,
|
|
@@ -722,22 +679,22 @@ class ContentStore {
|
|
|
722
679
|
}
|
|
723
680
|
async createDocument({ srcType, srcProjectId, modelName, object, locale, user }) {
|
|
724
681
|
this.logger.debug('createDocument', { srcType, srcProjectId, modelName, locale });
|
|
725
|
-
const contentSourceId =
|
|
682
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
726
683
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
727
684
|
const modelMap = contentSourceData.modelMap;
|
|
728
|
-
const
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
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({
|
|
732
692
|
object,
|
|
733
|
-
|
|
693
|
+
model,
|
|
734
694
|
modelMap,
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
userContext,
|
|
739
|
-
contentSourceInstance: contentSourceData.instance
|
|
740
|
-
})
|
|
695
|
+
locale,
|
|
696
|
+
userContext,
|
|
697
|
+
contentSourceInstance: contentSourceData.instance
|
|
741
698
|
});
|
|
742
699
|
this.logger.debug('created document', { srcType, srcProjectId, srcDocumentId: result.document.id, modelName });
|
|
743
700
|
// do not update cache in contentSourceData.documents and documentMap,
|
|
@@ -749,9 +706,9 @@ class ContentStore {
|
|
|
749
706
|
}
|
|
750
707
|
async updateDocument({ srcType, srcProjectId, srcDocumentId, updateOperations, user }) {
|
|
751
708
|
this.logger.debug('updateDocument');
|
|
752
|
-
const contentSourceId =
|
|
709
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
753
710
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
754
|
-
const userContext =
|
|
711
|
+
const userContext = getUserContextForSrcType(srcType, user);
|
|
755
712
|
const document = contentSourceData.documentMap[srcDocumentId];
|
|
756
713
|
const csiDocument = contentSourceData.csiDocumentMap[srcDocumentId];
|
|
757
714
|
if (!document || !csiDocument) {
|
|
@@ -767,20 +724,17 @@ class ContentStore {
|
|
|
767
724
|
const operations = await (0, utils_1.mapPromise)(updateOperations, async (updateOperation) => {
|
|
768
725
|
var _a;
|
|
769
726
|
const locale = (_a = updateOperation.locale) !== null && _a !== void 0 ? _a : contentSourceData.defaultLocaleCode;
|
|
770
|
-
const modelField =
|
|
727
|
+
const modelField = getModelFieldForFieldAtPath(document, model, updateOperation.fieldPath, modelMap, locale);
|
|
771
728
|
switch (updateOperation.opType) {
|
|
772
729
|
case 'set':
|
|
773
|
-
const field = await
|
|
730
|
+
const field = await convertOperationField({
|
|
774
731
|
operationField: updateOperation.field,
|
|
775
732
|
fieldPath: updateOperation.fieldPath,
|
|
733
|
+
locale: updateOperation.locale,
|
|
776
734
|
modelField,
|
|
777
735
|
modelMap,
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
csiModelMap,
|
|
781
|
-
userContext,
|
|
782
|
-
contentSourceInstance: contentSourceData.instance
|
|
783
|
-
})
|
|
736
|
+
userContext,
|
|
737
|
+
contentSourceInstance: contentSourceData.instance
|
|
784
738
|
});
|
|
785
739
|
return {
|
|
786
740
|
...updateOperation,
|
|
@@ -790,17 +744,14 @@ class ContentStore {
|
|
|
790
744
|
case 'unset':
|
|
791
745
|
return { ...updateOperation, modelField };
|
|
792
746
|
case 'insert':
|
|
793
|
-
const item = await
|
|
747
|
+
const item = await convertOperationField({
|
|
794
748
|
operationField: updateOperation.item,
|
|
795
749
|
fieldPath: updateOperation.fieldPath,
|
|
750
|
+
locale: updateOperation.locale,
|
|
796
751
|
modelField,
|
|
797
752
|
modelMap,
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
csiModelMap,
|
|
801
|
-
userContext,
|
|
802
|
-
contentSourceInstance: contentSourceData.instance
|
|
803
|
-
})
|
|
753
|
+
userContext,
|
|
754
|
+
contentSourceInstance: contentSourceData.instance
|
|
804
755
|
});
|
|
805
756
|
return {
|
|
806
757
|
...updateOperation,
|
|
@@ -827,24 +778,22 @@ class ContentStore {
|
|
|
827
778
|
}
|
|
828
779
|
async duplicateDocument({ srcType, srcProjectId, srcDocumentId, object, user }) {
|
|
829
780
|
this.logger.debug('duplicateDocument');
|
|
830
|
-
const contentSourceId =
|
|
781
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
831
782
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
832
783
|
const document = contentSourceData.documentMap[srcDocumentId];
|
|
833
784
|
if (!document) {
|
|
834
785
|
throw new Error(`no document with id '${srcDocumentId}' was found in ${contentSourceData.id}`);
|
|
835
786
|
}
|
|
836
787
|
const modelMap = contentSourceData.modelMap;
|
|
837
|
-
const csiModelMap = contentSourceData.csiModelMap;
|
|
838
788
|
const model = modelMap[document.srcModelName];
|
|
839
|
-
|
|
840
|
-
if (!model || !csiModel) {
|
|
789
|
+
if (!model) {
|
|
841
790
|
throw new Error(`no model with name '${document.srcModelName}' was found`);
|
|
842
791
|
}
|
|
843
|
-
const userContext =
|
|
792
|
+
const userContext = getUserContextForSrcType(srcType, user);
|
|
844
793
|
// TODO: take the data from the provided 'object' and merge them with
|
|
845
794
|
// DocumentFields of the existing Document:
|
|
846
795
|
// Option 1: Map the DocumentFields of the existing Document into flat
|
|
847
|
-
// object with '$$ref' and '
|
|
796
|
+
// object with '$$ref' and '$type' properties for references and
|
|
848
797
|
// nested objects (needs to be implemented), and then merge it with
|
|
849
798
|
// the provided object recursively, and then pass that object to
|
|
850
799
|
// createNestedObjectRecursively()
|
|
@@ -860,14 +809,12 @@ class ContentStore {
|
|
|
860
809
|
modelFields: model.fields,
|
|
861
810
|
modelMap: contentSourceData.modelMap
|
|
862
811
|
});
|
|
863
|
-
// When passing model and modelMap to contentSourceInstance, we have to pass
|
|
864
|
-
// the original models (i.e., csiModel and csiModelMap) that we've received
|
|
865
|
-
// from that contentSourceInstance. We can't pass internal models as they
|
|
866
|
-
// might
|
|
867
812
|
const documentResult = await contentSourceData.instance.createDocument({
|
|
868
813
|
updateOperationFields,
|
|
869
|
-
|
|
870
|
-
|
|
814
|
+
// TODO: pass csiModel
|
|
815
|
+
model,
|
|
816
|
+
// TODO: pass csiModelMap
|
|
817
|
+
modelMap,
|
|
871
818
|
locale: contentSourceData.defaultLocaleCode,
|
|
872
819
|
userContext
|
|
873
820
|
});
|
|
@@ -875,10 +822,10 @@ class ContentStore {
|
|
|
875
822
|
}
|
|
876
823
|
async uploadAssets({ srcType, srcProjectId, assets, locale, user }) {
|
|
877
824
|
this.logger.debug('uploadAssets');
|
|
878
|
-
const contentSourceId =
|
|
825
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
879
826
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
880
827
|
const sourceAssets = [];
|
|
881
|
-
const userContext =
|
|
828
|
+
const userContext = getUserContextForSrcType(srcType, user);
|
|
882
829
|
locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
|
|
883
830
|
for (const asset of assets) {
|
|
884
831
|
let base64 = undefined;
|
|
@@ -898,17 +845,17 @@ class ContentStore {
|
|
|
898
845
|
});
|
|
899
846
|
sourceAssets.push(sourceAsset);
|
|
900
847
|
}
|
|
901
|
-
const storeAssets =
|
|
848
|
+
const storeAssets = mapCSIAssetsToStoreAssets({
|
|
902
849
|
csiAssets: sourceAssets,
|
|
903
850
|
contentSourceInstance: contentSourceData.instance,
|
|
904
851
|
defaultLocaleCode: contentSourceData.defaultLocaleCode
|
|
905
852
|
});
|
|
906
|
-
return
|
|
853
|
+
return mapStoreAssetsToAPIAssets(storeAssets, locale);
|
|
907
854
|
}
|
|
908
855
|
async deleteDocument({ srcType, srcProjectId, srcDocumentId, user }) {
|
|
909
856
|
this.logger.debug('deleteDocument');
|
|
910
|
-
const userContext =
|
|
911
|
-
const contentSourceId =
|
|
857
|
+
const userContext = getUserContextForSrcType(srcType, user);
|
|
858
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
912
859
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
913
860
|
const csiDocument = contentSourceData.csiDocumentMap[srcDocumentId];
|
|
914
861
|
if (!csiDocument) {
|
|
@@ -922,13 +869,13 @@ class ContentStore {
|
|
|
922
869
|
}
|
|
923
870
|
async validateDocuments({ objects, locale, user }) {
|
|
924
871
|
this.logger.debug('validateDocuments');
|
|
925
|
-
const objectsBySourceId = lodash_1.default.groupBy(objects, (object) =>
|
|
872
|
+
const objectsBySourceId = lodash_1.default.groupBy(objects, (object) => getContentSourceId(object.srcType, object.srcProjectId));
|
|
926
873
|
let errors = [];
|
|
927
874
|
for (const [contentSourceId, contentSourceObjects] of Object.entries(objectsBySourceId)) {
|
|
928
875
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
929
876
|
locale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
|
|
930
877
|
const { documents, assets } = getCSIDocumentsAndAssetsFromContentSourceDataByIds(contentSourceData, contentSourceObjects);
|
|
931
|
-
const userContext =
|
|
878
|
+
const userContext = getUserContextForSrcType(contentSourceData.type, user);
|
|
932
879
|
const internalValidationErrors = internalValidateContent(documents, assets, contentSourceData);
|
|
933
880
|
const validationResult = await contentSourceData.instance.validateDocuments({ documents, assets, locale, userContext });
|
|
934
881
|
errors = errors.concat(internalValidationErrors, validationResult.errors.map((validationError) => ({
|
|
@@ -957,28 +904,12 @@ class ContentStore {
|
|
|
957
904
|
);
|
|
958
905
|
*/
|
|
959
906
|
}
|
|
960
|
-
async searchDocuments(data) {
|
|
961
|
-
this.logger.debug('searchDocuments');
|
|
962
|
-
const objectsBySourceId = lodash_1.default.groupBy(data.models, (object) => (0, content_store_utils_1.getContentSourceId)(object.srcType, object.srcProjectId));
|
|
963
|
-
const documents = [];
|
|
964
|
-
const schema = {};
|
|
965
|
-
Object.keys(objectsBySourceId).forEach((contentSourceId) => {
|
|
966
|
-
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
967
|
-
documents.push(...contentSourceData.documents);
|
|
968
|
-
lodash_1.default.set(schema, [contentSourceData.type, contentSourceData.projectId], contentSourceData.modelMap);
|
|
969
|
-
});
|
|
970
|
-
return (0, search_utils_1.searchDocuments)({
|
|
971
|
-
...data,
|
|
972
|
-
documents,
|
|
973
|
-
schema
|
|
974
|
-
});
|
|
975
|
-
}
|
|
976
907
|
async publishDocuments({ objects, user }) {
|
|
977
908
|
this.logger.debug('publishDocuments');
|
|
978
|
-
const objectsBySourceId = lodash_1.default.groupBy(objects, (object) =>
|
|
909
|
+
const objectsBySourceId = lodash_1.default.groupBy(objects, (object) => getContentSourceId(object.srcType, object.srcProjectId));
|
|
979
910
|
for (const [contentSourceId, contentSourceObjects] of Object.entries(objectsBySourceId)) {
|
|
980
911
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
981
|
-
const userContext =
|
|
912
|
+
const userContext = getUserContextForSrcType(contentSourceData.type, user);
|
|
982
913
|
const { documents, assets } = getCSIDocumentsAndAssetsFromContentSourceDataByIds(contentSourceData, contentSourceObjects);
|
|
983
914
|
await contentSourceData.instance.publishDocuments({ documents, assets, userContext });
|
|
984
915
|
}
|
|
@@ -992,10 +923,881 @@ class ContentStore {
|
|
|
992
923
|
}
|
|
993
924
|
}
|
|
994
925
|
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
|
+
}
|
|
995
1179
|
function mapStoreFieldsToOperationFields({ documentFields, modelFields, modelMap }) {
|
|
996
1180
|
// TODO: implement
|
|
997
1181
|
throw new Error(`duplicateDocument not implemented yet`);
|
|
998
1182
|
}
|
|
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
|
+
}
|
|
999
1801
|
function getCSIDocumentsAndAssetsFromContentSourceDataByIds(contentSourceData, objects) {
|
|
1000
1802
|
const documents = [];
|
|
1001
1803
|
const assets = [];
|