@stackbit/cms-core 0.1.1 → 0.1.3-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 (34) hide show
  1. package/dist/content-source-interface.d.ts +3 -11
  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 +15 -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 +0 -1
  11. package/dist/content-store.d.ts.map +1 -1
  12. package/dist/content-store.js +99 -945
  13. package/dist/content-store.js.map +1 -1
  14. package/dist/utils/create-update-csi-docs.d.ts +68 -0
  15. package/dist/utils/create-update-csi-docs.d.ts.map +1 -0
  16. package/dist/utils/create-update-csi-docs.js +376 -0
  17. package/dist/utils/create-update-csi-docs.js.map +1 -0
  18. package/dist/utils/csi-to-store-docs-converter.d.ts +15 -0
  19. package/dist/utils/csi-to-store-docs-converter.d.ts.map +1 -0
  20. package/dist/utils/csi-to-store-docs-converter.js +287 -0
  21. package/dist/utils/csi-to-store-docs-converter.js.map +1 -0
  22. package/dist/utils/store-to-api-docs-converter.d.ts +5 -0
  23. package/dist/utils/store-to-api-docs-converter.d.ts.map +1 -0
  24. package/dist/utils/store-to-api-docs-converter.js +247 -0
  25. package/dist/utils/store-to-api-docs-converter.js.map +1 -0
  26. package/package.json +4 -4
  27. package/src/content-source-interface.ts +4 -13
  28. package/src/content-store-types.ts +12 -10
  29. package/src/content-store-utils.ts +149 -0
  30. package/src/content-store.ts +57 -1073
  31. package/src/index.ts +1 -1
  32. package/src/utils/create-update-csi-docs.ts +440 -0
  33. package/src/utils/csi-to-store-docs-converter.ts +365 -0
  34. 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
+ }
@@ -0,0 +1,246 @@
1
+ import _ from 'lodash';
2
+ import { omitByNil } from '@stackbit/utils';
3
+ import * as ContentStoreTypes from '../content-store-types';
4
+ import { getDocumentFieldForLocale } from '../content-store-utils';
5
+
6
+ export function mapDocumentsToLocalizedApiObjects(documents: ContentStoreTypes.Document[], locale?: string): ContentStoreTypes.APIDocumentObject[] {
7
+ return documents.map((document) => documentToLocalizedApiObject(document, locale));
8
+ }
9
+
10
+ function documentToLocalizedApiObject(document: ContentStoreTypes.Document, locale?: string): ContentStoreTypes.APIDocumentObject {
11
+ const { type, fields, ...rest } = document;
12
+ return {
13
+ type: 'object',
14
+ ...rest,
15
+ fields: toLocalizedAPIFields(fields, locale)
16
+ };
17
+ }
18
+
19
+ function toLocalizedAPIFields(docFields: Record<string, ContentStoreTypes.DocumentField>, locale?: string): Record<string, ContentStoreTypes.DocumentFieldAPI> {
20
+ return _.mapValues(docFields, (docField) => toLocalizedAPIField(docField, locale));
21
+ }
22
+
23
+ function toLocalizedAPIField(docField: ContentStoreTypes.DocumentField, locale?: string, isListItem = false): ContentStoreTypes.DocumentFieldAPI {
24
+ type ToBoolean<T extends boolean | undefined> = T extends true ? true : false;
25
+ function localeFields<T extends boolean | undefined>(
26
+ localized: T,
27
+ _locale: string | undefined
28
+ ): null | { localized: ToBoolean<T>; locale: string | undefined } {
29
+ return isListItem
30
+ ? null
31
+ : {
32
+ localized: !!localized as ToBoolean<T>,
33
+ locale: locale ?? _locale
34
+ };
35
+ }
36
+ switch (docField.type) {
37
+ case 'string':
38
+ case 'text':
39
+ case 'url':
40
+ case 'slug':
41
+ case 'html':
42
+ case 'number':
43
+ case 'boolean':
44
+ case 'enum':
45
+ case 'date':
46
+ case 'datetime':
47
+ case 'color':
48
+ case 'style':
49
+ case 'file':
50
+ case 'json':
51
+ case 'markdown':
52
+ case 'richText':
53
+ if (docField.localized) {
54
+ const { localized, locales, ...base } = docField;
55
+ const localeProps = locale ? locales[locale] : undefined;
56
+ return {
57
+ ...base,
58
+ ...(localeProps ?? { value: null }),
59
+ ...localeFields(localized, locale),
60
+ ...(['file', 'json', 'markdown', 'richText'].includes(docField.type) && !localeProps ? { isUnset: true } : null)
61
+ };
62
+ }
63
+ return {
64
+ ...docField,
65
+ ...localeFields(docField.localized, docField.locale)
66
+ };
67
+ case 'image':
68
+ if (docField.localized) {
69
+ const { localized, locales, ...base } = docField;
70
+ const localeProps = locale ? locales[locale] : undefined;
71
+ return {
72
+ ...base,
73
+ ...(localeProps ?? { isUnset: true }),
74
+ ...localeFields(localized, locale)
75
+ };
76
+ }
77
+ return {
78
+ ...docField,
79
+ ...localeFields(docField.localized, docField.locale)
80
+ };
81
+ case 'object':
82
+ case 'model':
83
+ if (docField.localized) {
84
+ if (docField.type === 'object') {
85
+ const { localized, locales, ...base } = docField;
86
+ const localeProps = locale ? locales[locale] : undefined;
87
+ return {
88
+ ...base,
89
+ ...(localeProps
90
+ ? {
91
+ ...localeProps,
92
+ fields: toLocalizedAPIFields(localeProps.fields, locale)
93
+ }
94
+ : { isUnset: true }),
95
+ ...localeFields(localized, locale)
96
+ };
97
+ } else {
98
+ const { localized, locales, ...base } = docField;
99
+ const localeProps = locale ? locales[locale] : undefined;
100
+ return {
101
+ ...base,
102
+ type: 'object',
103
+ ...(localeProps
104
+ ? {
105
+ ...localeProps,
106
+ fields: toLocalizedAPIFields(localeProps.fields, locale)
107
+ }
108
+ : { isUnset: true }),
109
+ ...localeFields(localized, locale)
110
+ };
111
+ }
112
+ }
113
+ return {
114
+ ...(!docField.isUnset
115
+ ? {
116
+ ...docField,
117
+ type: 'object',
118
+ fields: toLocalizedAPIFields(docField.fields, locale)
119
+ }
120
+ : {
121
+ ...docField,
122
+ type: 'object'
123
+ }),
124
+ ...localeFields(docField.localized, docField.locale)
125
+ };
126
+ case 'reference':
127
+ if (docField.localized) {
128
+ const { type, refType, localized, locales, ...base } = docField;
129
+ const localeProps = locale ? locales[locale] : undefined;
130
+ // if reference field isUnset === true, it behaves like a regular object
131
+ if (!localeProps || localeProps.isUnset) {
132
+ return {
133
+ type: 'object',
134
+ isUnset: true,
135
+ ...base,
136
+ ...localeFields(localized, locale)
137
+ };
138
+ }
139
+ return {
140
+ type: 'unresolved_reference',
141
+ refType: refType === 'asset' ? 'image' : 'object',
142
+ ...base,
143
+ ...localeProps,
144
+ ...localeFields(localized, locale)
145
+ };
146
+ }
147
+ const { type, refType, ...base } = docField;
148
+ if (base.isUnset) {
149
+ return {
150
+ type: 'object',
151
+ ...base,
152
+ ...localeFields(docField.localized, docField.locale)
153
+ };
154
+ }
155
+ return {
156
+ type: 'unresolved_reference',
157
+ refType: refType === 'asset' ? 'image' : 'object',
158
+ ...base,
159
+ ...localeFields(docField.localized, docField.locale)
160
+ };
161
+ case 'list':
162
+ if (docField.localized) {
163
+ const { localized, locales, ...base } = docField;
164
+ const localeProps = locale ? locales[locale] : undefined;
165
+ return {
166
+ ...base,
167
+ ...localeProps,
168
+ items: (localeProps?.items ?? []).map((field) => toLocalizedAPIField(field, locale, true)),
169
+ ...localeFields(localized, locale)
170
+ };
171
+ }
172
+ return {
173
+ ...docField,
174
+ ...localeFields(docField.localized, docField.locale),
175
+ items: docField.items.map((field) => toLocalizedAPIField(field, locale, true))
176
+ };
177
+ default:
178
+ const _exhaustiveCheck: never = docField;
179
+ console.error(`toLocalizedAPIField _exhaustiveCheck failed, docField.type: ${docField['type']}`);
180
+ return _exhaustiveCheck;
181
+ }
182
+ }
183
+
184
+ export function mapAssetsToLocalizedApiImages(assets: ContentStoreTypes.Asset[], locale?: string): ContentStoreTypes.APIImageObject[] {
185
+ return assets.map((asset) => assetToLocalizedApiImage(asset, locale));
186
+ }
187
+
188
+ function assetToLocalizedApiImage(asset: ContentStoreTypes.Asset, locale?: string): ContentStoreTypes.APIImageObject {
189
+ const { type, fields, ...rest } = asset;
190
+ return {
191
+ type: 'image',
192
+ ...rest,
193
+ fields: localizeAssetFields(fields, locale)
194
+ };
195
+ }
196
+
197
+ function localizeAssetFields(assetFields: ContentStoreTypes.AssetFields, locale?: string): ContentStoreTypes.AssetFieldsAPI {
198
+ const fields: ContentStoreTypes.AssetFieldsAPI = {
199
+ title: {
200
+ type: 'string' as const,
201
+ value: null as any
202
+ },
203
+ url: {
204
+ type: 'string' as const,
205
+ value: null as any
206
+ }
207
+ };
208
+ const titleFieldNonLocalized = getDocumentFieldForLocale(assetFields.title, locale);
209
+ fields.title.value = titleFieldNonLocalized?.value;
210
+ fields.title.locale = locale ?? titleFieldNonLocalized?.locale;
211
+ const assetFileField = assetFields.file;
212
+ if (assetFileField.localized) {
213
+ if (locale) {
214
+ fields.url.value = assetFileField.locales[locale]?.url ?? null;
215
+ fields.url.locale = locale;
216
+ }
217
+ } else {
218
+ fields.url.value = assetFileField.url;
219
+ fields.url.locale = assetFileField.locale;
220
+ }
221
+ return fields;
222
+ }
223
+
224
+ export function mapStoreAssetsToAPIAssets(assets: ContentStoreTypes.Asset[], locale?: string): ContentStoreTypes.APIAsset[] {
225
+ return assets.map((asset) => storeAssetToAPIAsset(asset, locale));
226
+ }
227
+
228
+ function storeAssetToAPIAsset(asset: ContentStoreTypes.Asset, locale?: string): ContentStoreTypes.APIAsset {
229
+ const assetTitleField = asset.fields.title;
230
+ const localizedTitleField = assetTitleField.localized ? assetTitleField.locales[locale!]! : assetTitleField;
231
+ const assetFileField = asset.fields.file;
232
+ const localizedFileField = assetFileField.localized ? assetFileField.locales[locale!]! : assetFileField;
233
+ return {
234
+ objectId: asset.srcObjectId,
235
+ createdAt: asset.createdAt,
236
+ url: localizedFileField.url,
237
+ ...omitByNil({
238
+ title: localizedTitleField.value,
239
+ fileName: localizedFileField.fileName,
240
+ contentType: localizedFileField.contentType,
241
+ size: localizedFileField.size,
242
+ width: localizedFileField.dimensions?.width,
243
+ height: localizedFileField.dimensions?.height
244
+ })
245
+ };
246
+ }