@stackbit/cms-core 0.1.10-alpha.0 → 0.1.11
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 +9 -4
- package/dist/content-store-types.d.ts.map +1 -1
- package/dist/content-store.d.ts +2 -1
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +28 -37
- package/dist/content-store.js.map +1 -1
- package/dist/utils/create-update-csi-docs.d.ts.map +1 -1
- package/dist/utils/create-update-csi-docs.js +11 -0
- package/dist/utils/create-update-csi-docs.js.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.d.ts +20 -0
- package/dist/utils/csi-to-store-docs-converter.d.ts.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.js +20 -0
- package/dist/utils/csi-to-store-docs-converter.js.map +1 -1
- package/dist/utils/duplicate-document.d.ts +12 -0
- package/dist/utils/duplicate-document.d.ts.map +1 -0
- package/dist/utils/duplicate-document.js +196 -0
- package/dist/utils/duplicate-document.js.map +1 -0
- package/dist/utils/store-to-api-docs-converter.d.ts.map +1 -1
- package/dist/utils/store-to-api-docs-converter.js +16 -2
- package/dist/utils/store-to-api-docs-converter.js.map +1 -1
- package/package.json +5 -5
- package/src/content-store-types.ts +9 -4
- package/src/content-store.ts +29 -45
- package/src/utils/create-update-csi-docs.ts +11 -0
- package/src/utils/csi-to-store-docs-converter.ts +20 -0
- package/src/utils/duplicate-document.ts +254 -0
- package/src/utils/store-to-api-docs-converter.ts +16 -2
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
|
|
3
|
+
import * as ContentStoreTypes from '../content-store-types';
|
|
4
|
+
import { getDocumentFieldForLocale } from '../content-store-utils';
|
|
5
|
+
import { IMAGE_MODEL } from '../common/common-schema';
|
|
6
|
+
|
|
7
|
+
export function mergeObjectWithDocument({
|
|
8
|
+
object,
|
|
9
|
+
document,
|
|
10
|
+
locale,
|
|
11
|
+
documentMap,
|
|
12
|
+
seenReferences = [],
|
|
13
|
+
referenceBehavior,
|
|
14
|
+
duplicatableModels,
|
|
15
|
+
nonDuplicatableModels
|
|
16
|
+
}: {
|
|
17
|
+
object: Record<string, any> | undefined;
|
|
18
|
+
document: ContentStoreTypes.Document;
|
|
19
|
+
locale?: string;
|
|
20
|
+
documentMap: Record<string, ContentStoreTypes.Document>;
|
|
21
|
+
seenReferences?: string[];
|
|
22
|
+
referenceBehavior?: 'copyReference' | 'duplicateContents';
|
|
23
|
+
duplicatableModels?: string[];
|
|
24
|
+
nonDuplicatableModels?: string[];
|
|
25
|
+
}): Record<string, any> {
|
|
26
|
+
return mergeObjectWithDocumentFields({
|
|
27
|
+
object,
|
|
28
|
+
documentFields: document.fields,
|
|
29
|
+
locale,
|
|
30
|
+
documentMap,
|
|
31
|
+
seenReferences: seenReferences.concat(document.srcObjectId),
|
|
32
|
+
referenceBehavior,
|
|
33
|
+
duplicatableModels,
|
|
34
|
+
nonDuplicatableModels
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type Context = {
|
|
39
|
+
locale?: string;
|
|
40
|
+
documentMap: Record<string, ContentStoreTypes.Document>;
|
|
41
|
+
seenReferences: string[];
|
|
42
|
+
referenceBehavior?: 'copyReference' | 'duplicateContents';
|
|
43
|
+
duplicatableModels?: string[];
|
|
44
|
+
nonDuplicatableModels?: string[];
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
function mergeObjectWithDocumentFields({
|
|
48
|
+
object,
|
|
49
|
+
documentFields,
|
|
50
|
+
...context
|
|
51
|
+
}: {
|
|
52
|
+
object: Record<string, any> | undefined;
|
|
53
|
+
documentFields: Record<string, ContentStoreTypes.DocumentField>;
|
|
54
|
+
} & Context): Record<string, any> {
|
|
55
|
+
return _.reduce(
|
|
56
|
+
documentFields,
|
|
57
|
+
(object, documentField, fieldName) => {
|
|
58
|
+
const value = mergeObjectWithDocumentField({
|
|
59
|
+
value: object[fieldName],
|
|
60
|
+
documentField,
|
|
61
|
+
...context
|
|
62
|
+
});
|
|
63
|
+
if (typeof value !== 'undefined') {
|
|
64
|
+
object[fieldName] = value;
|
|
65
|
+
}
|
|
66
|
+
return object;
|
|
67
|
+
},
|
|
68
|
+
Object.assign({}, object)
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function mergeObjectWithDocumentField({
|
|
73
|
+
value,
|
|
74
|
+
documentField,
|
|
75
|
+
...context
|
|
76
|
+
}: {
|
|
77
|
+
value: any;
|
|
78
|
+
documentField: ContentStoreTypes.DocumentField;
|
|
79
|
+
} & Context): any {
|
|
80
|
+
const locale = context.locale;
|
|
81
|
+
switch (documentField.type) {
|
|
82
|
+
case 'string':
|
|
83
|
+
case 'text':
|
|
84
|
+
case 'html':
|
|
85
|
+
case 'slug':
|
|
86
|
+
case 'url':
|
|
87
|
+
case 'color':
|
|
88
|
+
case 'boolean':
|
|
89
|
+
case 'number':
|
|
90
|
+
case 'date':
|
|
91
|
+
case 'datetime':
|
|
92
|
+
case 'enum':
|
|
93
|
+
case 'file':
|
|
94
|
+
case 'json':
|
|
95
|
+
case 'style':
|
|
96
|
+
case 'markdown':
|
|
97
|
+
case 'richText': {
|
|
98
|
+
// if a value was provided explicitly, use it to override the value
|
|
99
|
+
// of the matching field in the duplicated document.
|
|
100
|
+
if (typeof value !== 'undefined') {
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
const localizedField = getDocumentFieldForLocale(documentField, locale);
|
|
104
|
+
if (localizedField) {
|
|
105
|
+
return localizedField.value;
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
case 'image': {
|
|
110
|
+
const localizedField = getDocumentFieldForLocale(documentField, locale);
|
|
111
|
+
if (localizedField && !localizedField.isUnset) {
|
|
112
|
+
return mergeObjectWithDocumentFields({
|
|
113
|
+
object: value,
|
|
114
|
+
documentFields: localizedField.fields,
|
|
115
|
+
...context
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case 'object': {
|
|
121
|
+
const localizedField = getDocumentFieldForLocale(documentField, locale);
|
|
122
|
+
if (localizedField && !localizedField.isUnset) {
|
|
123
|
+
return mergeObjectWithDocumentFields({
|
|
124
|
+
object: value,
|
|
125
|
+
documentFields: localizedField.fields,
|
|
126
|
+
...context
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
case 'model': {
|
|
132
|
+
const localizedField = getDocumentFieldForLocale(documentField, locale);
|
|
133
|
+
if (localizedField && !localizedField.isUnset) {
|
|
134
|
+
if (value && value.$$type !== localizedField.srcModelName) {
|
|
135
|
+
// if the override object's $$type isn't equal to the type
|
|
136
|
+
// of the current object in the field, then use whatever
|
|
137
|
+
// was passed in the object.
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
$$type: localizedField.srcModelName,
|
|
142
|
+
...mergeObjectWithDocumentFields({
|
|
143
|
+
object: value,
|
|
144
|
+
documentFields: localizedField.fields,
|
|
145
|
+
...context
|
|
146
|
+
})
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
case 'reference': {
|
|
152
|
+
const localizedField = getDocumentFieldForLocale(documentField, locale);
|
|
153
|
+
if (localizedField && !localizedField.isUnset) {
|
|
154
|
+
if (value && value.$$ref) {
|
|
155
|
+
// if the override object has $$ref, use it
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
if (localizedField.refType === 'asset') {
|
|
159
|
+
return {
|
|
160
|
+
$$ref: localizedField.refId
|
|
161
|
+
};
|
|
162
|
+
} else {
|
|
163
|
+
const document = context.documentMap[localizedField.refId];
|
|
164
|
+
if (!document) {
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
const shouldDuplicateDocument = shouldDuplicate({
|
|
168
|
+
referenceField: localizedField,
|
|
169
|
+
modelName: document.srcModelName,
|
|
170
|
+
seenReferences: context.seenReferences,
|
|
171
|
+
referenceBehavior: context.referenceBehavior,
|
|
172
|
+
duplicatableModels: context.duplicatableModels,
|
|
173
|
+
nonDuplicatableModels: context.nonDuplicatableModels
|
|
174
|
+
});
|
|
175
|
+
if (shouldDuplicateDocument || (value && value.$$type)) {
|
|
176
|
+
if (value && value.$$type !== document.srcModelName) {
|
|
177
|
+
// if the override object has $$type different from
|
|
178
|
+
// the type of the document that is currently
|
|
179
|
+
// referenced in the field, then create and link a
|
|
180
|
+
// new document according to the provided object
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
$$type: document.srcModelName,
|
|
185
|
+
...mergeObjectWithDocument({
|
|
186
|
+
object: value,
|
|
187
|
+
document,
|
|
188
|
+
locale: context.locale,
|
|
189
|
+
documentMap: context.documentMap,
|
|
190
|
+
seenReferences: context.seenReferences.concat(document.srcObjectId),
|
|
191
|
+
referenceBehavior: context.referenceBehavior,
|
|
192
|
+
duplicatableModels: context.duplicatableModels,
|
|
193
|
+
nonDuplicatableModels: context.nonDuplicatableModels
|
|
194
|
+
})
|
|
195
|
+
};
|
|
196
|
+
} else {
|
|
197
|
+
return {
|
|
198
|
+
$$ref: localizedField.refId
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
case 'list': {
|
|
206
|
+
const localizedField = getDocumentFieldForLocale(documentField, locale);
|
|
207
|
+
if (value) {
|
|
208
|
+
// do not try to merge provided list items with existing items
|
|
209
|
+
// because array items can not be matched by names like fields do.
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
if (localizedField) {
|
|
213
|
+
return (localizedField.items ?? []).map((field) =>
|
|
214
|
+
mergeObjectWithDocumentField({
|
|
215
|
+
value: undefined,
|
|
216
|
+
documentField: field,
|
|
217
|
+
...context
|
|
218
|
+
})
|
|
219
|
+
).filter((value) => typeof value !== 'undefined') // if locale passed, it may return undefined for items localized to a different locale;
|
|
220
|
+
}
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
default: {
|
|
224
|
+
const _exhaustiveCheck: never = documentField;
|
|
225
|
+
return _exhaustiveCheck;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// if the document value was not set and no merging occurred use the value
|
|
229
|
+
// that was provided to override the field in the duplicated document
|
|
230
|
+
return value;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function shouldDuplicate({
|
|
234
|
+
referenceField,
|
|
235
|
+
modelName,
|
|
236
|
+
seenReferences,
|
|
237
|
+
referenceBehavior,
|
|
238
|
+
nonDuplicatableModels,
|
|
239
|
+
duplicatableModels
|
|
240
|
+
}: {
|
|
241
|
+
referenceField: ContentStoreTypes.DocumentReferenceFieldNonLocalized & { isUnset?: false };
|
|
242
|
+
modelName: string;
|
|
243
|
+
seenReferences: string[];
|
|
244
|
+
referenceBehavior?: 'copyReference' | 'duplicateContents';
|
|
245
|
+
nonDuplicatableModels?: string[];
|
|
246
|
+
duplicatableModels?: string[];
|
|
247
|
+
}) {
|
|
248
|
+
return (
|
|
249
|
+
!seenReferences.includes(referenceField.refId) &&
|
|
250
|
+
modelName !== IMAGE_MODEL.name &&
|
|
251
|
+
((referenceBehavior === 'duplicateContents' && !(nonDuplicatableModels ?? []).includes(modelName)) ||
|
|
252
|
+
(referenceBehavior === 'copyReference' && (duplicatableModels ?? []).includes(modelName)))
|
|
253
|
+
);
|
|
254
|
+
}
|
|
@@ -70,12 +70,26 @@ function toLocalizedAPIField(docField: ContentStoreTypes.DocumentField, locale?:
|
|
|
70
70
|
const localeProps = locale ? locales[locale] : undefined;
|
|
71
71
|
return {
|
|
72
72
|
...base,
|
|
73
|
-
...(localeProps
|
|
73
|
+
...(localeProps
|
|
74
|
+
? {
|
|
75
|
+
...localeProps,
|
|
76
|
+
fields: toLocalizedAPIFields(localeProps.fields, locale) as ContentStoreTypes.ImageFieldsAPI
|
|
77
|
+
}
|
|
78
|
+
: { isUnset: true }),
|
|
74
79
|
...localeFields(localized, locale)
|
|
75
80
|
};
|
|
76
81
|
}
|
|
77
82
|
return {
|
|
78
|
-
...docField
|
|
83
|
+
...(!docField.isUnset
|
|
84
|
+
? {
|
|
85
|
+
...docField,
|
|
86
|
+
type: 'image',
|
|
87
|
+
fields: toLocalizedAPIFields(docField.fields, locale) as ContentStoreTypes.ImageFieldsAPI
|
|
88
|
+
}
|
|
89
|
+
: {
|
|
90
|
+
...docField,
|
|
91
|
+
type: 'image'
|
|
92
|
+
}),
|
|
79
93
|
...localeFields(docField.localized, docField.locale)
|
|
80
94
|
};
|
|
81
95
|
case 'object':
|