@stackbit/cms-core 0.1.13-alpha.0 → 0.1.13
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-store-types.d.ts +27 -3
- package/dist/content-store-types.d.ts.map +1 -1
- package/dist/content-store-utils.d.ts +12 -1
- package/dist/content-store-utils.d.ts.map +1 -1
- package/dist/content-store-utils.js +44 -1
- package/dist/content-store-utils.js.map +1 -1
- package/dist/content-store.d.ts +5 -1
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +56 -23
- package/dist/content-store.js.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.d.ts.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.js +13 -6
- package/dist/utils/csi-to-store-docs-converter.js.map +1 -1
- package/dist/utils/store-to-api-docs-converter.js +1 -1
- package/dist/utils/store-to-api-docs-converter.js.map +1 -1
- package/dist/utils/store-to-csi-docs-converter.d.ts +4 -0
- package/dist/utils/store-to-csi-docs-converter.d.ts.map +1 -0
- package/dist/utils/store-to-csi-docs-converter.js +211 -0
- package/dist/utils/store-to-csi-docs-converter.js.map +1 -0
- package/package.json +5 -5
- package/src/content-store-types.ts +41 -4
- package/src/content-store-utils.ts +61 -3
- package/src/content-store.ts +86 -74
- package/src/utils/csi-to-store-docs-converter.ts +21 -12
- package/src/utils/store-to-api-docs-converter.ts +3 -3
- package/src/utils/store-to-csi-docs-converter.ts +222 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackbit/cms-core",
|
|
3
|
-
"version": "0.1.13
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "stackbit-dev",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"@babel/parser": "^7.11.5",
|
|
30
30
|
"@babel/traverse": "^7.11.5",
|
|
31
31
|
"@iarna/toml": "^2.2.3",
|
|
32
|
-
"@stackbit/sdk": "^0.3.9
|
|
33
|
-
"@stackbit/types": "^0.1.7
|
|
34
|
-
"@stackbit/utils": "^0.2.
|
|
32
|
+
"@stackbit/sdk": "^0.3.9",
|
|
33
|
+
"@stackbit/types": "^0.1.7",
|
|
34
|
+
"@stackbit/utils": "^0.2.12",
|
|
35
35
|
"chalk": "^4.0.1",
|
|
36
36
|
"esm": "^3.2.25",
|
|
37
37
|
"fs-extra": "^8.1.0",
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"sanitize-filename": "^1.6.3",
|
|
46
46
|
"slugify": "^1.6.5"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "c82a7ec57444318dbd585486d90275635373a6f0"
|
|
49
49
|
}
|
|
@@ -1,7 +1,42 @@
|
|
|
1
1
|
import { DocumentStatus, FieldType } from '@stackbit/types';
|
|
2
|
+
import { Model } from '@stackbit/sdk';
|
|
3
|
+
import * as CSITypes from '@stackbit/types';
|
|
2
4
|
|
|
3
5
|
export { FieldType, DocumentStatus, Logger } from '@stackbit/types';
|
|
4
6
|
|
|
7
|
+
export interface ContentSourceData {
|
|
8
|
+
id: string;
|
|
9
|
+
instance: CSITypes.ContentSourceInterface;
|
|
10
|
+
srcType: string;
|
|
11
|
+
srcProjectId: string;
|
|
12
|
+
locales?: CSITypes.Locale[];
|
|
13
|
+
defaultLocaleCode?: string;
|
|
14
|
+
/* Array of extended and validated Models */
|
|
15
|
+
models: Model[];
|
|
16
|
+
/* Map of extended and validated Models by model name */
|
|
17
|
+
modelMap: Record<string, Model>;
|
|
18
|
+
/* Array of original Models (as provided by content source) */
|
|
19
|
+
csiModels: CSITypes.Model[];
|
|
20
|
+
/* Map of original Models (as provided by content source) by model name */
|
|
21
|
+
csiModelMap: Record<string, CSITypes.Model>;
|
|
22
|
+
/* Array of original content source Documents */
|
|
23
|
+
csiDocuments: CSITypes.Document[];
|
|
24
|
+
/* Map of original content source Documents by document ID */
|
|
25
|
+
csiDocumentMap: Record<string, CSITypes.Document>;
|
|
26
|
+
/* Array of converted content-store Documents */
|
|
27
|
+
documents: Document[];
|
|
28
|
+
/* Map of converted content-store Documents by document ID */
|
|
29
|
+
documentMap: Record<string, Document>;
|
|
30
|
+
/* Array of original content source Assets */
|
|
31
|
+
csiAssets: CSITypes.Asset[];
|
|
32
|
+
/* Map of original content source Assets by asset ID */
|
|
33
|
+
csiAssetMap: Record<string, CSITypes.Asset>;
|
|
34
|
+
/* Array of converted content-store Assets */
|
|
35
|
+
assets: Asset[];
|
|
36
|
+
/* Map of converted content-store Assets by asset ID */
|
|
37
|
+
assetMap: Record<string, Asset>;
|
|
38
|
+
}
|
|
39
|
+
|
|
5
40
|
export interface Document {
|
|
6
41
|
type: 'document';
|
|
7
42
|
srcType: string;
|
|
@@ -170,7 +205,7 @@ export type DocumentFieldTypeLocalized<BaseFieldProps, LocalizedFieldProps> = Si
|
|
|
170
205
|
BaseFieldProps & {
|
|
171
206
|
label?: string;
|
|
172
207
|
localized: true;
|
|
173
|
-
locales: Record<string, { locale: string } & Exclude<LocalizedFieldProps, DocumentFieldUnsetProps>>;
|
|
208
|
+
locales: Record<string, { locale: string } & Omit<Exclude<LocalizedFieldProps, DocumentFieldUnsetProps>, 'isUnset'>>;
|
|
174
209
|
}
|
|
175
210
|
>;
|
|
176
211
|
|
|
@@ -188,7 +223,7 @@ export type DocumentFieldTypeAPI<BaseFieldProps, LocalizedFieldProps> = BaseFiel
|
|
|
188
223
|
description?: string;
|
|
189
224
|
locale?: string;
|
|
190
225
|
localized?: boolean;
|
|
191
|
-
} & ({ localized?: false
|
|
226
|
+
} & ({ localized?: false } | { localized: true; locale: string });
|
|
192
227
|
|
|
193
228
|
// any field that is not 'object' | 'model' | 'reference' | 'richText' | 'markdown' | 'list'
|
|
194
229
|
export type DocumentValueFieldType = Exclude<FieldType, 'object' | 'model' | 'reference' | 'markdown' | 'richText' | 'list' | 'image'>;
|
|
@@ -306,11 +341,13 @@ export type DocumentListFieldAPI = DocumentFieldTypeAPI<DocumentListFieldBase, D
|
|
|
306
341
|
export type DocumentListFieldBase = {
|
|
307
342
|
type: 'list';
|
|
308
343
|
};
|
|
344
|
+
export type DocumentListFieldItems = Exclude<DocumentFieldNonLocalized, DocumentListFieldNonLocalized>;
|
|
309
345
|
export type DocumentListFieldProps = {
|
|
310
|
-
items:
|
|
346
|
+
items: DocumentListFieldItems[];
|
|
311
347
|
};
|
|
348
|
+
export type DocumentListFieldItemsAPI = Exclude<DocumentFieldAPI, DocumentListFieldAPI>;
|
|
312
349
|
export type DocumentListFieldPropsAPI = {
|
|
313
|
-
items:
|
|
350
|
+
items: DocumentListFieldItemsAPI[];
|
|
314
351
|
};
|
|
315
352
|
|
|
316
353
|
// image
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import { Model } from '@stackbit/sdk';
|
|
3
3
|
import { append } from '@stackbit/utils';
|
|
4
|
-
import { Field, FieldList, FieldListItems, FieldListProps, FieldObjectProps, FieldSpecificProps } from '@stackbit/types';
|
|
4
|
+
import { Field, FieldList, FieldListItems, FieldListProps, FieldObjectProps, FieldSpecificProps, SiteMapEntry } from '@stackbit/types';
|
|
5
5
|
import * as CSITypes from '@stackbit/types';
|
|
6
|
-
|
|
7
6
|
import * as ContentStoreTypes from './content-store-types';
|
|
8
7
|
|
|
9
8
|
export function getContentSourceIdForContentSource(contentSource: CSITypes.ContentSourceInterface): string {
|
|
@@ -159,7 +158,11 @@ export function groupModelsByContentSource({ models }: { models: CSITypes.ModelW
|
|
|
159
158
|
return modelMapByContentSource;
|
|
160
159
|
}
|
|
161
160
|
|
|
162
|
-
export function groupDocumentsByContentSource({
|
|
161
|
+
export function groupDocumentsByContentSource({
|
|
162
|
+
documents
|
|
163
|
+
}: {
|
|
164
|
+
documents: CSITypes.DocumentWithSource[];
|
|
165
|
+
}): Record<string, Record<string, CSITypes.Document[]>> {
|
|
163
166
|
const documentMapByContentSource: Record<string, Record<string, CSITypes.Document[]>> = {};
|
|
164
167
|
for (const document of documents) {
|
|
165
168
|
const { srcType, srcProjectId, ...rest } = document;
|
|
@@ -167,3 +170,58 @@ export function groupDocumentsByContentSource({ documents }: { documents: CSITyp
|
|
|
167
170
|
}
|
|
168
171
|
return documentMapByContentSource;
|
|
169
172
|
}
|
|
173
|
+
|
|
174
|
+
export function getCSIDocumentsAndAssetsFromContentSourceDataByIds(
|
|
175
|
+
contentSourceData: ContentStoreTypes.ContentSourceData,
|
|
176
|
+
objects: { srcObjectId: string }[]
|
|
177
|
+
): {
|
|
178
|
+
documents: CSITypes.Document[];
|
|
179
|
+
assets: CSITypes.Asset[];
|
|
180
|
+
} {
|
|
181
|
+
const documents: CSITypes.Document[] = [];
|
|
182
|
+
const assets: CSITypes.Asset[] = [];
|
|
183
|
+
for (const object of objects) {
|
|
184
|
+
if (object.srcObjectId in contentSourceData.csiDocumentMap) {
|
|
185
|
+
documents.push(contentSourceData.csiDocumentMap[object.srcObjectId]!);
|
|
186
|
+
} else if (object.srcObjectId in contentSourceData.csiAssetMap) {
|
|
187
|
+
assets.push(contentSourceData.csiAssetMap[object.srcObjectId]!);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
documents,
|
|
192
|
+
assets
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function getDocumentFieldLabelValueForSiteMapEntry({
|
|
197
|
+
siteMapEntry,
|
|
198
|
+
locale,
|
|
199
|
+
contentSourceDataById
|
|
200
|
+
}: {
|
|
201
|
+
siteMapEntry: SiteMapEntry;
|
|
202
|
+
locale?: string;
|
|
203
|
+
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
|
|
204
|
+
}): string | null {
|
|
205
|
+
if (!('document' in siteMapEntry)) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
const contentSourceId = getContentSourceId(siteMapEntry.document.srcType, siteMapEntry.document.srcProjectId);
|
|
209
|
+
const contentSourceData = contentSourceDataById[contentSourceId];
|
|
210
|
+
if (!contentSourceData) {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
const labelFieldName = contentSourceData.modelMap[siteMapEntry.document.modelName]?.labelField;
|
|
214
|
+
const document = contentSourceData.documentMap[siteMapEntry.document.id];
|
|
215
|
+
if (!labelFieldName || !document) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
const labelField = document.fields[labelFieldName];
|
|
219
|
+
if (!labelField) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
const localizedLabelField = getDocumentFieldForLocale(labelField, locale);
|
|
223
|
+
if (!localizedLabelField || !('value' in localizedLabelField) || !localizedLabelField.value) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
return String(localizedLabelField.value);
|
|
227
|
+
}
|
package/src/content-store.ts
CHANGED
|
@@ -3,21 +3,20 @@ import path from 'path';
|
|
|
3
3
|
import sanitizeFilename from 'sanitize-filename';
|
|
4
4
|
|
|
5
5
|
import * as CSITypes from '@stackbit/types';
|
|
6
|
-
import { getLocalizedFieldForLocale, ModelExtension, UserCommandSpawner } from '@stackbit/types';
|
|
6
|
+
import { DocumentWithSource, getLocalizedFieldForLocale, ModelExtension, ModelWithSource, UserCommandSpawner } from '@stackbit/types';
|
|
7
7
|
import {
|
|
8
8
|
Config,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
extendModelsWithPresetsIds,
|
|
10
|
+
getPresetDirs,
|
|
11
|
+
getYamlModelDirs,
|
|
11
12
|
ImageModel,
|
|
12
|
-
Preset,
|
|
13
|
-
PresetMap,
|
|
14
13
|
loadPresets,
|
|
15
|
-
getYamlModelDirs,
|
|
16
|
-
getPresetDirs,
|
|
17
14
|
loadYamlModelsFromFiles,
|
|
15
|
+
mergeConfigModelsWithExternalModels,
|
|
18
16
|
mergeConfigModelsWithModelsFromFiles,
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
Model,
|
|
18
|
+
Preset,
|
|
19
|
+
PresetMap
|
|
21
20
|
} from '@stackbit/sdk';
|
|
22
21
|
import { deferWhileRunning, mapPromise, reducePromise } from '@stackbit/utils';
|
|
23
22
|
|
|
@@ -26,13 +25,16 @@ import { Timer } from './utils/timer';
|
|
|
26
25
|
import { SearchFilter } from './types/search-filter';
|
|
27
26
|
import { searchDocuments } from './utils/search-utils';
|
|
28
27
|
import { mapCSIAssetsToStoreAssets, mapCSIDocumentsToStoreDocuments } from './utils/csi-to-store-docs-converter';
|
|
28
|
+
import { mapStoreDocumentsToCSIDocumentsWithSource } from './utils/store-to-csi-docs-converter';
|
|
29
29
|
import {
|
|
30
30
|
getContentSourceId,
|
|
31
31
|
getContentSourceIdForContentSource,
|
|
32
|
+
getDocumentFieldLabelValueForSiteMapEntry,
|
|
33
|
+
getCSIDocumentsAndAssetsFromContentSourceDataByIds,
|
|
32
34
|
getModelFieldForFieldAtPath,
|
|
33
35
|
getUserContextForSrcType,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
groupDocumentsByContentSource,
|
|
37
|
+
groupModelsByContentSource
|
|
36
38
|
} from './content-store-utils';
|
|
37
39
|
import { mapAssetsToLocalizedApiImages, mapDocumentsToLocalizedApiObjects, mapStoreAssetsToAPIAssets } from './utils/store-to-api-docs-converter';
|
|
38
40
|
import { convertOperationField, createDocumentRecursively, getCreateDocumentThunk } from './utils/create-update-csi-docs';
|
|
@@ -54,39 +56,7 @@ export interface ContentSourceOptions {
|
|
|
54
56
|
devAppRestartNeeded?: () => void;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
id: string;
|
|
59
|
-
instance: CSITypes.ContentSourceInterface;
|
|
60
|
-
srcType: string;
|
|
61
|
-
srcProjectId: string;
|
|
62
|
-
locales?: CSITypes.Locale[];
|
|
63
|
-
defaultLocaleCode?: string;
|
|
64
|
-
/* Array of extended and validated Models */
|
|
65
|
-
models: Model[];
|
|
66
|
-
/* Map of extended and validated Models by model name */
|
|
67
|
-
modelMap: Record<string, Model>;
|
|
68
|
-
/* Array of original Models (as provided by content source) */
|
|
69
|
-
csiModels: CSITypes.Model[];
|
|
70
|
-
/* Map of original Models (as provided by content source) by model name */
|
|
71
|
-
csiModelMap: Record<string, CSITypes.Model>;
|
|
72
|
-
/* Array of original content source Documents */
|
|
73
|
-
csiDocuments: CSITypes.Document[];
|
|
74
|
-
/* Map of original content source Documents by document ID */
|
|
75
|
-
csiDocumentMap: Record<string, CSITypes.Document>;
|
|
76
|
-
/* Array of converted content-store Documents */
|
|
77
|
-
documents: ContentStoreTypes.Document[];
|
|
78
|
-
/* Map of converted content-store Documents by document ID */
|
|
79
|
-
documentMap: Record<string, ContentStoreTypes.Document>;
|
|
80
|
-
/* Array of original content source Assets */
|
|
81
|
-
csiAssets: CSITypes.Asset[];
|
|
82
|
-
/* Map of original content source Assets by asset ID */
|
|
83
|
-
csiAssetMap: Record<string, CSITypes.Asset>;
|
|
84
|
-
/* Array of converted content-store Assets */
|
|
85
|
-
assets: ContentStoreTypes.Asset[];
|
|
86
|
-
/* Map of converted content-store Assets by asset ID */
|
|
87
|
-
assetMap: Record<string, ContentStoreTypes.Asset>;
|
|
88
|
-
}
|
|
89
|
-
|
|
59
|
+
type ContentSourceData = ContentStoreTypes.ContentSourceData;
|
|
90
60
|
type ContentSourceRawData = Omit<ContentSourceData, 'models' | 'modelMap' | 'documents' | 'documentMap'>;
|
|
91
61
|
|
|
92
62
|
export class ContentStore {
|
|
@@ -687,7 +657,9 @@ export class ContentStore {
|
|
|
687
657
|
message += `, srcProjectId: '${configModel.srcProjectId}'`;
|
|
688
658
|
}
|
|
689
659
|
const matchesModelsMessage = matchedCSIModels.map((model) => `srcType: '${model.srcType}', srcProjectId: '${model.srcProjectId}'`).join('; ');
|
|
690
|
-
this.userLogger.warn(
|
|
660
|
+
this.userLogger.warn(
|
|
661
|
+
`model ${message} defined in stackbit config matches more that 1 model in the following content sources: ${matchesModelsMessage}`
|
|
662
|
+
);
|
|
691
663
|
}
|
|
692
664
|
|
|
693
665
|
const modelsWithSource = contentSourceRawDataArr.reduce((accum: CSITypes.ModelWithSource[], csData) => {
|
|
@@ -905,6 +877,68 @@ export class ContentStore {
|
|
|
905
877
|
};
|
|
906
878
|
}
|
|
907
879
|
|
|
880
|
+
getSiteMapEntries({ locale }: { locale?: string } = {}): CSITypes.SiteMapEntry[] {
|
|
881
|
+
if (!this.stackbitConfig?.siteMap) {
|
|
882
|
+
return [];
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// TODO: cache siteMap in processData
|
|
886
|
+
const siteMapOptions = _.reduce(
|
|
887
|
+
this.contentSourceDataById,
|
|
888
|
+
(accum: { models: ModelWithSource[]; documents: DocumentWithSource[] }, contentSourceData) => {
|
|
889
|
+
return {
|
|
890
|
+
models: accum.models.concat(
|
|
891
|
+
contentSourceData.models.map((model) => ({
|
|
892
|
+
srcType: contentSourceData.srcType,
|
|
893
|
+
srcProjectId: contentSourceData.srcProjectId,
|
|
894
|
+
...model
|
|
895
|
+
}))
|
|
896
|
+
),
|
|
897
|
+
documents: accum.documents.concat(mapStoreDocumentsToCSIDocumentsWithSource(contentSourceData.documents))
|
|
898
|
+
};
|
|
899
|
+
},
|
|
900
|
+
{ models: [], documents: [] }
|
|
901
|
+
);
|
|
902
|
+
|
|
903
|
+
const siteMapEntries = this.stackbitConfig.siteMap(siteMapOptions).reduce((accum: CSITypes.SiteMapEntry[], siteMapEntry) => {
|
|
904
|
+
// The site map entries are provided by user, sanitize them and filter out illegal entries
|
|
905
|
+
if (!siteMapEntry) {
|
|
906
|
+
return accum;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if (typeof siteMapEntry.urlPath !== 'string') {
|
|
910
|
+
return accum;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
if ('document' in siteMapEntry) {
|
|
914
|
+
const doc = siteMapEntry.document;
|
|
915
|
+
if (!doc.srcType || !doc.srcProjectId || !doc.modelName || !doc.id) {
|
|
916
|
+
return accum;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
if (!siteMapEntry.label) {
|
|
921
|
+
const fieldLabelValue = getDocumentFieldLabelValueForSiteMapEntry({ siteMapEntry, locale, contentSourceDataById: this.contentSourceDataById });
|
|
922
|
+
siteMapEntry = {
|
|
923
|
+
...siteMapEntry,
|
|
924
|
+
label: fieldLabelValue ?? siteMapEntry.urlPath
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
if (!siteMapEntry.stableId) {
|
|
929
|
+
siteMapEntry = {
|
|
930
|
+
...siteMapEntry,
|
|
931
|
+
stableId: 'document' in siteMapEntry ? siteMapEntry.document.id : siteMapEntry.urlPath
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
accum.push(siteMapEntry);
|
|
936
|
+
return accum;
|
|
937
|
+
}, []);
|
|
938
|
+
|
|
939
|
+
return _.isEmpty(locale) ? siteMapEntries : siteMapEntries.filter((siteMapEntry) => !siteMapEntry.locale || siteMapEntry.locale === locale);
|
|
940
|
+
}
|
|
941
|
+
|
|
908
942
|
getDocument({
|
|
909
943
|
srcDocumentId,
|
|
910
944
|
srcProjectId,
|
|
@@ -925,7 +959,7 @@ export class ContentStore {
|
|
|
925
959
|
(documents: ContentStoreTypes.Document[], contentSourceData) => {
|
|
926
960
|
const currentDocuments = _.isEmpty(locale)
|
|
927
961
|
? contentSourceData.documents
|
|
928
|
-
: contentSourceData.documents.filter(document => !document.locale || document.locale === locale)
|
|
962
|
+
: contentSourceData.documents.filter((document) => !document.locale || document.locale === locale);
|
|
929
963
|
return documents.concat(currentDocuments);
|
|
930
964
|
},
|
|
931
965
|
[]
|
|
@@ -944,7 +978,7 @@ export class ContentStore {
|
|
|
944
978
|
(assets: ContentStoreTypes.Asset[], contentSourceData) => {
|
|
945
979
|
const currentAssets = _.isEmpty(locale)
|
|
946
980
|
? contentSourceData.assets
|
|
947
|
-
: contentSourceData.assets.filter(asset => !asset.locale || asset.locale === locale)
|
|
981
|
+
: contentSourceData.assets.filter((asset) => !asset.locale || asset.locale === locale);
|
|
948
982
|
return assets.concat(currentAssets);
|
|
949
983
|
},
|
|
950
984
|
[]
|
|
@@ -957,10 +991,10 @@ export class ContentStore {
|
|
|
957
991
|
this.contentSourceDataById,
|
|
958
992
|
(objects: ContentStoreTypes.APIObject[], contentSourceData) => {
|
|
959
993
|
const documents = hasExplicitLocale
|
|
960
|
-
? contentSourceData.documents.filter(document => !document.locale || document.locale === locale)
|
|
994
|
+
? contentSourceData.documents.filter((document) => !document.locale || document.locale === locale)
|
|
961
995
|
: contentSourceData.documents;
|
|
962
996
|
const assets = hasExplicitLocale
|
|
963
|
-
? contentSourceData.assets.filter(asset => !asset.locale || asset.locale === locale)
|
|
997
|
+
? contentSourceData.assets.filter((asset) => !asset.locale || asset.locale === locale)
|
|
964
998
|
: contentSourceData.assets;
|
|
965
999
|
const currentLocale = locale ?? contentSourceData.defaultLocaleCode;
|
|
966
1000
|
const documentObjects = mapDocumentsToLocalizedApiObjects(documents, currentLocale);
|
|
@@ -1568,12 +1602,12 @@ export class ContentStore {
|
|
|
1568
1602
|
|
|
1569
1603
|
contentSourceIds.forEach((contentSourceId) => {
|
|
1570
1604
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
1571
|
-
|
|
1605
|
+
|
|
1572
1606
|
_.set(schema, [contentSourceData.srcType, contentSourceData.srcProjectId], contentSourceData.modelMap);
|
|
1573
1607
|
|
|
1574
1608
|
const contentSourceDocuments = _.isEmpty(locale)
|
|
1575
|
-
|
|
1576
|
-
|
|
1609
|
+
? contentSourceData.documents
|
|
1610
|
+
: contentSourceData.documents.filter((document) => !document.locale || document.locale === locale);
|
|
1577
1611
|
documents.push(...contentSourceDocuments);
|
|
1578
1612
|
|
|
1579
1613
|
if (contentSourceData.defaultLocaleCode) {
|
|
@@ -1624,28 +1658,6 @@ export class ContentStore {
|
|
|
1624
1658
|
}
|
|
1625
1659
|
}
|
|
1626
1660
|
|
|
1627
|
-
function getCSIDocumentsAndAssetsFromContentSourceDataByIds(
|
|
1628
|
-
contentSourceData: ContentSourceData,
|
|
1629
|
-
objects: { srcObjectId: string }[]
|
|
1630
|
-
): {
|
|
1631
|
-
documents: CSITypes.Document[];
|
|
1632
|
-
assets: CSITypes.Asset[];
|
|
1633
|
-
} {
|
|
1634
|
-
const documents: CSITypes.Document[] = [];
|
|
1635
|
-
const assets: CSITypes.Asset[] = [];
|
|
1636
|
-
for (const object of objects) {
|
|
1637
|
-
if (object.srcObjectId in contentSourceData.csiDocumentMap) {
|
|
1638
|
-
documents.push(contentSourceData.csiDocumentMap[object.srcObjectId]!);
|
|
1639
|
-
} else if (object.srcObjectId in contentSourceData.csiAssetMap) {
|
|
1640
|
-
assets.push(contentSourceData.csiAssetMap[object.srcObjectId]!);
|
|
1641
|
-
}
|
|
1642
|
-
}
|
|
1643
|
-
return {
|
|
1644
|
-
documents,
|
|
1645
|
-
assets
|
|
1646
|
-
};
|
|
1647
|
-
}
|
|
1648
|
-
|
|
1649
1661
|
function internalValidateContent(
|
|
1650
1662
|
documents: CSITypes.Document[],
|
|
1651
1663
|
assets: CSITypes.Asset[],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
import {
|
|
3
|
-
import { isLocalizedField } from '@stackbit/types';
|
|
2
|
+
import { Model, ImageModel } from '@stackbit/sdk';
|
|
3
|
+
import { Field, FieldSpecificProps, FieldList, FieldModelProps, FieldObjectProps, isLocalizedField } from '@stackbit/types';
|
|
4
4
|
import * as CSITypes from '@stackbit/types';
|
|
5
5
|
|
|
6
6
|
import * as ContentStoreTypes from '../content-store-types';
|
|
@@ -163,6 +163,7 @@ function mapCSIFieldsToStoreFields({
|
|
|
163
163
|
const docField = mapCSIFieldToStoreField({
|
|
164
164
|
csiDocumentField,
|
|
165
165
|
modelField,
|
|
166
|
+
localized: modelField.localized,
|
|
166
167
|
context
|
|
167
168
|
});
|
|
168
169
|
// Override document field types with specific model field types.
|
|
@@ -172,9 +173,6 @@ function mapCSIFieldsToStoreFields({
|
|
|
172
173
|
docField.type = modelField.type;
|
|
173
174
|
}
|
|
174
175
|
docField.label = modelField.label;
|
|
175
|
-
if ('localized' in modelField) {
|
|
176
|
-
docField.localized = modelField.localized;
|
|
177
|
-
}
|
|
178
176
|
result[modelField.name] = docField;
|
|
179
177
|
return result;
|
|
180
178
|
}, {});
|
|
@@ -183,18 +181,24 @@ function mapCSIFieldsToStoreFields({
|
|
|
183
181
|
function mapCSIFieldToStoreField({
|
|
184
182
|
csiDocumentField,
|
|
185
183
|
modelField,
|
|
184
|
+
localized,
|
|
186
185
|
context
|
|
187
186
|
}: {
|
|
188
187
|
csiDocumentField: CSITypes.DocumentField | undefined;
|
|
189
|
-
modelField: FieldSpecificProps;
|
|
188
|
+
modelField: Field | FieldSpecificProps;
|
|
189
|
+
localized?: boolean;
|
|
190
190
|
context: MapContext;
|
|
191
191
|
}): ContentStoreTypes.DocumentField {
|
|
192
192
|
if (!csiDocumentField) {
|
|
193
193
|
const isUnset = ['object', 'model', 'reference', 'richText', 'markdown', 'image', 'file', 'json'].includes(modelField.type);
|
|
194
194
|
return {
|
|
195
195
|
type: modelField.type,
|
|
196
|
-
...(
|
|
197
|
-
|
|
196
|
+
...(localized
|
|
197
|
+
? { localized, locales: {} }
|
|
198
|
+
: {
|
|
199
|
+
...(isUnset ? { isUnset } : null),
|
|
200
|
+
...(modelField.type === 'list' ? { items: [] } : null)
|
|
201
|
+
})
|
|
198
202
|
} as ContentStoreTypes.DocumentField;
|
|
199
203
|
}
|
|
200
204
|
// TODO: check if need to add "options" to "enum" and subtype/min/max to "number"
|
|
@@ -204,7 +208,8 @@ function mapCSIFieldToStoreField({
|
|
|
204
208
|
case 'model':
|
|
205
209
|
return mapModelField(csiDocumentField as CSITypes.DocumentModelField, modelField, context);
|
|
206
210
|
case 'list':
|
|
207
|
-
|
|
211
|
+
// list can not be in list, so modelField must be FieldList
|
|
212
|
+
return mapListField(csiDocumentField as CSITypes.DocumentListField, modelField as FieldList, context);
|
|
208
213
|
case 'richText':
|
|
209
214
|
return mapRichTextField(csiDocumentField as CSITypes.DocumentRichTextField);
|
|
210
215
|
case 'markdown':
|
|
@@ -282,7 +287,7 @@ function mapModelField(csiDocumentField: CSITypes.DocumentModelField, modelField
|
|
|
282
287
|
};
|
|
283
288
|
}
|
|
284
289
|
|
|
285
|
-
function mapListField(csiDocumentField: CSITypes.DocumentListField, modelField:
|
|
290
|
+
function mapListField(csiDocumentField: CSITypes.DocumentListField, modelField: FieldList, context: MapContext): ContentStoreTypes.DocumentListField {
|
|
286
291
|
if (!isLocalizedField(csiDocumentField)) {
|
|
287
292
|
return {
|
|
288
293
|
type: csiDocumentField.type,
|
|
@@ -290,8 +295,10 @@ function mapListField(csiDocumentField: CSITypes.DocumentListField, modelField:
|
|
|
290
295
|
mapCSIFieldToStoreField({
|
|
291
296
|
csiDocumentField: item,
|
|
292
297
|
modelField: modelField.items ?? { type: 'string' },
|
|
298
|
+
// list items can not be localized, only the list itself can be localized
|
|
299
|
+
localized: false,
|
|
293
300
|
context
|
|
294
|
-
})
|
|
301
|
+
}) as ContentStoreTypes.DocumentListFieldItems
|
|
295
302
|
)
|
|
296
303
|
};
|
|
297
304
|
}
|
|
@@ -305,8 +312,10 @@ function mapListField(csiDocumentField: CSITypes.DocumentListField, modelField:
|
|
|
305
312
|
mapCSIFieldToStoreField({
|
|
306
313
|
csiDocumentField: item,
|
|
307
314
|
modelField: modelField.items ?? { type: 'string' },
|
|
315
|
+
// list items can not be localized, only the list itself can be localized
|
|
316
|
+
localized: false,
|
|
308
317
|
context
|
|
309
|
-
})
|
|
318
|
+
}) as ContentStoreTypes.DocumentListFieldItems
|
|
310
319
|
)
|
|
311
320
|
};
|
|
312
321
|
})
|
|
@@ -149,7 +149,7 @@ function toLocalizedAPIField(docField: ContentStoreTypes.DocumentField, locale?:
|
|
|
149
149
|
const { type, refType, localized, locales, ...base } = docField;
|
|
150
150
|
const localeProps = locales && locale ? locales[locale] : undefined;
|
|
151
151
|
// if reference field isUnset === true, it behaves like a regular object
|
|
152
|
-
if (!localeProps
|
|
152
|
+
if (!localeProps) {
|
|
153
153
|
return {
|
|
154
154
|
type: 'object',
|
|
155
155
|
isUnset: true,
|
|
@@ -186,14 +186,14 @@ function toLocalizedAPIField(docField: ContentStoreTypes.DocumentField, locale?:
|
|
|
186
186
|
return {
|
|
187
187
|
...base,
|
|
188
188
|
...localeProps,
|
|
189
|
-
items: (localeProps?.items ?? []).map((field) => toLocalizedAPIField(field, locale, true)),
|
|
189
|
+
items: (localeProps?.items ?? []).map((field) => toLocalizedAPIField(field, locale, true) as ContentStoreTypes.DocumentListFieldItemsAPI),
|
|
190
190
|
...localeFields(localized)
|
|
191
191
|
};
|
|
192
192
|
}
|
|
193
193
|
return {
|
|
194
194
|
...docField,
|
|
195
195
|
...localeFields(docField.localized),
|
|
196
|
-
items: docField.items.map((field) => toLocalizedAPIField(field, locale, true))
|
|
196
|
+
items: docField.items.map((field) => toLocalizedAPIField(field, locale, true) as ContentStoreTypes.DocumentListFieldItemsAPI)
|
|
197
197
|
};
|
|
198
198
|
default:
|
|
199
199
|
const _exhaustiveCheck: never = docField;
|