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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/content-source-interface.d.ts +9 -14
  2. package/dist/content-source-interface.d.ts.map +1 -1
  3. package/dist/content-source-interface.js.map +1 -1
  4. package/dist/content-store-types.d.ts +25 -24
  5. package/dist/content-store-types.d.ts.map +1 -1
  6. package/dist/content-store-utils.d.ts +9 -0
  7. package/dist/content-store-utils.d.ts.map +1 -0
  8. package/dist/content-store-utils.js +139 -0
  9. package/dist/content-store-utils.js.map +1 -0
  10. package/dist/content-store.d.ts +17 -4
  11. package/dist/content-store.d.ts.map +1 -1
  12. package/dist/content-store.js +147 -949
  13. package/dist/content-store.js.map +1 -1
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/types/search-filter.d.ts +42 -0
  19. package/dist/types/search-filter.d.ts.map +1 -0
  20. package/dist/types/search-filter.js +3 -0
  21. package/dist/types/search-filter.js.map +1 -0
  22. package/dist/utils/create-update-csi-docs.d.ts +68 -0
  23. package/dist/utils/create-update-csi-docs.d.ts.map +1 -0
  24. package/dist/utils/create-update-csi-docs.js +376 -0
  25. package/dist/utils/create-update-csi-docs.js.map +1 -0
  26. package/dist/utils/csi-to-store-docs-converter.d.ts +15 -0
  27. package/dist/utils/csi-to-store-docs-converter.d.ts.map +1 -0
  28. package/dist/utils/csi-to-store-docs-converter.js +287 -0
  29. package/dist/utils/csi-to-store-docs-converter.js.map +1 -0
  30. package/dist/utils/search-utils.d.ts +21 -0
  31. package/dist/utils/search-utils.d.ts.map +1 -0
  32. package/dist/utils/search-utils.js +323 -0
  33. package/dist/utils/search-utils.js.map +1 -0
  34. package/dist/utils/store-to-api-docs-converter.d.ts +5 -0
  35. package/dist/utils/store-to-api-docs-converter.d.ts.map +1 -0
  36. package/dist/utils/store-to-api-docs-converter.js +247 -0
  37. package/dist/utils/store-to-api-docs-converter.js.map +1 -0
  38. package/package.json +6 -5
  39. package/src/content-source-interface.ts +6 -15
  40. package/src/content-store-types.ts +23 -10
  41. package/src/content-store-utils.ts +149 -0
  42. package/src/content-store.ts +137 -1079
  43. package/src/index.ts +3 -1
  44. package/src/types/search-filter.ts +53 -0
  45. package/src/utils/create-update-csi-docs.ts +440 -0
  46. package/src/utils/csi-to-store-docs-converter.ts +365 -0
  47. package/src/utils/search-utils.ts +436 -0
  48. package/src/utils/store-to-api-docs-converter.ts +246 -0
@@ -0,0 +1,365 @@
1
+ import _ from 'lodash';
2
+ import { Field, FieldListProps, FieldModelProps, FieldObjectProps, FieldSpecificProps, Model } from '@stackbit/sdk';
3
+ import { isLocalizedField } from '../content-source-interface';
4
+ import * as CSITypes from '../content-source-interface';
5
+ import * as ContentStoreTypes from '../content-store-types';
6
+ import { IMAGE_MODEL } from '../common/common-schema';
7
+
8
+ export function mapCSIAssetsToStoreAssets({
9
+ csiAssets,
10
+ contentSourceInstance,
11
+ defaultLocaleCode
12
+ }: {
13
+ csiAssets: CSITypes.Asset[];
14
+ contentSourceInstance: CSITypes.ContentSourceInterface;
15
+ defaultLocaleCode?: string;
16
+ }): ContentStoreTypes.Asset[] {
17
+ const extra = getMetadataFromContentStore({ contentSourceInstance });
18
+ return csiAssets.map((csiAsset) =>
19
+ sourceAssetToStoreAsset({
20
+ csiAsset,
21
+ defaultLocaleCode,
22
+ extra
23
+ })
24
+ );
25
+ }
26
+
27
+ function sourceAssetToStoreAsset({
28
+ csiAsset,
29
+ defaultLocaleCode,
30
+ extra
31
+ }: {
32
+ csiAsset: CSITypes.Asset;
33
+ defaultLocaleCode?: string;
34
+ extra: { srcType: string; srcProjectId: string; srcProjectUrl: string; srcEnvironment: string };
35
+ }): ContentStoreTypes.Asset {
36
+ return {
37
+ type: 'asset',
38
+ ...extra,
39
+ srcObjectId: csiAsset.id,
40
+ srcObjectUrl: csiAsset.manageUrl,
41
+ srcObjectLabel: getObjectLabel(csiAsset.fields, IMAGE_MODEL, defaultLocaleCode),
42
+ srcModelName: IMAGE_MODEL.name,
43
+ srcModelLabel: IMAGE_MODEL.label!,
44
+ isChanged: csiAsset.status === 'added' || csiAsset.status === 'modified',
45
+ status: csiAsset.status,
46
+ createdAt: csiAsset.createdAt,
47
+ createdBy: csiAsset.createdBy,
48
+ updatedAt: csiAsset.updatedAt,
49
+ updatedBy: csiAsset.updatedBy,
50
+ fields: {
51
+ title: {
52
+ label: 'Title',
53
+ ...csiAsset.fields.title
54
+ },
55
+ file: {
56
+ label: 'File',
57
+ ...csiAsset.fields.file
58
+ }
59
+ }
60
+ };
61
+ }
62
+
63
+ export function mapCSIDocumentsToStoreDocuments({
64
+ csiDocuments,
65
+ contentSourceInstance,
66
+ modelMap,
67
+ defaultLocaleCode
68
+ }: {
69
+ csiDocuments: CSITypes.Document[];
70
+ contentSourceInstance: CSITypes.ContentSourceInterface;
71
+ modelMap: Record<string, Model>;
72
+ defaultLocaleCode?: string;
73
+ }): ContentStoreTypes.Document[] {
74
+ const extra = getMetadataFromContentStore({ contentSourceInstance });
75
+ return csiDocuments.map((csiDocument) =>
76
+ mapCSIDocumentToStoreDocument({
77
+ csiDocument,
78
+ model: modelMap[csiDocument.modelName]!,
79
+ modelMap,
80
+ defaultLocaleCode,
81
+ extra
82
+ })
83
+ );
84
+ }
85
+
86
+ function mapCSIDocumentToStoreDocument({
87
+ csiDocument,
88
+ model,
89
+ modelMap,
90
+ defaultLocaleCode,
91
+ extra
92
+ }: {
93
+ csiDocument: CSITypes.Document;
94
+ model: Model;
95
+ modelMap: Record<string, Model>;
96
+ defaultLocaleCode?: string;
97
+ extra: { srcType: string; srcProjectId: string; srcProjectUrl: string; srcEnvironment: string };
98
+ }): ContentStoreTypes.Document {
99
+ return {
100
+ type: 'document',
101
+ ...extra,
102
+ srcObjectId: csiDocument.id,
103
+ srcObjectUrl: csiDocument.manageUrl,
104
+ srcObjectLabel: getObjectLabel(csiDocument.fields, model, defaultLocaleCode),
105
+ srcModelLabel: model.label ?? _.startCase(csiDocument.modelName),
106
+ srcModelName: csiDocument.modelName,
107
+ isChanged: csiDocument.status === 'added' || csiDocument.status === 'modified',
108
+ status: csiDocument.status,
109
+ createdAt: csiDocument.createdAt,
110
+ createdBy: csiDocument.createdBy,
111
+ updatedAt: csiDocument.updatedAt,
112
+ updatedBy: csiDocument.updatedBy,
113
+ fields: mapCSIFieldsToStoreFields({
114
+ csiDocumentFields: csiDocument.fields,
115
+ modelFields: model.fields ?? [],
116
+ context: {
117
+ modelMap,
118
+ defaultLocaleCode
119
+ }
120
+ })
121
+ };
122
+ }
123
+
124
+ type MapContext = {
125
+ modelMap: Record<string, Model>;
126
+ defaultLocaleCode?: string;
127
+ };
128
+
129
+ function mapCSIFieldsToStoreFields({
130
+ csiDocumentFields,
131
+ modelFields,
132
+ context
133
+ }: {
134
+ csiDocumentFields: Record<string, CSITypes.DocumentField>;
135
+ modelFields: Field[];
136
+ context: MapContext;
137
+ }): Record<string, ContentStoreTypes.DocumentField> {
138
+ return modelFields.reduce((result: Record<string, ContentStoreTypes.DocumentField>, modelField) => {
139
+ const csiDocumentField = csiDocumentFields[modelField.name];
140
+ const docField = mapCSIFieldToStoreField({
141
+ csiDocumentField,
142
+ modelField,
143
+ context
144
+ });
145
+ docField.label = modelField.label;
146
+ result[modelField.name] = docField;
147
+ return result;
148
+ }, {});
149
+ }
150
+
151
+ function mapCSIFieldToStoreField({
152
+ csiDocumentField,
153
+ modelField,
154
+ context
155
+ }: {
156
+ csiDocumentField: CSITypes.DocumentField | undefined;
157
+ modelField: FieldSpecificProps;
158
+ context: MapContext;
159
+ }): ContentStoreTypes.DocumentField {
160
+ if (!csiDocumentField) {
161
+ const isUnset = ['object', 'model', 'reference', 'richText', 'markdown', 'image', 'file', 'json'].includes(modelField.type);
162
+ return {
163
+ type: modelField.type,
164
+ ...(isUnset ? { isUnset } : null),
165
+ ...(modelField.type === 'list' ? { items: [] } : null)
166
+ } as ContentStoreTypes.DocumentField;
167
+ }
168
+ // TODO: check if need to add "options" to "enum" and subtype/min/max to "number"
169
+ switch (modelField.type) {
170
+ case 'object':
171
+ return mapObjectField(csiDocumentField as CSITypes.DocumentObjectField, modelField, context);
172
+ case 'model':
173
+ return mapModelField(csiDocumentField as CSITypes.DocumentModelField, modelField, context);
174
+ case 'list':
175
+ return mapListField(csiDocumentField as CSITypes.DocumentListField, modelField, context);
176
+ case 'richText':
177
+ return mapRichTextField(csiDocumentField as CSITypes.DocumentRichTextField);
178
+ case 'markdown':
179
+ return mapMarkdownField(csiDocumentField as CSITypes.DocumentValueField);
180
+ default:
181
+ return csiDocumentField as ContentStoreTypes.DocumentField;
182
+ }
183
+ }
184
+
185
+ function mapObjectField(
186
+ csiDocumentField: CSITypes.DocumentObjectField,
187
+ modelField: FieldObjectProps,
188
+ context: MapContext
189
+ ): ContentStoreTypes.DocumentObjectField {
190
+ if (!isLocalizedField(csiDocumentField)) {
191
+ return {
192
+ type: csiDocumentField.type,
193
+ srcObjectLabel: getObjectLabel(csiDocumentField.fields ?? {}, modelField ?? [], context.defaultLocaleCode),
194
+ fields: mapCSIFieldsToStoreFields({
195
+ csiDocumentFields: csiDocumentField.fields ?? {},
196
+ modelFields: modelField.fields ?? [],
197
+ context
198
+ })
199
+ };
200
+ }
201
+ return {
202
+ type: csiDocumentField.type,
203
+ localized: true,
204
+ locales: _.mapValues(csiDocumentField.locales, (locale) => {
205
+ return {
206
+ locale: locale.locale,
207
+ srcObjectLabel: getObjectLabel(locale.fields ?? {}, modelField, locale.locale),
208
+ fields: mapCSIFieldsToStoreFields({
209
+ csiDocumentFields: locale.fields ?? {},
210
+ modelFields: modelField.fields ?? [],
211
+ context
212
+ })
213
+ };
214
+ })
215
+ };
216
+ }
217
+
218
+ function mapModelField(csiDocumentField: CSITypes.DocumentModelField, modelField: FieldModelProps, context: MapContext): ContentStoreTypes.DocumentModelField {
219
+ if (!isLocalizedField(csiDocumentField)) {
220
+ const model = context.modelMap[csiDocumentField.modelName]!;
221
+ return {
222
+ type: csiDocumentField.type,
223
+ srcObjectLabel: getObjectLabel(csiDocumentField.fields ?? {}, model, context.defaultLocaleCode),
224
+ srcModelName: csiDocumentField.modelName,
225
+ srcModelLabel: model.label ?? _.startCase(model.name),
226
+ fields: mapCSIFieldsToStoreFields({
227
+ csiDocumentFields: csiDocumentField.fields ?? {},
228
+ modelFields: model.fields ?? [],
229
+ context
230
+ })
231
+ };
232
+ }
233
+ return {
234
+ type: csiDocumentField.type,
235
+ localized: true,
236
+ locales: _.mapValues(csiDocumentField.locales, (locale) => {
237
+ const model = context.modelMap[locale.modelName]!;
238
+ return {
239
+ locale: locale.locale,
240
+ srcObjectLabel: getObjectLabel(locale.fields ?? {}, model, locale.locale),
241
+ srcModelName: locale.modelName,
242
+ srcModelLabel: model.label ?? _.startCase(model.name),
243
+ fields: mapCSIFieldsToStoreFields({
244
+ csiDocumentFields: locale.fields ?? {},
245
+ modelFields: model.fields ?? [],
246
+ context
247
+ })
248
+ };
249
+ })
250
+ };
251
+ }
252
+
253
+ function mapListField(csiDocumentField: CSITypes.DocumentListField, modelField: FieldListProps, context: MapContext): ContentStoreTypes.DocumentListField {
254
+ if (!isLocalizedField(csiDocumentField)) {
255
+ return {
256
+ type: csiDocumentField.type,
257
+ items: csiDocumentField.items.map((item) =>
258
+ mapCSIFieldToStoreField({
259
+ csiDocumentField: item,
260
+ modelField: modelField.items ?? { type: 'string' },
261
+ context
262
+ })
263
+ )
264
+ };
265
+ }
266
+ return {
267
+ type: csiDocumentField.type,
268
+ localized: true,
269
+ locales: _.mapValues(csiDocumentField.locales, (locale) => {
270
+ return {
271
+ locale: locale.locale,
272
+ items: (locale.items ?? []).map((item) =>
273
+ mapCSIFieldToStoreField({
274
+ csiDocumentField: item,
275
+ modelField: modelField.items ?? { type: 'string' },
276
+ context
277
+ })
278
+ )
279
+ };
280
+ })
281
+ };
282
+ }
283
+
284
+ function mapRichTextField(csiDocumentField: CSITypes.DocumentRichTextField): ContentStoreTypes.DocumentRichTextField {
285
+ if (!isLocalizedField(csiDocumentField)) {
286
+ return {
287
+ ...csiDocumentField,
288
+ multiElement: true
289
+ };
290
+ }
291
+ return {
292
+ type: csiDocumentField.type,
293
+ localized: true,
294
+ locales: _.mapValues(csiDocumentField.locales, (locale) => {
295
+ return {
296
+ ...locale,
297
+ multiElement: true
298
+ };
299
+ })
300
+ };
301
+ }
302
+
303
+ function mapMarkdownField(csiDocumentField: CSITypes.DocumentValueField): ContentStoreTypes.DocumentMarkdownField {
304
+ if (!isLocalizedField(csiDocumentField)) {
305
+ return {
306
+ type: 'markdown',
307
+ value: csiDocumentField.value,
308
+ multiElement: true
309
+ };
310
+ }
311
+ return {
312
+ type: 'markdown',
313
+ localized: true,
314
+ locales: _.mapValues(csiDocumentField.locales, (locale) => {
315
+ return {
316
+ ...locale,
317
+ multiElement: true
318
+ };
319
+ })
320
+ };
321
+ }
322
+
323
+ function getMetadataFromContentStore({
324
+ contentSourceInstance
325
+ }: {
326
+ contentSourceInstance: CSITypes.ContentSourceInterface;
327
+ }): {
328
+ srcType: string;
329
+ srcProjectId: string;
330
+ srcProjectUrl: string;
331
+ srcEnvironment: string;
332
+ } {
333
+ return {
334
+ srcType: contentSourceInstance.getContentSourceType(),
335
+ srcProjectId: contentSourceInstance.getProjectId(),
336
+ srcProjectUrl: contentSourceInstance.getProjectManageUrl(),
337
+ srcEnvironment: contentSourceInstance.getProjectEnvironment()
338
+ };
339
+ }
340
+
341
+ function getObjectLabel(
342
+ documentFields: Record<string, CSITypes.DocumentField | CSITypes.AssetFileField>,
343
+ modelOrObjectField: Model | FieldObjectProps,
344
+ locale?: string
345
+ ): string {
346
+ const labelField = modelOrObjectField.labelField;
347
+ let label = null;
348
+ if (labelField) {
349
+ const field = _.get(documentFields, labelField, null);
350
+ if (field && ['string', 'url', 'slug', 'text', 'markdown', 'number', 'enum', 'date', 'datetime', 'color', 'image', 'file'].includes(field.type)) {
351
+ if (isLocalizedField(field) && locale) {
352
+ label = _.get(field, ['locales', locale, 'value'], null);
353
+ } else if (!isLocalizedField(field)) {
354
+ label = _.get(field, 'value', null);
355
+ }
356
+ }
357
+ }
358
+ if (!label) {
359
+ label = _.get(modelOrObjectField, 'label');
360
+ }
361
+ if (!label && _.has(modelOrObjectField, 'name')) {
362
+ label = _.startCase(_.get(modelOrObjectField, 'name'));
363
+ }
364
+ return label;
365
+ }