@stackbit/cms-core 0.0.18-alpha.0 → 0.0.19-alpha.2
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 +70 -26
- package/dist/content-source-interface.d.ts.map +1 -1
- package/dist/content-source-interface.js +1 -1
- package/dist/content-source-interface.js.map +1 -1
- package/dist/content-store-types.d.ts +31 -8
- package/dist/content-store-types.d.ts.map +1 -1
- package/dist/content-store.d.ts +4 -4
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +415 -317
- package/dist/content-store.js.map +1 -1
- package/package.json +2 -2
- package/src/content-source-interface.ts +107 -31
- package/src/content-store-types.ts +32 -8
- package/src/content-store.ts +497 -378
package/src/content-store.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
Model
|
|
17
17
|
} from '@stackbit/sdk';
|
|
18
18
|
import { mapPromise, omitByNil } from '@stackbit/utils';
|
|
19
|
-
import * as
|
|
19
|
+
import * as CSITypes from './content-source-interface';
|
|
20
20
|
import { isLocalizedField } from './content-source-interface';
|
|
21
21
|
import * as ContentStoreTypes from './content-store-types';
|
|
22
22
|
import { IMAGE_MODEL } from './common/common-schema';
|
|
@@ -27,7 +27,7 @@ export interface ContentSourceOptions {
|
|
|
27
27
|
userLogger: ContentStoreTypes.Logger;
|
|
28
28
|
localDev: boolean;
|
|
29
29
|
stackbitYamlDir: string;
|
|
30
|
-
contentSources:
|
|
30
|
+
contentSources: CSITypes.ContentSourceInterface[];
|
|
31
31
|
onSchemaChangeCallback: () => void;
|
|
32
32
|
onContentChangeCallback: (contentChanges: ContentStoreTypes.ContentChangeResult) => void;
|
|
33
33
|
handleConfigAssets: (config: Config) => Promise<Config>;
|
|
@@ -35,21 +35,25 @@ export interface ContentSourceOptions {
|
|
|
35
35
|
|
|
36
36
|
interface ContentSourceData {
|
|
37
37
|
id: string;
|
|
38
|
-
instance:
|
|
38
|
+
instance: CSITypes.ContentSourceInterface;
|
|
39
39
|
type: string;
|
|
40
40
|
projectId: string;
|
|
41
41
|
models: Model[];
|
|
42
42
|
modelMap: Record<string, Model>;
|
|
43
|
-
locales?:
|
|
43
|
+
locales?: CSITypes.Locale[];
|
|
44
44
|
defaultLocaleCode?: string;
|
|
45
|
+
csiDocuments: CSITypes.Document[];
|
|
46
|
+
csiDocumentMap: Record<string, CSITypes.Document>;
|
|
45
47
|
documents: ContentStoreTypes.Document[];
|
|
46
48
|
documentMap: Record<string, ContentStoreTypes.Document>;
|
|
49
|
+
csiAssets: CSITypes.Asset[];
|
|
50
|
+
csiAssetMap: Record<string, CSITypes.Asset>;
|
|
47
51
|
assets: ContentStoreTypes.Asset[];
|
|
48
52
|
assetMap: Record<string, ContentStoreTypes.Asset>;
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
export class ContentStore {
|
|
52
|
-
private readonly contentSources:
|
|
56
|
+
private readonly contentSources: CSITypes.ContentSourceInterface[];
|
|
53
57
|
private readonly logger: ContentStoreTypes.Logger;
|
|
54
58
|
private readonly userLogger: ContentStoreTypes.Logger;
|
|
55
59
|
private readonly localDev: boolean;
|
|
@@ -205,7 +209,7 @@ export class ContentStore {
|
|
|
205
209
|
return config;
|
|
206
210
|
}
|
|
207
211
|
|
|
208
|
-
async loadContentSourceData({ contentSourceInstance, init }: { contentSourceInstance:
|
|
212
|
+
async loadContentSourceData({ contentSourceInstance, init }: { contentSourceInstance: CSITypes.ContentSourceInterface; init: boolean }) {
|
|
209
213
|
// TODO: defer loading content if content is already loading for a specific content source
|
|
210
214
|
|
|
211
215
|
// TODO: optimize: cache raw responses from contentSource
|
|
@@ -242,19 +246,24 @@ export class ContentStore {
|
|
|
242
246
|
// that maps presetIds by model name instead of storing that map inside every model
|
|
243
247
|
this.presets = config.presets;
|
|
244
248
|
|
|
245
|
-
const
|
|
246
|
-
const
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
+
const csiDocuments = await contentSourceInstance.getDocuments({ modelMap });
|
|
250
|
+
const csiAssets = await contentSourceInstance.getAssets();
|
|
251
|
+
const csiDocumentMap = _.keyBy(csiDocuments, 'id');
|
|
252
|
+
const csiAssetMap = _.keyBy(csiAssets, 'id');
|
|
253
|
+
|
|
254
|
+
const contentStoreDocuments = mapCSIDocumentsToStoreDocuments({
|
|
255
|
+
csiDocuments,
|
|
249
256
|
contentSourceInstance,
|
|
250
257
|
modelMap,
|
|
251
258
|
defaultLocaleCode
|
|
252
259
|
});
|
|
253
|
-
const contentStoreAssets =
|
|
254
|
-
|
|
260
|
+
const contentStoreAssets = mapCSIAssetsToStoreAssets({
|
|
261
|
+
csiAssets,
|
|
255
262
|
contentSourceInstance,
|
|
256
263
|
defaultLocaleCode
|
|
257
264
|
});
|
|
265
|
+
const documentMap = _.keyBy(contentStoreDocuments, 'srcObjectId');
|
|
266
|
+
const assetMap = _.keyBy(contentStoreAssets, 'srcObjectId');
|
|
258
267
|
|
|
259
268
|
this.logger.debug('loaded content source data', {
|
|
260
269
|
contentSourceId,
|
|
@@ -274,10 +283,14 @@ export class ContentStore {
|
|
|
274
283
|
defaultLocaleCode: defaultLocaleCode,
|
|
275
284
|
models: models,
|
|
276
285
|
modelMap: modelMap,
|
|
286
|
+
csiDocuments: csiDocuments,
|
|
287
|
+
csiDocumentMap: csiDocumentMap,
|
|
277
288
|
documents: contentStoreDocuments,
|
|
278
|
-
documentMap:
|
|
289
|
+
documentMap: documentMap,
|
|
290
|
+
csiAssets: csiAssets,
|
|
291
|
+
csiAssetMap: csiAssetMap,
|
|
279
292
|
assets: contentStoreAssets,
|
|
280
|
-
assetMap:
|
|
293
|
+
assetMap: assetMap
|
|
281
294
|
};
|
|
282
295
|
|
|
283
296
|
contentSourceInstance.startWatchingContentUpdates({
|
|
@@ -285,7 +298,13 @@ export class ContentStore {
|
|
|
285
298
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
286
299
|
return contentSourceData.modelMap;
|
|
287
300
|
},
|
|
288
|
-
|
|
301
|
+
getDocument({ documentId }: { documentId: string }) {
|
|
302
|
+
return csiDocumentMap[documentId];
|
|
303
|
+
},
|
|
304
|
+
getAsset({ assetId }: { assetId: string }) {
|
|
305
|
+
return csiAssetMap[assetId];
|
|
306
|
+
},
|
|
307
|
+
onContentChange: (contentChangeEvent: CSITypes.ContentChangeEvent) => {
|
|
289
308
|
this.logger.debug('content source called onContentChange', { contentSourceId });
|
|
290
309
|
const result = this.onContentChange(contentSourceId, contentChangeEvent);
|
|
291
310
|
this.onContentChangeCallback(result);
|
|
@@ -301,7 +320,7 @@ export class ContentStore {
|
|
|
301
320
|
});
|
|
302
321
|
}
|
|
303
322
|
|
|
304
|
-
onContentChange(contentSourceId: string, contentChangeEvent:
|
|
323
|
+
onContentChange(contentSourceId: string, contentChangeEvent: CSITypes.ContentChangeEvent): ContentStoreTypes.ContentChangeResult {
|
|
305
324
|
// TODO: prevent content change process for contentSourceId if loading content is in progress
|
|
306
325
|
|
|
307
326
|
this.logger.debug('onContentChange', {
|
|
@@ -320,50 +339,80 @@ export class ContentStore {
|
|
|
320
339
|
};
|
|
321
340
|
|
|
322
341
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
342
|
+
|
|
343
|
+
// update contentSourceData with deleted documents
|
|
323
344
|
contentChangeEvent.deletedDocumentIds.forEach((docId) => {
|
|
345
|
+
// delete document from documents map
|
|
324
346
|
delete contentSourceData.documentMap[docId];
|
|
347
|
+
delete contentSourceData.csiDocumentMap[docId];
|
|
348
|
+
|
|
349
|
+
// delete document from document array
|
|
325
350
|
const index = contentSourceData.documents.findIndex((document) => document.srcObjectId === docId);
|
|
326
351
|
if (index !== -1) {
|
|
352
|
+
// the indexes of documents and csiDocuments are always the same as they are always updated at the same time
|
|
327
353
|
contentSourceData.documents.splice(index, 1);
|
|
354
|
+
contentSourceData.csiDocuments.splice(index, 1);
|
|
328
355
|
}
|
|
356
|
+
|
|
329
357
|
result.deletedDocuments.push({
|
|
330
358
|
srcType: contentSourceData.type,
|
|
331
359
|
srcProjectId: contentSourceData.projectId,
|
|
332
360
|
srcObjectId: docId
|
|
333
361
|
});
|
|
334
362
|
});
|
|
363
|
+
|
|
364
|
+
// update contentSourceData with deleted assets
|
|
335
365
|
contentChangeEvent.deletedAssetIds.forEach((assetId) => {
|
|
366
|
+
// delete document from asset map
|
|
336
367
|
delete contentSourceData.assetMap[assetId];
|
|
368
|
+
delete contentSourceData.csiAssetMap[assetId];
|
|
369
|
+
|
|
370
|
+
// delete document from asset array
|
|
337
371
|
const index = contentSourceData.assets.findIndex((asset) => asset.srcObjectId === assetId);
|
|
338
372
|
if (index !== -1) {
|
|
373
|
+
// the indexes of assets and csiAssets are always the same as they are always updated at the same time
|
|
339
374
|
contentSourceData.assets.splice(index, 1);
|
|
375
|
+
contentSourceData.csiAssets.splice(index, 1);
|
|
340
376
|
}
|
|
377
|
+
|
|
341
378
|
result.deletedAssets.push({
|
|
342
379
|
srcType: contentSourceData.type,
|
|
343
380
|
srcProjectId: contentSourceData.projectId,
|
|
344
381
|
srcObjectId: assetId
|
|
345
382
|
});
|
|
346
383
|
});
|
|
347
|
-
|
|
348
|
-
|
|
384
|
+
|
|
385
|
+
// map csi documents and assets to content store documents and assets
|
|
386
|
+
const documents = mapCSIDocumentsToStoreDocuments({
|
|
387
|
+
csiDocuments: contentChangeEvent.documents,
|
|
349
388
|
contentSourceInstance: contentSourceData.instance,
|
|
350
389
|
modelMap: contentSourceData.modelMap,
|
|
351
390
|
defaultLocaleCode: contentSourceData.defaultLocaleCode
|
|
352
391
|
});
|
|
353
|
-
const assets =
|
|
354
|
-
|
|
392
|
+
const assets = mapCSIAssetsToStoreAssets({
|
|
393
|
+
csiAssets: contentChangeEvent.assets,
|
|
355
394
|
contentSourceInstance: contentSourceData.instance,
|
|
356
395
|
defaultLocaleCode: contentSourceData.defaultLocaleCode
|
|
357
396
|
});
|
|
358
397
|
|
|
398
|
+
// update contentSourceData with new or updated documents and assets
|
|
399
|
+
Object.assign(contentSourceData.csiDocumentMap, _.keyBy(contentChangeEvent.documents, 'id'));
|
|
400
|
+
Object.assign(contentSourceData.csiAssets, _.keyBy(contentChangeEvent.assets, 'id'));
|
|
359
401
|
Object.assign(contentSourceData.documentMap, _.keyBy(documents, 'srcObjectId'));
|
|
360
402
|
Object.assign(contentSourceData.assetMap, _.keyBy(assets, 'srcObjectId'));
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
403
|
+
|
|
404
|
+
for (let idx = 0; idx < documents.length; idx++) {
|
|
405
|
+
// the indexes of mapped documents and documents from changeEvent are the same
|
|
406
|
+
const document = documents[idx]!;
|
|
407
|
+
const csiDocument = contentChangeEvent.documents[idx]!;
|
|
408
|
+
const dataIndex = contentSourceData.documents.findIndex((existingDoc) => existingDoc.srcObjectId === document.srcObjectId);
|
|
409
|
+
if (dataIndex === -1) {
|
|
364
410
|
contentSourceData.documents.push(document);
|
|
411
|
+
contentSourceData.csiDocuments.push(csiDocument);
|
|
365
412
|
} else {
|
|
366
|
-
|
|
413
|
+
// the indexes of documents and csiDocuments are always the same as they are always updated at the same time
|
|
414
|
+
contentSourceData.documents.splice(dataIndex, 1, document);
|
|
415
|
+
contentSourceData.csiDocuments.splice(dataIndex, 1, csiDocument);
|
|
367
416
|
}
|
|
368
417
|
result.updatedDocuments.push({
|
|
369
418
|
srcType: contentSourceData.type,
|
|
@@ -371,12 +420,19 @@ export class ContentStore {
|
|
|
371
420
|
srcObjectId: document.srcObjectId
|
|
372
421
|
});
|
|
373
422
|
}
|
|
374
|
-
|
|
423
|
+
|
|
424
|
+
for (let idx = 0; idx < assets.length; idx++) {
|
|
425
|
+
// the indexes of mapped assets and assets from changeEvent are the same
|
|
426
|
+
const asset = assets[idx]!;
|
|
427
|
+
const csiAsset = contentChangeEvent.assets[idx]!;
|
|
375
428
|
const index = contentSourceData.assets.findIndex((existingAsset) => existingAsset.srcObjectId === asset.srcObjectId);
|
|
376
429
|
if (index === -1) {
|
|
377
430
|
contentSourceData.assets.push(asset);
|
|
431
|
+
contentSourceData.csiAssets.push(csiAsset);
|
|
378
432
|
} else {
|
|
433
|
+
// the indexes of assets and csiAssets are always the same as they are always updated at the same time
|
|
379
434
|
contentSourceData.assets.splice(index, 1, asset);
|
|
435
|
+
contentSourceData.csiAssets.splice(index, 1, csiAsset);
|
|
380
436
|
}
|
|
381
437
|
result.updatedAssets.push({
|
|
382
438
|
srcType: contentSourceData.type,
|
|
@@ -614,7 +670,8 @@ export class ContentStore {
|
|
|
614
670
|
|
|
615
671
|
// get the document that is being updated
|
|
616
672
|
const document = contentSourceData.documentMap[srcDocumentId];
|
|
617
|
-
|
|
673
|
+
const csiDocument = contentSourceData.csiDocumentMap[srcDocumentId];
|
|
674
|
+
if (!document || !csiDocument) {
|
|
618
675
|
throw new Error(`no document with id '${srcDocumentId}' was found in ${contentSourceData.id}`);
|
|
619
676
|
}
|
|
620
677
|
|
|
@@ -663,7 +720,7 @@ export class ContentStore {
|
|
|
663
720
|
refId: result.srcDocumentId
|
|
664
721
|
} as const;
|
|
665
722
|
const updatedDocument = await contentSourceData.instance.updateDocument({
|
|
666
|
-
|
|
723
|
+
document: csiDocument,
|
|
667
724
|
modelMap: modelMap,
|
|
668
725
|
userContext: userContext,
|
|
669
726
|
operations: [
|
|
@@ -713,7 +770,8 @@ export class ContentStore {
|
|
|
713
770
|
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
714
771
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
715
772
|
const document = contentSourceData.documentMap[srcDocumentId];
|
|
716
|
-
|
|
773
|
+
const csiDocument = contentSourceData.csiDocumentMap[srcDocumentId];
|
|
774
|
+
if (!document || !csiDocument) {
|
|
717
775
|
throw new Error(`no document with id '${srcDocumentId}' was found in ${contentSourceData.id}`);
|
|
718
776
|
}
|
|
719
777
|
|
|
@@ -753,7 +811,7 @@ export class ContentStore {
|
|
|
753
811
|
refId: result.id
|
|
754
812
|
} as const;
|
|
755
813
|
const updatedDocument = await contentSourceData.instance.updateDocument({
|
|
756
|
-
|
|
814
|
+
document: csiDocument,
|
|
757
815
|
modelMap: modelMap,
|
|
758
816
|
userContext: userContext,
|
|
759
817
|
operations: [
|
|
@@ -841,21 +899,23 @@ export class ContentStore {
|
|
|
841
899
|
|
|
842
900
|
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
843
901
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
844
|
-
const modelMap = contentSourceData.modelMap;
|
|
845
902
|
const userContext = getUserContextForSrcType(srcType, user);
|
|
903
|
+
const document = contentSourceData.documentMap[srcDocumentId];
|
|
904
|
+
const csiDocument = contentSourceData.csiDocumentMap[srcDocumentId];
|
|
905
|
+
if (!document || !csiDocument) {
|
|
906
|
+
throw new Error(`no document with id '${srcDocumentId}' was found in ${contentSourceData.id}`);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
const modelMap = contentSourceData.modelMap;
|
|
910
|
+
const documentModelName = document.srcModelName;
|
|
911
|
+
const model = modelMap[documentModelName];
|
|
912
|
+
if (!model) {
|
|
913
|
+
throw new Error(`error updating document, could not find document model: '${documentModelName}'`);
|
|
914
|
+
}
|
|
846
915
|
|
|
847
916
|
const operations = await mapPromise(
|
|
848
917
|
updateOperations,
|
|
849
|
-
async (updateOperation): Promise<
|
|
850
|
-
const document = contentSourceData.documentMap[srcDocumentId];
|
|
851
|
-
if (!document) {
|
|
852
|
-
throw new Error(`no document with id '${srcDocumentId}' was found in ${contentSourceData.id}`);
|
|
853
|
-
}
|
|
854
|
-
const documentModelName = document.srcModelName;
|
|
855
|
-
const model = modelMap[documentModelName];
|
|
856
|
-
if (!model) {
|
|
857
|
-
throw new Error(`error updating document, could not find document model: '${documentModelName}'`);
|
|
858
|
-
}
|
|
918
|
+
async (updateOperation): Promise<CSITypes.UpdateOperation> => {
|
|
859
919
|
const locale = updateOperation.locale ?? contentSourceData.defaultLocaleCode;
|
|
860
920
|
const modelField = getModelFieldForFieldAtPath(document, model, updateOperation.fieldPath, modelMap, locale);
|
|
861
921
|
switch (updateOperation.opType) {
|
|
@@ -899,8 +959,8 @@ export class ContentStore {
|
|
|
899
959
|
}
|
|
900
960
|
);
|
|
901
961
|
|
|
902
|
-
const
|
|
903
|
-
|
|
962
|
+
const updatedDocumentResult = await contentSourceData.instance.updateDocument({
|
|
963
|
+
document: csiDocument,
|
|
904
964
|
modelMap,
|
|
905
965
|
userContext,
|
|
906
966
|
operations
|
|
@@ -911,7 +971,7 @@ export class ContentStore {
|
|
|
911
971
|
// and use data from contentChangeEvent to update the cache
|
|
912
972
|
// contentSourceData.documentMap = Object.assign(contentSourceData.documentMap, { [document.srcObjectId]: document });
|
|
913
973
|
|
|
914
|
-
return { srcDocumentId:
|
|
974
|
+
return { srcDocumentId: updatedDocumentResult.id };
|
|
915
975
|
}
|
|
916
976
|
|
|
917
977
|
async duplicateDocument({
|
|
@@ -976,7 +1036,7 @@ export class ContentStore {
|
|
|
976
1036
|
|
|
977
1037
|
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
978
1038
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
979
|
-
const sourceAssets:
|
|
1039
|
+
const sourceAssets: CSITypes.Asset[] = [];
|
|
980
1040
|
const userContext = getUserContextForSrcType(srcType, user);
|
|
981
1041
|
|
|
982
1042
|
locale = locale ?? contentSourceData.defaultLocaleCode;
|
|
@@ -999,8 +1059,8 @@ export class ContentStore {
|
|
|
999
1059
|
});
|
|
1000
1060
|
sourceAssets.push(sourceAsset);
|
|
1001
1061
|
}
|
|
1002
|
-
const storeAssets =
|
|
1003
|
-
|
|
1062
|
+
const storeAssets = mapCSIAssetsToStoreAssets({
|
|
1063
|
+
csiAssets: sourceAssets,
|
|
1004
1064
|
contentSourceInstance: contentSourceData.instance,
|
|
1005
1065
|
defaultLocaleCode: contentSourceData.defaultLocaleCode
|
|
1006
1066
|
});
|
|
@@ -1023,7 +1083,11 @@ export class ContentStore {
|
|
|
1023
1083
|
const userContext = getUserContextForSrcType(srcType, user);
|
|
1024
1084
|
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
1025
1085
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
1026
|
-
|
|
1086
|
+
const csiDocument = contentSourceData.csiDocumentMap[srcDocumentId];
|
|
1087
|
+
if (!csiDocument) {
|
|
1088
|
+
throw new Error(`no document with id '${srcDocumentId}' was found in ${contentSourceData.id}`);
|
|
1089
|
+
}
|
|
1090
|
+
await contentSourceData.instance.deleteDocument({ document: csiDocument, userContext });
|
|
1027
1091
|
|
|
1028
1092
|
// do not update cache in contentSourceData.documents and documentMap,
|
|
1029
1093
|
// instead wait for contentSource to call onContentChange(contentChangeEvent)
|
|
@@ -1044,20 +1108,12 @@ export class ContentStore {
|
|
|
1044
1108
|
|
|
1045
1109
|
const objectsBySourceId = _.groupBy(objects, (object) => getContentSourceId(object.srcType, object.srcProjectId));
|
|
1046
1110
|
let errors: ContentStoreTypes.ValidationError[] = [];
|
|
1047
|
-
for (const [contentSourceId,
|
|
1111
|
+
for (const [contentSourceId, contentSourceObjects] of Object.entries(objectsBySourceId)) {
|
|
1048
1112
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
1049
1113
|
locale = locale ?? contentSourceData.defaultLocaleCode;
|
|
1050
|
-
const
|
|
1051
|
-
const assetIds = [];
|
|
1052
|
-
for (const object of objects) {
|
|
1053
|
-
if (object.srcObjectId in contentSourceData.documentMap) {
|
|
1054
|
-
documentIds.push(object.srcObjectId);
|
|
1055
|
-
} else if (object.srcObjectId in contentSourceData.assetMap) {
|
|
1056
|
-
assetIds.push(object.srcObjectId);
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1114
|
+
const { documents, assets } = getCSIDocumentsAndAssetsFromContentSourceDataByIds(contentSourceData, contentSourceObjects);
|
|
1059
1115
|
const userContext = getUserContextForSrcType(contentSourceData.type, user);
|
|
1060
|
-
const validationResult = await contentSourceData.instance.validateDocuments({
|
|
1116
|
+
const validationResult = await contentSourceData.instance.validateDocuments({ documents, assets, locale, userContext });
|
|
1061
1117
|
errors = errors.concat(
|
|
1062
1118
|
validationResult.errors.map((validationError) => ({
|
|
1063
1119
|
message: validationError.message,
|
|
@@ -1093,19 +1149,11 @@ export class ContentStore {
|
|
|
1093
1149
|
this.logger.debug('publishDocuments');
|
|
1094
1150
|
|
|
1095
1151
|
const objectsBySourceId = _.groupBy(objects, (object) => getContentSourceId(object.srcType, object.srcProjectId));
|
|
1096
|
-
for (const [contentSourceId,
|
|
1152
|
+
for (const [contentSourceId, contentSourceObjects] of Object.entries(objectsBySourceId)) {
|
|
1097
1153
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
1098
1154
|
const userContext = getUserContextForSrcType(contentSourceData.type, user);
|
|
1099
|
-
const
|
|
1100
|
-
|
|
1101
|
-
for (const object of objects) {
|
|
1102
|
-
if (object.srcObjectId in contentSourceData.documentMap) {
|
|
1103
|
-
documentIds.push(object.srcObjectId);
|
|
1104
|
-
} else if (object.srcObjectId in contentSourceData.assetMap) {
|
|
1105
|
-
assetIds.push(object.srcObjectId);
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
await contentSourceData.instance.publishDocuments({ documentIds, assetIds, userContext });
|
|
1155
|
+
const { documents, assets } = getCSIDocumentsAndAssetsFromContentSourceDataByIds(contentSourceData, contentSourceObjects);
|
|
1156
|
+
await contentSourceData.instance.publishDocuments({ documents, assets, userContext });
|
|
1109
1157
|
}
|
|
1110
1158
|
}
|
|
1111
1159
|
|
|
@@ -1126,13 +1174,13 @@ function getUserContextForSrcType(srcType: string, user?: ContentStoreTypes.User
|
|
|
1126
1174
|
return user?.connections?.find((connection) => connection.type === srcType);
|
|
1127
1175
|
}
|
|
1128
1176
|
|
|
1129
|
-
function
|
|
1130
|
-
|
|
1177
|
+
function mapCSIAssetsToStoreAssets({
|
|
1178
|
+
csiAssets,
|
|
1131
1179
|
contentSourceInstance,
|
|
1132
1180
|
defaultLocaleCode
|
|
1133
1181
|
}: {
|
|
1134
|
-
|
|
1135
|
-
contentSourceInstance:
|
|
1182
|
+
csiAssets: CSITypes.Asset[];
|
|
1183
|
+
contentSourceInstance: CSITypes.ContentSourceInterface;
|
|
1136
1184
|
defaultLocaleCode?: string;
|
|
1137
1185
|
}): ContentStoreTypes.Asset[] {
|
|
1138
1186
|
const extra = {
|
|
@@ -1141,53 +1189,53 @@ function mapSourceAssetsToStoreAssets({
|
|
|
1141
1189
|
srcProjectUrl: contentSourceInstance.getProjectManageUrl(),
|
|
1142
1190
|
srcEnvironment: contentSourceInstance.getProjectEnvironment()
|
|
1143
1191
|
};
|
|
1144
|
-
return
|
|
1192
|
+
return csiAssets.map((csiAsset) => sourceAssetToStoreAsset({ csiAsset, defaultLocaleCode, extra }));
|
|
1145
1193
|
}
|
|
1146
1194
|
|
|
1147
1195
|
function sourceAssetToStoreAsset({
|
|
1148
|
-
|
|
1196
|
+
csiAsset,
|
|
1149
1197
|
defaultLocaleCode,
|
|
1150
1198
|
extra
|
|
1151
1199
|
}: {
|
|
1152
|
-
|
|
1200
|
+
csiAsset: CSITypes.Asset;
|
|
1153
1201
|
defaultLocaleCode?: string;
|
|
1154
1202
|
extra: { srcType: string; srcProjectId: string; srcProjectUrl: string; srcEnvironment: string };
|
|
1155
1203
|
}): ContentStoreTypes.Asset {
|
|
1156
1204
|
return {
|
|
1157
1205
|
type: 'asset',
|
|
1158
1206
|
...extra,
|
|
1159
|
-
srcObjectId:
|
|
1160
|
-
srcObjectUrl:
|
|
1161
|
-
srcObjectLabel: getObjectLabel(
|
|
1207
|
+
srcObjectId: csiAsset.id,
|
|
1208
|
+
srcObjectUrl: csiAsset.manageUrl,
|
|
1209
|
+
srcObjectLabel: getObjectLabel(csiAsset.fields, IMAGE_MODEL, defaultLocaleCode),
|
|
1162
1210
|
srcModelName: IMAGE_MODEL.name,
|
|
1163
1211
|
srcModelLabel: IMAGE_MODEL.label!,
|
|
1164
|
-
isChanged:
|
|
1165
|
-
status:
|
|
1166
|
-
createdAt:
|
|
1167
|
-
createdBy:
|
|
1168
|
-
updatedAt:
|
|
1169
|
-
updatedBy:
|
|
1212
|
+
isChanged: csiAsset.status === 'added' || csiAsset.status === 'modified',
|
|
1213
|
+
status: csiAsset.status,
|
|
1214
|
+
createdAt: csiAsset.createdAt,
|
|
1215
|
+
createdBy: csiAsset.createdBy,
|
|
1216
|
+
updatedAt: csiAsset.updatedAt,
|
|
1217
|
+
updatedBy: csiAsset.updatedBy,
|
|
1170
1218
|
fields: {
|
|
1171
1219
|
title: {
|
|
1172
1220
|
label: 'Title',
|
|
1173
|
-
...
|
|
1221
|
+
...csiAsset.fields.title
|
|
1174
1222
|
},
|
|
1175
1223
|
file: {
|
|
1176
1224
|
label: 'File',
|
|
1177
|
-
...
|
|
1225
|
+
...csiAsset.fields.file
|
|
1178
1226
|
}
|
|
1179
1227
|
}
|
|
1180
1228
|
};
|
|
1181
1229
|
}
|
|
1182
1230
|
|
|
1183
|
-
function
|
|
1184
|
-
|
|
1231
|
+
function mapCSIDocumentsToStoreDocuments({
|
|
1232
|
+
csiDocuments,
|
|
1185
1233
|
contentSourceInstance,
|
|
1186
1234
|
modelMap,
|
|
1187
1235
|
defaultLocaleCode
|
|
1188
1236
|
}: {
|
|
1189
|
-
|
|
1190
|
-
contentSourceInstance:
|
|
1237
|
+
csiDocuments: CSITypes.Document[];
|
|
1238
|
+
contentSourceInstance: CSITypes.ContentSourceInterface;
|
|
1191
1239
|
modelMap: Record<string, Model>;
|
|
1192
1240
|
defaultLocaleCode?: string;
|
|
1193
1241
|
}): ContentStoreTypes.Document[] {
|
|
@@ -1197,19 +1245,19 @@ function mapSourceDocumentsToStoreDocuments({
|
|
|
1197
1245
|
srcProjectUrl: contentSourceInstance.getProjectManageUrl(),
|
|
1198
1246
|
srcEnvironment: contentSourceInstance.getProjectEnvironment()
|
|
1199
1247
|
};
|
|
1200
|
-
return
|
|
1201
|
-
|
|
1248
|
+
return csiDocuments.map((csiDocument) =>
|
|
1249
|
+
mapCSIDocumentToStoreDocument({ csiDocument, model: modelMap[csiDocument.modelName]!, modelMap, defaultLocaleCode, extra })
|
|
1202
1250
|
);
|
|
1203
1251
|
}
|
|
1204
1252
|
|
|
1205
|
-
function
|
|
1206
|
-
|
|
1253
|
+
function mapCSIDocumentToStoreDocument({
|
|
1254
|
+
csiDocument,
|
|
1207
1255
|
model,
|
|
1208
1256
|
modelMap,
|
|
1209
1257
|
defaultLocaleCode,
|
|
1210
1258
|
extra
|
|
1211
1259
|
}: {
|
|
1212
|
-
|
|
1260
|
+
csiDocument: CSITypes.Document;
|
|
1213
1261
|
model: Model;
|
|
1214
1262
|
modelMap: Record<string, Model>;
|
|
1215
1263
|
defaultLocaleCode?: string;
|
|
@@ -1218,44 +1266,48 @@ function mapSourceDocumentToStoreDocument({
|
|
|
1218
1266
|
return {
|
|
1219
1267
|
type: 'document',
|
|
1220
1268
|
...extra,
|
|
1221
|
-
srcObjectId:
|
|
1222
|
-
srcObjectUrl:
|
|
1223
|
-
srcObjectLabel: getObjectLabel(
|
|
1224
|
-
srcModelLabel: model.label ?? _.startCase(
|
|
1225
|
-
srcModelName:
|
|
1226
|
-
isChanged:
|
|
1227
|
-
status:
|
|
1228
|
-
createdAt:
|
|
1229
|
-
createdBy:
|
|
1230
|
-
updatedAt:
|
|
1231
|
-
updatedBy:
|
|
1232
|
-
fields:
|
|
1233
|
-
|
|
1269
|
+
srcObjectId: csiDocument.id,
|
|
1270
|
+
srcObjectUrl: csiDocument.manageUrl,
|
|
1271
|
+
srcObjectLabel: getObjectLabel(csiDocument.fields, model, defaultLocaleCode),
|
|
1272
|
+
srcModelLabel: model.label ?? _.startCase(csiDocument.modelName),
|
|
1273
|
+
srcModelName: csiDocument.modelName,
|
|
1274
|
+
isChanged: csiDocument.status === 'added' || csiDocument.status === 'modified',
|
|
1275
|
+
status: csiDocument.status,
|
|
1276
|
+
createdAt: csiDocument.createdAt,
|
|
1277
|
+
createdBy: csiDocument.createdBy,
|
|
1278
|
+
updatedAt: csiDocument.updatedAt,
|
|
1279
|
+
updatedBy: csiDocument.updatedBy,
|
|
1280
|
+
fields: mapCSIFieldsToStoreFields({
|
|
1281
|
+
csiDocumentFields: csiDocument.fields,
|
|
1234
1282
|
modelFields: model.fields ?? [],
|
|
1235
|
-
|
|
1236
|
-
|
|
1283
|
+
context: {
|
|
1284
|
+
modelMap,
|
|
1285
|
+
defaultLocaleCode
|
|
1286
|
+
}
|
|
1237
1287
|
})
|
|
1238
1288
|
};
|
|
1239
1289
|
}
|
|
1240
1290
|
|
|
1241
|
-
|
|
1242
|
-
|
|
1291
|
+
type MapContext = {
|
|
1292
|
+
modelMap: Record<string, Model>;
|
|
1293
|
+
defaultLocaleCode?: string;
|
|
1294
|
+
};
|
|
1295
|
+
|
|
1296
|
+
function mapCSIFieldsToStoreFields({
|
|
1297
|
+
csiDocumentFields,
|
|
1243
1298
|
modelFields,
|
|
1244
|
-
|
|
1245
|
-
defaultLocaleCode
|
|
1299
|
+
context
|
|
1246
1300
|
}: {
|
|
1247
|
-
|
|
1301
|
+
csiDocumentFields: Record<string, CSITypes.DocumentField>;
|
|
1248
1302
|
modelFields: Field[];
|
|
1249
|
-
|
|
1250
|
-
defaultLocaleCode?: string;
|
|
1303
|
+
context: MapContext;
|
|
1251
1304
|
}): Record<string, ContentStoreTypes.DocumentField> {
|
|
1252
1305
|
return modelFields.reduce((result: Record<string, ContentStoreTypes.DocumentField>, modelField) => {
|
|
1253
|
-
const
|
|
1254
|
-
const docField =
|
|
1255
|
-
|
|
1306
|
+
const csiDocumentField = csiDocumentFields[modelField.name];
|
|
1307
|
+
const docField = mapCSIFieldToStoreField({
|
|
1308
|
+
csiDocumentField,
|
|
1256
1309
|
modelField,
|
|
1257
|
-
|
|
1258
|
-
defaultLocaleCode
|
|
1310
|
+
context
|
|
1259
1311
|
});
|
|
1260
1312
|
docField.label = modelField.label;
|
|
1261
1313
|
result[modelField.name] = docField;
|
|
@@ -1263,18 +1315,16 @@ function mapSourceFieldsToStoreFields({
|
|
|
1263
1315
|
}, {});
|
|
1264
1316
|
}
|
|
1265
1317
|
|
|
1266
|
-
function
|
|
1267
|
-
|
|
1318
|
+
function mapCSIFieldToStoreField({
|
|
1319
|
+
csiDocumentField,
|
|
1268
1320
|
modelField,
|
|
1269
|
-
|
|
1270
|
-
defaultLocaleCode
|
|
1321
|
+
context
|
|
1271
1322
|
}: {
|
|
1272
|
-
|
|
1323
|
+
csiDocumentField: CSITypes.DocumentField | undefined;
|
|
1273
1324
|
modelField: FieldSpecificProps;
|
|
1274
|
-
|
|
1275
|
-
defaultLocaleCode?: string;
|
|
1325
|
+
context: MapContext;
|
|
1276
1326
|
}): ContentStoreTypes.DocumentField {
|
|
1277
|
-
if (!
|
|
1327
|
+
if (!csiDocumentField) {
|
|
1278
1328
|
const isUnset = ['object', 'model', 'reference', 'richText', 'markdown', 'image', 'file', 'json'].includes(modelField.type);
|
|
1279
1329
|
return {
|
|
1280
1330
|
type: modelField.type,
|
|
@@ -1285,129 +1335,112 @@ function mapSourceFieldToStoreField({
|
|
|
1285
1335
|
// TODO: check if need to add "options" to "enum" and subtype/min/max to "number"
|
|
1286
1336
|
switch (modelField.type) {
|
|
1287
1337
|
case 'object':
|
|
1288
|
-
return mapObjectField(
|
|
1338
|
+
return mapObjectField(csiDocumentField as CSITypes.DocumentObjectField, modelField, context);
|
|
1289
1339
|
case 'model':
|
|
1290
|
-
return mapModelField(
|
|
1340
|
+
return mapModelField(csiDocumentField as CSITypes.DocumentModelField, modelField, context);
|
|
1291
1341
|
case 'list':
|
|
1292
|
-
return mapListField(
|
|
1342
|
+
return mapListField(csiDocumentField as CSITypes.DocumentListField, modelField, context);
|
|
1293
1343
|
case 'richText':
|
|
1294
|
-
return mapRichTextField(
|
|
1344
|
+
return mapRichTextField(csiDocumentField as CSITypes.DocumentRichTextField);
|
|
1295
1345
|
case 'markdown':
|
|
1296
|
-
return mapMarkdownField(
|
|
1346
|
+
return mapMarkdownField(csiDocumentField as CSITypes.DocumentValueField);
|
|
1297
1347
|
default:
|
|
1298
|
-
return
|
|
1348
|
+
return csiDocumentField as ContentStoreTypes.DocumentField;
|
|
1299
1349
|
}
|
|
1300
1350
|
}
|
|
1301
1351
|
|
|
1302
1352
|
function mapObjectField(
|
|
1303
|
-
|
|
1353
|
+
csiDocumentField: CSITypes.DocumentObjectField,
|
|
1304
1354
|
modelField: FieldObjectProps,
|
|
1305
|
-
|
|
1306
|
-
defaultLocaleCode?: string
|
|
1355
|
+
context: MapContext
|
|
1307
1356
|
): ContentStoreTypes.DocumentObjectField {
|
|
1308
|
-
if (!isLocalizedField(
|
|
1357
|
+
if (!isLocalizedField(csiDocumentField)) {
|
|
1309
1358
|
return {
|
|
1310
|
-
type:
|
|
1311
|
-
srcObjectLabel: getObjectLabel(
|
|
1312
|
-
fields:
|
|
1313
|
-
|
|
1359
|
+
type: csiDocumentField.type,
|
|
1360
|
+
srcObjectLabel: getObjectLabel(csiDocumentField.fields ?? {}, modelField ?? [], context.defaultLocaleCode),
|
|
1361
|
+
fields: mapCSIFieldsToStoreFields({
|
|
1362
|
+
csiDocumentFields: csiDocumentField.fields ?? {},
|
|
1314
1363
|
modelFields: modelField.fields ?? [],
|
|
1315
|
-
|
|
1316
|
-
defaultLocaleCode
|
|
1364
|
+
context
|
|
1317
1365
|
})
|
|
1318
1366
|
};
|
|
1319
1367
|
}
|
|
1320
1368
|
return {
|
|
1321
|
-
type:
|
|
1369
|
+
type: csiDocumentField.type,
|
|
1322
1370
|
localized: true,
|
|
1323
|
-
locales: _.mapValues(
|
|
1371
|
+
locales: _.mapValues(csiDocumentField.locales, (locale) => {
|
|
1324
1372
|
return {
|
|
1325
1373
|
locale: locale.locale,
|
|
1326
1374
|
srcObjectLabel: getObjectLabel(locale.fields ?? {}, modelField, locale.locale),
|
|
1327
|
-
fields:
|
|
1328
|
-
|
|
1375
|
+
fields: mapCSIFieldsToStoreFields({
|
|
1376
|
+
csiDocumentFields: locale.fields ?? {},
|
|
1329
1377
|
modelFields: modelField.fields ?? [],
|
|
1330
|
-
|
|
1331
|
-
defaultLocaleCode
|
|
1378
|
+
context
|
|
1332
1379
|
})
|
|
1333
1380
|
};
|
|
1334
1381
|
})
|
|
1335
1382
|
};
|
|
1336
1383
|
}
|
|
1337
1384
|
|
|
1338
|
-
function mapModelField(
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
modelMap: Record<string, Model>,
|
|
1342
|
-
defaultLocaleCode?: string
|
|
1343
|
-
): ContentStoreTypes.DocumentModelField {
|
|
1344
|
-
if (!isLocalizedField(documentField)) {
|
|
1345
|
-
const model = modelMap[documentField.modelName]!;
|
|
1385
|
+
function mapModelField(csiDocumentField: CSITypes.DocumentModelField, modelField: FieldModelProps, context: MapContext): ContentStoreTypes.DocumentModelField {
|
|
1386
|
+
if (!isLocalizedField(csiDocumentField)) {
|
|
1387
|
+
const model = context.modelMap[csiDocumentField.modelName]!;
|
|
1346
1388
|
return {
|
|
1347
|
-
type:
|
|
1348
|
-
srcObjectLabel: getObjectLabel(
|
|
1349
|
-
srcModelName:
|
|
1389
|
+
type: csiDocumentField.type,
|
|
1390
|
+
srcObjectLabel: getObjectLabel(csiDocumentField.fields ?? {}, model, context.defaultLocaleCode),
|
|
1391
|
+
srcModelName: csiDocumentField.modelName,
|
|
1350
1392
|
srcModelLabel: model.label ?? _.startCase(model.name),
|
|
1351
|
-
fields:
|
|
1352
|
-
|
|
1393
|
+
fields: mapCSIFieldsToStoreFields({
|
|
1394
|
+
csiDocumentFields: csiDocumentField.fields ?? {},
|
|
1353
1395
|
modelFields: model.fields ?? [],
|
|
1354
|
-
|
|
1355
|
-
defaultLocaleCode
|
|
1396
|
+
context
|
|
1356
1397
|
})
|
|
1357
1398
|
};
|
|
1358
1399
|
}
|
|
1359
1400
|
return {
|
|
1360
|
-
type:
|
|
1401
|
+
type: csiDocumentField.type,
|
|
1361
1402
|
localized: true,
|
|
1362
|
-
locales: _.mapValues(
|
|
1363
|
-
const model = modelMap[locale.modelName]!;
|
|
1403
|
+
locales: _.mapValues(csiDocumentField.locales, (locale) => {
|
|
1404
|
+
const model = context.modelMap[locale.modelName]!;
|
|
1364
1405
|
return {
|
|
1365
1406
|
locale: locale.locale,
|
|
1366
1407
|
srcObjectLabel: getObjectLabel(locale.fields ?? {}, model, locale.locale),
|
|
1367
1408
|
srcModelName: locale.modelName,
|
|
1368
1409
|
srcModelLabel: model.label ?? _.startCase(model.name),
|
|
1369
|
-
fields:
|
|
1370
|
-
|
|
1410
|
+
fields: mapCSIFieldsToStoreFields({
|
|
1411
|
+
csiDocumentFields: locale.fields ?? {},
|
|
1371
1412
|
modelFields: model.fields ?? [],
|
|
1372
|
-
|
|
1373
|
-
defaultLocaleCode
|
|
1413
|
+
context
|
|
1374
1414
|
})
|
|
1375
1415
|
};
|
|
1376
1416
|
})
|
|
1377
1417
|
};
|
|
1378
1418
|
}
|
|
1379
1419
|
|
|
1380
|
-
function mapListField(
|
|
1381
|
-
|
|
1382
|
-
modelField: FieldListProps,
|
|
1383
|
-
modelMap: Record<string, Model>,
|
|
1384
|
-
defaultLocaleCode?: string
|
|
1385
|
-
): ContentStoreTypes.DocumentListField {
|
|
1386
|
-
if (!isLocalizedField(documentField)) {
|
|
1420
|
+
function mapListField(csiDocumentField: CSITypes.DocumentListField, modelField: FieldListProps, context: MapContext): ContentStoreTypes.DocumentListField {
|
|
1421
|
+
if (!isLocalizedField(csiDocumentField)) {
|
|
1387
1422
|
return {
|
|
1388
|
-
type:
|
|
1389
|
-
items:
|
|
1390
|
-
|
|
1391
|
-
|
|
1423
|
+
type: csiDocumentField.type,
|
|
1424
|
+
items: csiDocumentField.items.map((item) =>
|
|
1425
|
+
mapCSIFieldToStoreField({
|
|
1426
|
+
csiDocumentField: item,
|
|
1392
1427
|
modelField: modelField.items ?? { type: 'string' },
|
|
1393
|
-
|
|
1394
|
-
defaultLocaleCode
|
|
1428
|
+
context
|
|
1395
1429
|
})
|
|
1396
1430
|
)
|
|
1397
1431
|
};
|
|
1398
1432
|
}
|
|
1399
1433
|
return {
|
|
1400
|
-
type:
|
|
1434
|
+
type: csiDocumentField.type,
|
|
1401
1435
|
localized: true,
|
|
1402
|
-
locales: _.mapValues(
|
|
1436
|
+
locales: _.mapValues(csiDocumentField.locales, (locale) => {
|
|
1403
1437
|
return {
|
|
1404
1438
|
locale: locale.locale,
|
|
1405
1439
|
items: (locale.items ?? []).map((item) =>
|
|
1406
|
-
|
|
1407
|
-
|
|
1440
|
+
mapCSIFieldToStoreField({
|
|
1441
|
+
csiDocumentField: item,
|
|
1408
1442
|
modelField: modelField.items ?? { type: 'string' },
|
|
1409
|
-
|
|
1410
|
-
defaultLocaleCode
|
|
1443
|
+
context
|
|
1411
1444
|
})
|
|
1412
1445
|
)
|
|
1413
1446
|
};
|
|
@@ -1415,17 +1448,17 @@ function mapListField(
|
|
|
1415
1448
|
};
|
|
1416
1449
|
}
|
|
1417
1450
|
|
|
1418
|
-
function mapRichTextField(
|
|
1419
|
-
if (!isLocalizedField(
|
|
1451
|
+
function mapRichTextField(csiDocumentField: CSITypes.DocumentRichTextField): ContentStoreTypes.DocumentRichTextField {
|
|
1452
|
+
if (!isLocalizedField(csiDocumentField)) {
|
|
1420
1453
|
return {
|
|
1421
|
-
...
|
|
1454
|
+
...csiDocumentField,
|
|
1422
1455
|
multiElement: true
|
|
1423
1456
|
};
|
|
1424
1457
|
}
|
|
1425
1458
|
return {
|
|
1426
|
-
type:
|
|
1459
|
+
type: csiDocumentField.type,
|
|
1427
1460
|
localized: true,
|
|
1428
|
-
locales: _.mapValues(
|
|
1461
|
+
locales: _.mapValues(csiDocumentField.locales, (locale) => {
|
|
1429
1462
|
return {
|
|
1430
1463
|
...locale,
|
|
1431
1464
|
multiElement: true
|
|
@@ -1434,18 +1467,18 @@ function mapRichTextField(documentField: ContentSourceTypes.DocumentRichTextFiel
|
|
|
1434
1467
|
};
|
|
1435
1468
|
}
|
|
1436
1469
|
|
|
1437
|
-
function mapMarkdownField(
|
|
1438
|
-
if (!isLocalizedField(
|
|
1470
|
+
function mapMarkdownField(csiDocumentField: CSITypes.DocumentValueField): ContentStoreTypes.DocumentMarkdownField {
|
|
1471
|
+
if (!isLocalizedField(csiDocumentField)) {
|
|
1439
1472
|
return {
|
|
1440
1473
|
type: 'markdown',
|
|
1441
|
-
value:
|
|
1474
|
+
value: csiDocumentField.value,
|
|
1442
1475
|
multiElement: true
|
|
1443
1476
|
};
|
|
1444
1477
|
}
|
|
1445
1478
|
return {
|
|
1446
1479
|
type: 'markdown',
|
|
1447
1480
|
localized: true,
|
|
1448
|
-
locales: _.mapValues(
|
|
1481
|
+
locales: _.mapValues(csiDocumentField.locales, (locale) => {
|
|
1449
1482
|
return {
|
|
1450
1483
|
...locale,
|
|
1451
1484
|
multiElement: true
|
|
@@ -1462,12 +1495,12 @@ function mapStoreFieldsToSourceFields({
|
|
|
1462
1495
|
documentFields: Record<string, ContentStoreTypes.DocumentField>;
|
|
1463
1496
|
modelFields: Field[];
|
|
1464
1497
|
modelMap: Record<string, Model>;
|
|
1465
|
-
}): Record<string,
|
|
1466
|
-
// TODO:
|
|
1498
|
+
}): Record<string, CSITypes.DocumentField> {
|
|
1499
|
+
// TODO: implement
|
|
1467
1500
|
throw new Error(`duplicateDocument not implemented yet`);
|
|
1468
1501
|
}
|
|
1469
1502
|
|
|
1470
|
-
function getContentSourceIdForContentSource(contentSource:
|
|
1503
|
+
function getContentSourceIdForContentSource(contentSource: CSITypes.ContentSourceInterface): string {
|
|
1471
1504
|
return getContentSourceId(contentSource.getContentSourceType(), contentSource.getProjectId());
|
|
1472
1505
|
}
|
|
1473
1506
|
|
|
@@ -1483,7 +1516,7 @@ function sanitizeSlug(slug: string) {
|
|
|
1483
1516
|
}
|
|
1484
1517
|
|
|
1485
1518
|
function getObjectLabel(
|
|
1486
|
-
documentFields: Record<string,
|
|
1519
|
+
documentFields: Record<string, CSITypes.DocumentField | CSITypes.AssetFileField>,
|
|
1487
1520
|
modelOrObjectField: Model | FieldObjectProps,
|
|
1488
1521
|
locale?: string
|
|
1489
1522
|
): string {
|
|
@@ -1552,6 +1585,7 @@ function toLocalizedAPIField(docField: ContentStoreTypes.DocumentField, locale?:
|
|
|
1552
1585
|
if (docFieldLocalized.type === 'object' || docFieldLocalized.type === 'model') {
|
|
1553
1586
|
return {
|
|
1554
1587
|
...docFieldLocalized,
|
|
1588
|
+
type: 'object',
|
|
1555
1589
|
...commonProps,
|
|
1556
1590
|
...(docFieldLocalized.isUnset
|
|
1557
1591
|
? null
|
|
@@ -1671,8 +1705,8 @@ async function createDocumentRecursively({
|
|
|
1671
1705
|
modelMap: Record<string, Model>;
|
|
1672
1706
|
locale?: string;
|
|
1673
1707
|
userContext: unknown;
|
|
1674
|
-
contentSourceInstance:
|
|
1675
|
-
}): Promise<{ document:
|
|
1708
|
+
contentSourceInstance: CSITypes.ContentSourceInterface;
|
|
1709
|
+
}): Promise<{ document: CSITypes.Document; newRefDocuments: CSITypes.Document[] }> {
|
|
1676
1710
|
if (model.type === 'page') {
|
|
1677
1711
|
const tokens = extractTokensFromString(String(model.urlPath));
|
|
1678
1712
|
const slugField = _.last(tokens);
|
|
@@ -1692,7 +1726,7 @@ async function createDocumentRecursively({
|
|
|
1692
1726
|
contentSourceInstance
|
|
1693
1727
|
});
|
|
1694
1728
|
const document = await contentSourceInstance.createDocument({
|
|
1695
|
-
documentFields: nestedResult.fields,
|
|
1729
|
+
documentFields: nestedResult.fields as Record<string, CSITypes.DocumentField>,
|
|
1696
1730
|
model,
|
|
1697
1731
|
modelMap,
|
|
1698
1732
|
locale,
|
|
@@ -1719,200 +1753,216 @@ async function createNestedObjectRecursively({
|
|
|
1719
1753
|
modelMap: Record<string, Model>;
|
|
1720
1754
|
locale?: string;
|
|
1721
1755
|
userContext: unknown;
|
|
1722
|
-
contentSourceInstance:
|
|
1756
|
+
contentSourceInstance: CSITypes.ContentSourceInterface;
|
|
1723
1757
|
}): Promise<{
|
|
1724
|
-
fields: Record<string,
|
|
1725
|
-
newRefDocuments:
|
|
1758
|
+
fields: Record<string, CSITypes.UpdateOperationField>;
|
|
1759
|
+
newRefDocuments: CSITypes.Document[];
|
|
1726
1760
|
}> {
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
}
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1761
|
+
object = object ?? {};
|
|
1762
|
+
const result: {
|
|
1763
|
+
fields: Record<string, CSITypes.UpdateOperationField>;
|
|
1764
|
+
newRefDocuments: CSITypes.Document[];
|
|
1765
|
+
} = {
|
|
1766
|
+
fields: {},
|
|
1767
|
+
newRefDocuments: []
|
|
1768
|
+
};
|
|
1769
|
+
const objectFieldNames = Object.keys(object);
|
|
1770
|
+
for (const modelField of modelFields) {
|
|
1771
|
+
const fieldName = modelField.name;
|
|
1772
|
+
let value;
|
|
1773
|
+
if (fieldName in object) {
|
|
1774
|
+
value = object[fieldName];
|
|
1775
|
+
_.pull(objectFieldNames, fieldName);
|
|
1776
|
+
} else if (modelField.const) {
|
|
1777
|
+
value = modelField.const;
|
|
1778
|
+
} else if (!_.isNil(modelField.default)) {
|
|
1779
|
+
value = modelField.default;
|
|
1780
|
+
}
|
|
1781
|
+
if (!_.isNil(value)) {
|
|
1782
|
+
const fieldResult = await createNestedField({
|
|
1783
|
+
value,
|
|
1784
|
+
modelField,
|
|
1785
|
+
fieldPath: fieldPath.concat(fieldName),
|
|
1741
1786
|
modelMap,
|
|
1742
1787
|
locale,
|
|
1743
1788
|
userContext,
|
|
1744
1789
|
contentSourceInstance
|
|
1745
1790
|
});
|
|
1791
|
+
result.fields[fieldName] = fieldResult.field;
|
|
1792
|
+
result.newRefDocuments = result.newRefDocuments.concat(fieldResult.newRefDocuments);
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
if (objectFieldNames.length > 0) {
|
|
1796
|
+
throw new Error(`no model fields found when creating a document with fields: '${objectFieldNames.join(', ')}'`);
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
return result;
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
async function createNestedField({
|
|
1803
|
+
value,
|
|
1804
|
+
modelField,
|
|
1805
|
+
fieldPath,
|
|
1806
|
+
modelMap,
|
|
1807
|
+
locale,
|
|
1808
|
+
userContext,
|
|
1809
|
+
contentSourceInstance
|
|
1810
|
+
}: {
|
|
1811
|
+
value: any;
|
|
1812
|
+
modelField: FieldSpecificProps;
|
|
1813
|
+
fieldPath: (string | number)[];
|
|
1814
|
+
modelMap: Record<string, Model>;
|
|
1815
|
+
locale?: string;
|
|
1816
|
+
userContext: unknown;
|
|
1817
|
+
contentSourceInstance: CSITypes.ContentSourceInterface;
|
|
1818
|
+
}): Promise<{ field: CSITypes.UpdateOperationField; newRefDocuments: CSITypes.Document[] }> {
|
|
1819
|
+
if (modelField.type === 'object') {
|
|
1820
|
+
const result = await createNestedObjectRecursively({
|
|
1821
|
+
object: value,
|
|
1822
|
+
modelFields: modelField.fields,
|
|
1823
|
+
fieldPath,
|
|
1824
|
+
modelMap,
|
|
1825
|
+
locale,
|
|
1826
|
+
userContext,
|
|
1827
|
+
contentSourceInstance
|
|
1828
|
+
});
|
|
1829
|
+
return {
|
|
1830
|
+
field: {
|
|
1831
|
+
type: 'object',
|
|
1832
|
+
fields: result.fields
|
|
1833
|
+
},
|
|
1834
|
+
newRefDocuments: result.newRefDocuments
|
|
1835
|
+
};
|
|
1836
|
+
} else if (modelField.type === 'model') {
|
|
1837
|
+
let { $$type, ...rest } = value;
|
|
1838
|
+
const modelNames = modelField.models;
|
|
1839
|
+
// for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
|
|
1840
|
+
// the 'type' property in default values
|
|
1841
|
+
if (!$$type && 'type' in rest) {
|
|
1842
|
+
$$type = rest.type;
|
|
1843
|
+
rest = _.omit(rest, 'type');
|
|
1844
|
+
}
|
|
1845
|
+
const modelName = $$type ?? (modelNames.length === 1 ? modelNames[0] : null);
|
|
1846
|
+
if (!modelName) {
|
|
1847
|
+
throw new Error(`no $$type was specified for nested model`);
|
|
1848
|
+
}
|
|
1849
|
+
const model = modelMap[modelName];
|
|
1850
|
+
if (!model) {
|
|
1851
|
+
throw new Error(`no model with name '${modelName}' was found`);
|
|
1852
|
+
}
|
|
1853
|
+
const result = await createNestedObjectRecursively({
|
|
1854
|
+
object: rest,
|
|
1855
|
+
modelFields: model.fields ?? [],
|
|
1856
|
+
fieldPath,
|
|
1857
|
+
modelMap,
|
|
1858
|
+
locale,
|
|
1859
|
+
userContext,
|
|
1860
|
+
contentSourceInstance
|
|
1861
|
+
});
|
|
1862
|
+
return {
|
|
1863
|
+
field: {
|
|
1864
|
+
type: 'model',
|
|
1865
|
+
modelName: modelName,
|
|
1866
|
+
fields: result.fields
|
|
1867
|
+
},
|
|
1868
|
+
newRefDocuments: result.newRefDocuments
|
|
1869
|
+
};
|
|
1870
|
+
} else if (modelField.type === 'image') {
|
|
1871
|
+
let refId: string | undefined;
|
|
1872
|
+
if (_.isPlainObject(value)) {
|
|
1873
|
+
refId = value.$$ref;
|
|
1874
|
+
} else {
|
|
1875
|
+
refId = value;
|
|
1876
|
+
}
|
|
1877
|
+
if (!refId) {
|
|
1878
|
+
throw new Error(`reference field must specify a value`);
|
|
1879
|
+
}
|
|
1880
|
+
return {
|
|
1881
|
+
field: {
|
|
1882
|
+
type: 'reference',
|
|
1883
|
+
refType: 'asset',
|
|
1884
|
+
refId: refId
|
|
1885
|
+
},
|
|
1886
|
+
newRefDocuments: []
|
|
1887
|
+
};
|
|
1888
|
+
} else if (modelField.type === 'reference') {
|
|
1889
|
+
let { $$ref: refId = null, $$type: modelName = null, ...rest } = _.isPlainObject(value) ? value : { $$ref: value };
|
|
1890
|
+
if (refId) {
|
|
1746
1891
|
return {
|
|
1747
1892
|
field: {
|
|
1748
|
-
type: '
|
|
1749
|
-
|
|
1893
|
+
type: 'reference',
|
|
1894
|
+
refType: 'document',
|
|
1895
|
+
refId: refId
|
|
1750
1896
|
},
|
|
1751
|
-
newRefDocuments:
|
|
1897
|
+
newRefDocuments: []
|
|
1752
1898
|
};
|
|
1753
|
-
} else
|
|
1754
|
-
let { $$type, ...rest } = value;
|
|
1899
|
+
} else {
|
|
1755
1900
|
const modelNames = modelField.models;
|
|
1756
|
-
// for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
|
|
1757
|
-
// the 'type' property in default values
|
|
1758
|
-
if (!$$type && 'type' in rest) {
|
|
1759
|
-
$$type = rest.type;
|
|
1760
|
-
rest = _.omit(rest, 'type');
|
|
1761
|
-
}
|
|
1762
|
-
const modelName = $$type ?? (modelNames.length === 1 ? modelNames[0] : null);
|
|
1763
1901
|
if (!modelName) {
|
|
1764
|
-
|
|
1902
|
+
// for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
|
|
1903
|
+
// the 'type' property in default values
|
|
1904
|
+
if ('type' in rest) {
|
|
1905
|
+
modelName = rest.type;
|
|
1906
|
+
rest = _.omit(rest, 'type');
|
|
1907
|
+
} else if (modelNames.length === 1) {
|
|
1908
|
+
modelName = modelNames[0];
|
|
1909
|
+
}
|
|
1765
1910
|
}
|
|
1766
1911
|
const model = modelMap[modelName];
|
|
1767
1912
|
if (!model) {
|
|
1768
1913
|
throw new Error(`no model with name '${modelName}' was found`);
|
|
1769
1914
|
}
|
|
1770
|
-
const
|
|
1915
|
+
const { document, newRefDocuments } = await createDocumentRecursively({
|
|
1771
1916
|
object: rest,
|
|
1772
|
-
|
|
1773
|
-
fieldPath,
|
|
1917
|
+
model: model,
|
|
1774
1918
|
modelMap,
|
|
1775
1919
|
locale,
|
|
1776
1920
|
userContext,
|
|
1777
1921
|
contentSourceInstance
|
|
1778
1922
|
});
|
|
1779
|
-
return {
|
|
1780
|
-
field: {
|
|
1781
|
-
type: 'model',
|
|
1782
|
-
modelName: modelName,
|
|
1783
|
-
fields: result.fields
|
|
1784
|
-
},
|
|
1785
|
-
newRefDocuments: result.newRefDocuments
|
|
1786
|
-
};
|
|
1787
|
-
} else if (modelField.type === 'image') {
|
|
1788
|
-
let refId: string | undefined;
|
|
1789
|
-
if (_.isPlainObject(value)) {
|
|
1790
|
-
refId = value.$$ref;
|
|
1791
|
-
} else {
|
|
1792
|
-
refId = value;
|
|
1793
|
-
}
|
|
1794
|
-
if (!refId) {
|
|
1795
|
-
throw new Error(`reference field must specify a value`);
|
|
1796
|
-
}
|
|
1797
1923
|
return {
|
|
1798
1924
|
field: {
|
|
1799
1925
|
type: 'reference',
|
|
1800
|
-
refType: '
|
|
1801
|
-
refId:
|
|
1926
|
+
refType: 'document',
|
|
1927
|
+
refId: document.id
|
|
1802
1928
|
},
|
|
1803
|
-
newRefDocuments: []
|
|
1804
|
-
};
|
|
1805
|
-
} else if (modelField.type === 'reference') {
|
|
1806
|
-
let { $$ref: refId = null, $$type: modelName = null, ...rest } = _.isPlainObject(value) ? value : { $$ref: value };
|
|
1807
|
-
if (refId) {
|
|
1808
|
-
return {
|
|
1809
|
-
field: {
|
|
1810
|
-
type: 'reference',
|
|
1811
|
-
refType: 'document',
|
|
1812
|
-
refId: refId
|
|
1813
|
-
},
|
|
1814
|
-
newRefDocuments: []
|
|
1815
|
-
};
|
|
1816
|
-
} else {
|
|
1817
|
-
const modelNames = modelField.models;
|
|
1818
|
-
if (!modelName) {
|
|
1819
|
-
// for backward compatibility check if the object has 'type' instead of '$$type' because older projects use
|
|
1820
|
-
// the 'type' property in default values
|
|
1821
|
-
if ('type' in rest) {
|
|
1822
|
-
modelName = rest.type;
|
|
1823
|
-
rest = _.omit(rest, 'type');
|
|
1824
|
-
} else if (modelNames.length === 1) {
|
|
1825
|
-
modelName = modelNames[0];
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1828
|
-
const model = modelMap[modelName];
|
|
1829
|
-
if (!model) {
|
|
1830
|
-
throw new Error(`no model with name '${modelName}' was found`);
|
|
1831
|
-
}
|
|
1832
|
-
const { document, newRefDocuments } = await createDocumentRecursively({
|
|
1833
|
-
object: rest,
|
|
1834
|
-
model: model,
|
|
1835
|
-
modelMap,
|
|
1836
|
-
locale,
|
|
1837
|
-
userContext,
|
|
1838
|
-
contentSourceInstance
|
|
1839
|
-
});
|
|
1840
|
-
return {
|
|
1841
|
-
field: {
|
|
1842
|
-
type: 'reference',
|
|
1843
|
-
refType: 'document',
|
|
1844
|
-
refId: document.id
|
|
1845
|
-
},
|
|
1846
|
-
newRefDocuments: [document, ...newRefDocuments]
|
|
1847
|
-
};
|
|
1848
|
-
}
|
|
1849
|
-
} else if (modelField.type === 'list') {
|
|
1850
|
-
if (!Array.isArray(value)) {
|
|
1851
|
-
throw new Error(`value for list field must be array`);
|
|
1852
|
-
}
|
|
1853
|
-
const itemsField = modelField.items;
|
|
1854
|
-
if (!itemsField) {
|
|
1855
|
-
throw new Error(`list field does not define items`);
|
|
1856
|
-
}
|
|
1857
|
-
const arrayResult = await mapPromise(value, async (item, index) => {
|
|
1858
|
-
return createNestedField({
|
|
1859
|
-
value: item,
|
|
1860
|
-
modelField: itemsField,
|
|
1861
|
-
fieldPath: fieldPath.concat(index)
|
|
1862
|
-
});
|
|
1863
|
-
});
|
|
1864
|
-
return {
|
|
1865
|
-
field: {
|
|
1866
|
-
type: 'list',
|
|
1867
|
-
items: arrayResult.map((result) => result.field)
|
|
1868
|
-
},
|
|
1869
|
-
newRefDocuments: arrayResult.reduce((result: ContentSourceTypes.Document[], { newRefDocuments }) => result.concat(newRefDocuments), [])
|
|
1929
|
+
newRefDocuments: [document, ...newRefDocuments]
|
|
1870
1930
|
};
|
|
1871
1931
|
}
|
|
1932
|
+
} else if (modelField.type === 'list') {
|
|
1933
|
+
if (!Array.isArray(value)) {
|
|
1934
|
+
throw new Error(`value for list field must be array`);
|
|
1935
|
+
}
|
|
1936
|
+
const itemsField = modelField.items;
|
|
1937
|
+
if (!itemsField) {
|
|
1938
|
+
throw new Error(`list field does not define items`);
|
|
1939
|
+
}
|
|
1940
|
+
const arrayResult = await mapPromise(value, async (item, index) => {
|
|
1941
|
+
return createNestedField({
|
|
1942
|
+
value: item,
|
|
1943
|
+
modelField: itemsField,
|
|
1944
|
+
fieldPath: fieldPath.concat(index),
|
|
1945
|
+
modelMap,
|
|
1946
|
+
locale,
|
|
1947
|
+
userContext,
|
|
1948
|
+
contentSourceInstance
|
|
1949
|
+
});
|
|
1950
|
+
});
|
|
1872
1951
|
return {
|
|
1873
1952
|
field: {
|
|
1874
|
-
type:
|
|
1875
|
-
|
|
1876
|
-
}
|
|
1877
|
-
newRefDocuments: []
|
|
1953
|
+
type: 'list',
|
|
1954
|
+
items: arrayResult.map((result) => result.field)
|
|
1955
|
+
},
|
|
1956
|
+
newRefDocuments: arrayResult.reduce((result: CSITypes.Document[], { newRefDocuments }) => result.concat(newRefDocuments), [])
|
|
1878
1957
|
};
|
|
1879
|
-
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
} = {
|
|
1886
|
-
fields: {},
|
|
1958
|
+
}
|
|
1959
|
+
return {
|
|
1960
|
+
field: {
|
|
1961
|
+
type: modelField.type,
|
|
1962
|
+
value: value
|
|
1963
|
+
},
|
|
1887
1964
|
newRefDocuments: []
|
|
1888
1965
|
};
|
|
1889
|
-
const objectFieldNames = Object.keys(object);
|
|
1890
|
-
for (const modelField of modelFields) {
|
|
1891
|
-
const fieldName = modelField.name;
|
|
1892
|
-
let value;
|
|
1893
|
-
if (fieldName in object) {
|
|
1894
|
-
value = object[fieldName];
|
|
1895
|
-
_.pull(objectFieldNames, fieldName);
|
|
1896
|
-
} else if (modelField.const) {
|
|
1897
|
-
value = modelField.const;
|
|
1898
|
-
} else if (!_.isNil(modelField.default)) {
|
|
1899
|
-
value = modelField.default;
|
|
1900
|
-
}
|
|
1901
|
-
if (!_.isNil(value)) {
|
|
1902
|
-
const fieldResult = await createNestedField({
|
|
1903
|
-
value,
|
|
1904
|
-
modelField,
|
|
1905
|
-
fieldPath: fieldPath.concat(fieldName)
|
|
1906
|
-
});
|
|
1907
|
-
result.fields[fieldName] = fieldResult.field;
|
|
1908
|
-
result.newRefDocuments = result.newRefDocuments.concat(fieldResult.newRefDocuments);
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1911
|
-
if (objectFieldNames.length > 0) {
|
|
1912
|
-
throw new Error(`no model fields found when creating a document with fields: '${objectFieldNames.join(', ')}'`);
|
|
1913
|
-
}
|
|
1914
|
-
|
|
1915
|
-
return result;
|
|
1916
1966
|
}
|
|
1917
1967
|
|
|
1918
1968
|
function getModelFieldForFieldAtPath(
|
|
@@ -2040,14 +2090,15 @@ async function convertOperationField({
|
|
|
2040
2090
|
modelMap: Record<string, Model>;
|
|
2041
2091
|
locale?: string;
|
|
2042
2092
|
userContext: unknown;
|
|
2043
|
-
contentSourceInstance:
|
|
2044
|
-
}): Promise<
|
|
2045
|
-
|
|
2093
|
+
contentSourceInstance: CSITypes.ContentSourceInterface;
|
|
2094
|
+
}): Promise<CSITypes.UpdateOperationField> {
|
|
2095
|
+
// for insert operations, the modelField will be of the list, so get the modelField of the list items
|
|
2096
|
+
const modelFieldOrListItems: FieldSpecificProps = modelField.type === 'list' ? modelField.items! : modelField;
|
|
2046
2097
|
switch (operationField.type) {
|
|
2047
|
-
case 'object':
|
|
2048
|
-
result = await createNestedObjectRecursively({
|
|
2098
|
+
case 'object': {
|
|
2099
|
+
const result = await createNestedObjectRecursively({
|
|
2049
2100
|
object: operationField.object,
|
|
2050
|
-
modelFields: (
|
|
2101
|
+
modelFields: (modelFieldOrListItems as FieldObjectProps).fields,
|
|
2051
2102
|
fieldPath: fieldPath,
|
|
2052
2103
|
modelMap,
|
|
2053
2104
|
locale,
|
|
@@ -2058,12 +2109,13 @@ async function convertOperationField({
|
|
|
2058
2109
|
type: operationField.type,
|
|
2059
2110
|
fields: result.fields
|
|
2060
2111
|
};
|
|
2061
|
-
|
|
2112
|
+
}
|
|
2113
|
+
case 'model': {
|
|
2062
2114
|
const model = modelMap[operationField.modelName];
|
|
2063
2115
|
if (!model) {
|
|
2064
2116
|
throw new Error(`error updating document, could not find document model: '${operationField.modelName}'`);
|
|
2065
2117
|
}
|
|
2066
|
-
result = await createNestedObjectRecursively({
|
|
2118
|
+
const result = await createNestedObjectRecursively({
|
|
2067
2119
|
object: operationField.object,
|
|
2068
2120
|
modelFields: model.fields!,
|
|
2069
2121
|
fieldPath,
|
|
@@ -2077,8 +2129,53 @@ async function convertOperationField({
|
|
|
2077
2129
|
modelName: operationField.modelName,
|
|
2078
2130
|
fields: result.fields
|
|
2079
2131
|
};
|
|
2132
|
+
}
|
|
2133
|
+
case 'list': {
|
|
2134
|
+
if (modelField.type !== 'list') {
|
|
2135
|
+
throw new Error(`'the operation field type '${operationField.type}' does not match the model field type '${modelField.type}'`);
|
|
2136
|
+
}
|
|
2137
|
+
const result = await mapPromise(operationField.items, async (item, index) => {
|
|
2138
|
+
const result = await createNestedField({
|
|
2139
|
+
value: item,
|
|
2140
|
+
modelField: modelField.items!,
|
|
2141
|
+
fieldPath,
|
|
2142
|
+
modelMap,
|
|
2143
|
+
locale,
|
|
2144
|
+
userContext,
|
|
2145
|
+
contentSourceInstance
|
|
2146
|
+
});
|
|
2147
|
+
return result.field;
|
|
2148
|
+
});
|
|
2149
|
+
return {
|
|
2150
|
+
type: operationField.type,
|
|
2151
|
+
items: result
|
|
2152
|
+
};
|
|
2153
|
+
}
|
|
2154
|
+
case 'string':
|
|
2155
|
+
if (typeof operationField.value !== 'string') {
|
|
2156
|
+
return {
|
|
2157
|
+
type: operationField.type,
|
|
2158
|
+
value: ''
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
return operationField as CSITypes.UpdateOperationField;
|
|
2162
|
+
case 'enum':
|
|
2163
|
+
if (typeof operationField.value !== 'string') {
|
|
2164
|
+
if (modelFieldOrListItems.type !== 'enum') {
|
|
2165
|
+
throw new Error(`'the operation field type 'enum' does not match the model field type '${modelFieldOrListItems.type}'`);
|
|
2166
|
+
}
|
|
2167
|
+
const option = modelFieldOrListItems.options[0]!;
|
|
2168
|
+
const optionValue = typeof option === 'object' ? option.value : option;
|
|
2169
|
+
return {
|
|
2170
|
+
type: operationField.type,
|
|
2171
|
+
value: optionValue
|
|
2172
|
+
};
|
|
2173
|
+
}
|
|
2174
|
+
return operationField as CSITypes.UpdateOperationField;
|
|
2175
|
+
case 'image':
|
|
2176
|
+
return operationField as CSITypes.UpdateOperationField;
|
|
2080
2177
|
default:
|
|
2081
|
-
return operationField as
|
|
2178
|
+
return operationField as CSITypes.UpdateOperationField;
|
|
2082
2179
|
}
|
|
2083
2180
|
}
|
|
2084
2181
|
|
|
@@ -2110,3 +2207,25 @@ function isStackbitConfigFile(filePath: string) {
|
|
|
2110
2207
|
const isMainStackbitConfigFile = pathObject.name === 'stackbit' && ['yaml', 'yml'].includes(pathObject.ext.substring(1));
|
|
2111
2208
|
return isMainStackbitConfigFile || isInDotStackbitFolder;
|
|
2112
2209
|
}
|
|
2210
|
+
|
|
2211
|
+
function getCSIDocumentsAndAssetsFromContentSourceDataByIds(
|
|
2212
|
+
contentSourceData: ContentSourceData,
|
|
2213
|
+
objects: { srcObjectId: string }[]
|
|
2214
|
+
): {
|
|
2215
|
+
documents: CSITypes.Document[];
|
|
2216
|
+
assets: CSITypes.Asset[];
|
|
2217
|
+
} {
|
|
2218
|
+
const documents: CSITypes.Document[] = [];
|
|
2219
|
+
const assets: CSITypes.Asset[] = [];
|
|
2220
|
+
for (const object of objects) {
|
|
2221
|
+
if (object.srcObjectId in contentSourceData.csiDocumentMap) {
|
|
2222
|
+
documents.push(contentSourceData.csiDocumentMap[object.srcObjectId]!);
|
|
2223
|
+
} else if (object.srcObjectId in contentSourceData.csiAssetMap) {
|
|
2224
|
+
assets.push(contentSourceData.csiAssetMap[object.srcObjectId]!);
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
return {
|
|
2228
|
+
documents,
|
|
2229
|
+
assets
|
|
2230
|
+
};
|
|
2231
|
+
}
|