@stackbit/cms-core 0.1.25 → 0.1.26-develop.1

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 (103) hide show
  1. package/dist/content-store-utils.d.ts +5 -5
  2. package/dist/content-store-utils.d.ts.map +1 -1
  3. package/dist/content-store-utils.js +15 -3
  4. package/dist/content-store-utils.js.map +1 -1
  5. package/dist/content-store.d.ts +11 -3
  6. package/dist/content-store.d.ts.map +1 -1
  7. package/dist/content-store.js +10 -5
  8. package/dist/content-store.js.map +1 -1
  9. package/dist/index.d.ts +2 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/services/git.d.ts +38 -0
  14. package/dist/services/git.d.ts.map +1 -0
  15. package/dist/services/git.js +201 -0
  16. package/dist/services/git.js.map +1 -0
  17. package/dist/services/index.d.ts +3 -0
  18. package/dist/services/index.d.ts.map +1 -0
  19. package/dist/services/index.js +15 -0
  20. package/dist/services/index.js.map +1 -0
  21. package/dist/services/run.d.ts +7 -0
  22. package/dist/services/run.d.ts.map +1 -0
  23. package/dist/services/run.js +53 -0
  24. package/dist/services/run.js.map +1 -0
  25. package/dist/types/content-store-document-fields.d.ts +600 -0
  26. package/dist/types/content-store-document-fields.d.ts.map +1 -0
  27. package/dist/types/content-store-document-fields.js +3 -0
  28. package/dist/types/content-store-document-fields.js.map +1 -0
  29. package/dist/types/content-store-documents.d.ts +99 -0
  30. package/dist/types/content-store-documents.d.ts.map +1 -0
  31. package/dist/types/content-store-documents.js +3 -0
  32. package/dist/types/content-store-documents.js.map +1 -0
  33. package/dist/types/content-store-types.d.ts +75 -0
  34. package/dist/types/content-store-types.d.ts.map +1 -0
  35. package/dist/types/content-store-types.js.map +1 -0
  36. package/dist/types/content-store-update-operation.d.ts +61 -0
  37. package/dist/types/content-store-update-operation.d.ts.map +1 -0
  38. package/dist/types/content-store-update-operation.js +3 -0
  39. package/dist/types/content-store-update-operation.js.map +1 -0
  40. package/dist/types/index.d.ts +6 -0
  41. package/dist/types/index.d.ts.map +1 -0
  42. package/dist/types/index.js +18 -0
  43. package/dist/types/index.js.map +1 -0
  44. package/dist/types/search-filter.d.ts +1 -1
  45. package/dist/types/search-filter.d.ts.map +1 -1
  46. package/dist/utils/create-update-csi-docs.d.ts +1 -1
  47. package/dist/utils/create-update-csi-docs.d.ts.map +1 -1
  48. package/dist/utils/create-update-csi-docs.js +28 -14
  49. package/dist/utils/create-update-csi-docs.js.map +1 -1
  50. package/dist/utils/csi-to-store-docs-converter.d.ts +1 -1
  51. package/dist/utils/csi-to-store-docs-converter.d.ts.map +1 -1
  52. package/dist/utils/csi-to-store-docs-converter.js +20 -4
  53. package/dist/utils/csi-to-store-docs-converter.js.map +1 -1
  54. package/dist/utils/duplicate-document.d.ts +1 -1
  55. package/dist/utils/duplicate-document.d.ts.map +1 -1
  56. package/dist/utils/duplicate-document.js +11 -0
  57. package/dist/utils/duplicate-document.js.map +1 -1
  58. package/dist/utils/index.d.ts +2 -2
  59. package/dist/utils/index.d.ts.map +1 -1
  60. package/dist/utils/search-utils.d.ts +1 -1
  61. package/dist/utils/search-utils.d.ts.map +1 -1
  62. package/dist/utils/search-utils.js +16 -16
  63. package/dist/utils/search-utils.js.map +1 -1
  64. package/dist/utils/site-map.d.ts +1 -1
  65. package/dist/utils/site-map.d.ts.map +1 -1
  66. package/dist/utils/site-map.js +9 -0
  67. package/dist/utils/site-map.js.map +1 -1
  68. package/dist/utils/store-to-api-docs-converter.d.ts +2 -2
  69. package/dist/utils/store-to-api-docs-converter.d.ts.map +1 -1
  70. package/dist/utils/store-to-api-docs-converter.js +87 -38
  71. package/dist/utils/store-to-api-docs-converter.js.map +1 -1
  72. package/dist/utils/store-to-csi-docs-converter.d.ts +1 -1
  73. package/dist/utils/store-to-csi-docs-converter.d.ts.map +1 -1
  74. package/dist/utils/store-to-csi-docs-converter.js +4 -0
  75. package/dist/utils/store-to-csi-docs-converter.js.map +1 -1
  76. package/dist/utils/timer.d.ts +1 -1
  77. package/dist/utils/timer.d.ts.map +1 -1
  78. package/package.json +9 -6
  79. package/src/content-store-utils.ts +19 -8
  80. package/src/content-store.ts +28 -15
  81. package/src/index.ts +2 -1
  82. package/src/services/git.ts +245 -0
  83. package/src/services/index.ts +2 -0
  84. package/src/services/run.ts +54 -0
  85. package/src/types/content-store-document-fields.ts +658 -0
  86. package/src/types/content-store-documents.ts +113 -0
  87. package/src/types/content-store-types.ts +96 -0
  88. package/src/types/content-store-update-operation.ts +85 -0
  89. package/src/types/index.ts +5 -0
  90. package/src/types/search-filter.ts +26 -19
  91. package/src/utils/create-update-csi-docs.ts +33 -16
  92. package/src/utils/csi-to-store-docs-converter.ts +33 -14
  93. package/src/utils/duplicate-document.ts +11 -1
  94. package/src/utils/search-utils.ts +18 -19
  95. package/src/utils/site-map.ts +10 -1
  96. package/src/utils/store-to-api-docs-converter.ts +86 -38
  97. package/src/utils/store-to-csi-docs-converter.ts +5 -1
  98. package/src/utils/timer.ts +1 -1
  99. package/dist/content-store-types.d.ts +0 -411
  100. package/dist/content-store-types.d.ts.map +0 -1
  101. package/dist/content-store-types.js.map +0 -1
  102. package/src/content-store-types.ts +0 -527
  103. /package/dist/{content-store-types.js → types/content-store-types.js} +0 -0
@@ -1,11 +1,9 @@
1
1
  import _ from 'lodash';
2
2
  import { ImageModel, Model } from '@stackbit/sdk';
3
- import * as ContentSourceInterface from '@stackbit/types';
4
- import { getLocalizedFieldForLocale } from '@stackbit/types';
5
3
 
4
+ import * as ContentStoreTypes from '../types';
6
5
  import { SearchFilter, SearchFilterItem } from '../types/search-filter';
7
- import { ContentStoreTypes } from '..';
8
- import { getContentSourceId } from '../content-store-utils';
6
+ import { getContentSourceId, getDocumentFieldForLocale } from '../content-store-utils';
9
7
 
10
8
  const META_FIELD = {
11
9
  createdAt: {
@@ -91,7 +89,7 @@ const isDocumentMatchesPattern = (document: ContentStoreTypes.Document, query: s
91
89
  case 'text':
92
90
  case 'markdown':
93
91
  case 'html':
94
- value = getLocalizedFieldForLocale(field, locale)?.value;
92
+ value = getDocumentFieldForLocale(field, locale)?.value;
95
93
  break;
96
94
  }
97
95
 
@@ -105,13 +103,14 @@ const isDocumentMatchesPattern = (document: ContentStoreTypes.Document, query: s
105
103
 
106
104
  const getFieldForFilter = (document: ContentStoreTypes.Document, filter: SearchFilterItem): ContentStoreTypes.DocumentField => {
107
105
  if (filter.isMeta) {
108
- const fieldDef = META_FIELD[filter.field as keyof typeof META_FIELD];
109
- if (!fieldDef) {
106
+ if (filter.field !== 'createdAt' && filter.field !== 'updatedAt') {
110
107
  throw new Error(`Unsupported meta field ${filter.field}`);
111
108
  }
109
+ const fieldDef = META_FIELD[filter.field];
110
+ const dateValue = document[filter.field];
112
111
  return {
113
112
  ...fieldDef,
114
- value: document[filter.field as keyof typeof document]
113
+ value: dateValue
115
114
  };
116
115
  } else {
117
116
  const documentField = document.fields[filter.field];
@@ -180,7 +179,7 @@ const isStringFieldMatches = ({
180
179
  locale?: string;
181
180
  }) => {
182
181
  // ignoring case
183
- const fieldValue = getLocalizedFieldForLocale(field, locale)?.value?.toLowerCase();
182
+ const fieldValue = getDocumentFieldForLocale(field, locale)?.value?.toLowerCase();
184
183
 
185
184
  switch (filter.operator) {
186
185
  case 'is-undefined': return fieldValue === undefined;
@@ -202,9 +201,9 @@ const isStringFieldMatches = ({
202
201
  case 'neq':
203
202
  return fieldValue !== filterValue;
204
203
  case 'includes':
205
- return fieldValue.includes(filterValue);
204
+ return Boolean(fieldValue?.includes(filterValue));
206
205
  case 'not-includes':
207
- return !fieldValue.includes(filterValue);
206
+ return !Boolean(fieldValue?.includes(filterValue));
208
207
  }
209
208
  }
210
209
  }
@@ -213,7 +212,7 @@ const isStringFieldMatches = ({
213
212
  };
214
213
 
215
214
  const isNumberFieldMatches = ({ field, filter, locale }: { field: ContentStoreTypes.DocumentFieldForType<'number'>; filter: SearchFilterItem; locale?: string }) => {
216
- const fieldValue = getLocalizedFieldForLocale(field, locale)?.value;
215
+ const fieldValue = getDocumentFieldForLocale(field, locale)?.value;
217
216
 
218
217
  switch (filter.operator) {
219
218
  case 'is-undefined': return fieldValue === undefined;
@@ -234,9 +233,9 @@ const isNumberFieldMatches = ({ field, filter, locale }: { field: ContentStoreTy
234
233
  case 'neq':
235
234
  return fieldValue !== filter.value;
236
235
  case 'gte':
237
- return fieldValue >= filter.value;
236
+ return Boolean(fieldValue && fieldValue >= filter.value);
238
237
  case 'lte':
239
- return fieldValue <= filter.value;
238
+ return Boolean(fieldValue && fieldValue <= filter.value);
240
239
  }
241
240
  }
242
241
 
@@ -246,7 +245,7 @@ const isNumberFieldMatches = ({ field, filter, locale }: { field: ContentStoreTy
246
245
  throw new Error(`Filter startValue and endValue should be number for field ${filter.field}`);
247
246
  }
248
247
 
249
- return fieldValue >= filter.startValue && fieldValue <= filter.endValue;
248
+ return Boolean(fieldValue && fieldValue >= filter.startValue && fieldValue <= filter.endValue);
250
249
  }
251
250
  }
252
251
 
@@ -262,7 +261,7 @@ const isBooleanFieldMatches = ({
262
261
  filter: SearchFilterItem;
263
262
  locale?: string;
264
263
  }) => {
265
- const fieldValue = getLocalizedFieldForLocale(field, locale)?.value;
264
+ const fieldValue = getDocumentFieldForLocale(field, locale)?.value;
266
265
 
267
266
  switch (filter.operator) {
268
267
  case 'is-undefined': return fieldValue === undefined;
@@ -311,7 +310,7 @@ const isDateFieldMatches = ({
311
310
  filter: SearchFilterItem;
312
311
  locale?: string;
313
312
  }) => {
314
- const origValue = getLocalizedFieldForLocale(field, locale)?.value;
313
+ const origValue = getDocumentFieldForLocale(field, locale)?.value;
315
314
  const fieldValue = parseDateValue(origValue);
316
315
  if (origValue && !fieldValue) {
317
316
  throw new Error(`Can't parse value ${origValue} for field ${filter.field}`);
@@ -374,7 +373,7 @@ const isDateFieldMatches = ({
374
373
  };
375
374
 
376
375
  const isEnumFieldMatches = ({ field, filter, locale }: { field: ContentStoreTypes.DocumentFieldForType<'enum'>; filter: SearchFilterItem; locale?: string }) => {
377
- const fieldValue = getLocalizedFieldForLocale(field, locale)?.value;
376
+ const fieldValue = getDocumentFieldForLocale(field, locale)?.value;
378
377
 
379
378
  switch (filter.operator) {
380
379
  case 'is-undefined': return fieldValue === undefined;
@@ -415,7 +414,7 @@ const isListFieldMatches = ({
415
414
  throw new Error(`Unsupported filter for list field ${filter.field} with children ${listItemsType}`);
416
415
  }
417
416
 
418
- const fieldValue = getLocalizedFieldForLocale(field as ContentSourceInterface.DocumentFieldForType<'list'>, locale)?.items?.map((item) =>
417
+ const fieldValue = getDocumentFieldForLocale(field, locale)?.items?.map((item) =>
419
418
  'value' in item ? item.value : undefined
420
419
  );
421
420
 
@@ -3,7 +3,7 @@ import { Config } from '@stackbit/sdk';
3
3
  import { append } from '@stackbit/utils';
4
4
  import { SiteMapEntry } from '@stackbit/types';
5
5
  import * as CSITypes from '@stackbit/types';
6
- import * as ContentStoreTypes from '../content-store-types';
6
+ import * as ContentStoreTypes from '../types';
7
7
  import { mapStoreDocumentsToCSIDocumentsWithSource } from './store-to-csi-docs-converter';
8
8
  import { getContentSourceId, getDocumentFieldForLocale } from '../content-store-utils';
9
9
 
@@ -169,6 +169,15 @@ function sanitizeAndGroupSiteMapEntries(siteMapEntries: SiteMapEntry[]): SiteMap
169
169
  if (!doc.srcType || !doc.srcProjectId || !doc.modelName || !doc.id) {
170
170
  return accum;
171
171
  }
172
+ siteMapEntry = {
173
+ ...siteMapEntry,
174
+ document: {
175
+ id: doc.id,
176
+ modelName: doc.modelName,
177
+ srcType: doc.srcType,
178
+ srcProjectId: doc.srcProjectId
179
+ }
180
+ }
172
181
  }
173
182
 
174
183
  if (!siteMapEntry.stableId) {
@@ -1,6 +1,8 @@
1
1
  import _ from 'lodash';
2
+ import path from 'path';
2
3
  import { omitByNil } from '@stackbit/utils';
3
- import * as ContentStoreTypes from '../content-store-types';
4
+ import * as ContentStoreTypes from '../types';
5
+ import { DocumentStringLikeFieldAPI } from '../types';
4
6
 
5
7
  export function mapDocumentsToLocalizedApiObjects(documents: ContentStoreTypes.Document[], locale?: string): ContentStoreTypes.APIDocumentObject[] {
6
8
  return documents.map((document) => documentToLocalizedApiObject(document, locale));
@@ -51,53 +53,84 @@ function toLocalizedAPIField(docField: ContentStoreTypes.DocumentField, locale?:
51
53
  case 'date':
52
54
  case 'datetime':
53
55
  case 'color':
54
- case 'style':
55
- case 'file':
56
- case 'json':
57
- case 'markdown':
58
- case 'richText':
56
+ case 'style': {
59
57
  if (docField.localized) {
60
58
  const { localized, locales, ...base } = docField;
61
59
  const localeProps = locales && locale ? locales[locale] : undefined;
62
60
  return {
63
61
  ...base,
64
- ...(localeProps ?? { value: null }),
65
- ...localeFields(localized),
66
- ...(['file', 'json', 'markdown', 'richText'].includes(docField.type) && !localeProps ? { isUnset: true } : null)
67
- };
62
+ ...localeProps,
63
+ ...localeFields(localized)
64
+ } as ContentStoreTypes.DocumentStringLikeFieldAPI;
68
65
  }
69
66
  return {
70
67
  ...docField,
71
68
  ...localeFields(docField.localized)
72
69
  };
73
- case 'image':
70
+ }
71
+ case 'file':
72
+ case 'json':
73
+ case 'markdown':
74
+ case 'richText': {
74
75
  if (docField.localized) {
75
76
  const { localized, locales, ...base } = docField;
76
77
  const localeProps = locales && locale ? locales[locale] : undefined;
78
+ if (localeProps) {
79
+ return {
80
+ ...base,
81
+ ...localeProps,
82
+ ...localeFields(localized)
83
+ };
84
+ }
77
85
  return {
78
86
  ...base,
79
- ...(localeProps
80
- ? {
81
- ...localeProps,
82
- fields: toLocalizedAPIFields(localeProps.fields, locale) as ContentStoreTypes.ImageFieldsAPI
83
- }
84
- : { isUnset: true }),
87
+ isUnset: true,
85
88
  ...localeFields(localized)
86
89
  };
87
90
  }
88
91
  return {
89
- ...(!docField.isUnset
90
- ? {
91
- ...docField,
92
- type: 'image',
93
- fields: toLocalizedAPIFields(docField.fields, locale) as ContentStoreTypes.ImageFieldsAPI
94
- }
95
- : {
96
- ...docField,
97
- type: 'image'
98
- }),
92
+ ...docField,
99
93
  ...localeFields(docField.localized)
100
94
  };
95
+ }
96
+ case 'image':
97
+ let result: ContentStoreTypes.DocumentFieldAPI;
98
+ if (docField.localized) {
99
+ const { localized, locales, ...base } = docField;
100
+ const localeProps = locales && locale ? locales[locale] : undefined;
101
+ if (localeProps) {
102
+ const fields = toLocalizedAPIFields(localeProps.fields, locale) as ContentStoreTypes.ImageFieldsAPI;
103
+ result = {
104
+ ...base,
105
+ ...localeProps,
106
+ fields,
107
+ ...localeFields(localized)
108
+ };
109
+ } else {
110
+ result = {
111
+ ...base,
112
+ isUnset: true,
113
+ ...localeFields(localized)
114
+ };
115
+ }
116
+ } else {
117
+ if (docField.isUnset) {
118
+ result = {
119
+ ...docField,
120
+ type: 'image',
121
+ ...localeFields(docField.localized)
122
+ };
123
+ } else {
124
+ const fields = toLocalizedAPIFields(docField.fields, locale) as ContentStoreTypes.ImageFieldsAPI;
125
+ result = {
126
+ ...docField,
127
+ type: 'image',
128
+ fields,
129
+ ...localeFields(docField.localized)
130
+ };
131
+ }
132
+ }
133
+ return result;
101
134
  case 'object':
102
135
  case 'model':
103
136
  if (docField.localized) {
@@ -265,9 +298,12 @@ function localizeAssetFields(assetFields: ContentStoreTypes.AssetFields, locale?
265
298
  const titleField = assetFields.title;
266
299
  if (titleField.localized) {
267
300
  if (locale) {
268
- fields.title.value = titleField.locales?.[locale]?.value ?? null;
269
- fields.title.localized = true;
270
- fields.title.locale = locale;
301
+ fields.title = {
302
+ type: 'string',
303
+ value: titleField.locales?.[locale]?.value ?? null,
304
+ localized: true,
305
+ locale: locale
306
+ };
271
307
  }
272
308
  } else {
273
309
  fields.title.value = titleField.value;
@@ -275,9 +311,12 @@ function localizeAssetFields(assetFields: ContentStoreTypes.AssetFields, locale?
275
311
  const assetFileField = assetFields.file;
276
312
  if (assetFileField.localized) {
277
313
  if (locale) {
278
- fields.url.value = assetFileField.locales?.[locale]?.url ?? null;
279
- fields.url.localized = true;
280
- fields.url.locale = locale;
314
+ fields.url = {
315
+ type: 'string',
316
+ value: assetFileField.locales?.[locale]?.url ?? null,
317
+ localized: true,
318
+ locale: locale
319
+ };
281
320
  }
282
321
  } else {
283
322
  fields.url.value = assetFileField.url;
@@ -285,11 +324,11 @@ function localizeAssetFields(assetFields: ContentStoreTypes.AssetFields, locale?
285
324
  return fields;
286
325
  }
287
326
 
288
- export function mapStoreAssetsToAPIAssets(assets: ContentStoreTypes.Asset[], locale?: string): ContentStoreTypes.APIAsset[] {
289
- return assets.map((asset) => storeAssetToAPIAsset(asset, locale)).filter((asset): asset is ContentStoreTypes.APIAsset => !!asset);
327
+ export function mapStoreAssetsToAPIAssets(assets: ContentStoreTypes.Asset[], staticAssetsPublicPath: string, locale?: string): ContentStoreTypes.APIAsset[] {
328
+ return assets.map((asset) => storeAssetToAPIAsset(asset, staticAssetsPublicPath, locale)).filter((asset): asset is ContentStoreTypes.APIAsset => !!asset);
290
329
  }
291
330
 
292
- function storeAssetToAPIAsset(asset: ContentStoreTypes.Asset, locale?: string): ContentStoreTypes.APIAsset | null {
331
+ function storeAssetToAPIAsset(asset: ContentStoreTypes.Asset, staticAssetsPublicPath: string, locale?: string): ContentStoreTypes.APIAsset | null {
293
332
  const assetTitleField = asset.fields.title;
294
333
  const localizedTitleField = assetTitleField.localized ? assetTitleField.locales?.[locale!] : assetTitleField;
295
334
  const assetFileField = asset.fields.file;
@@ -300,9 +339,9 @@ function storeAssetToAPIAsset(asset: ContentStoreTypes.Asset, locale?: string):
300
339
  return {
301
340
  objectId: asset.srcObjectId,
302
341
  createdAt: asset.createdAt,
303
- url: localizedFileField.url,
342
+ url: replaceAssetUrlIfNeeded(staticAssetsPublicPath, localizedFileField.url) ?? staticAssetsPublicPath,
304
343
  ...omitByNil({
305
- title: localizedTitleField?.value ?? null,
344
+ title: localizedTitleField?.value ?? undefined,
306
345
  fileName: localizedFileField.fileName,
307
346
  contentType: localizedFileField.contentType,
308
347
  size: localizedFileField.size,
@@ -311,3 +350,12 @@ function storeAssetToAPIAsset(asset: ContentStoreTypes.Asset, locale?: string):
311
350
  })
312
351
  };
313
352
  }
353
+
354
+ function replaceAssetUrlIfNeeded(staticAssetsPublicPath: string, value: string | undefined) {
355
+ let url = value;
356
+ let normalizedUrl = url?.toLowerCase();
357
+ if (normalizedUrl && !normalizedUrl.startsWith('http:') && !normalizedUrl.startsWith('https:') && !normalizedUrl.startsWith('//')) {
358
+ url = path.join(staticAssetsPublicPath, url!);
359
+ }
360
+ return url;
361
+ }
@@ -1,6 +1,6 @@
1
1
  import _ from 'lodash';
2
2
  import * as CSITypes from '@stackbit/types';
3
- import * as ContentStoreTypes from '../content-store-types';
3
+ import * as ContentStoreTypes from '../types';
4
4
 
5
5
  export function mapStoreDocumentsToCSIDocumentsWithSource(documents: ContentStoreTypes.Document[]): CSITypes.DocumentWithSource[] {
6
6
  return documents.map((document) => mapStoreDocumentToCSIDocumentWithSource(document));
@@ -95,6 +95,8 @@ function mapStoreFieldToCSIField(documentField: ContentStoreTypes.DocumentField)
95
95
  return {
96
96
  type: 'image',
97
97
  localized: true,
98
+ source: documentField.source,
99
+ sourceData: documentField.sourceData,
98
100
  locales: _.mapValues(documentField.locales, (locale) => ({
99
101
  locale: locale.locale,
100
102
  fields: mapStoreFieldsToCSIFields(locale.fields)
@@ -106,6 +108,8 @@ function mapStoreFieldToCSIField(documentField: ContentStoreTypes.DocumentField)
106
108
  }
107
109
  return {
108
110
  type: 'image',
111
+ source: documentField.source,
112
+ sourceData: documentField.sourceData,
109
113
  fields: mapStoreFieldsToCSIFields(documentField.fields)
110
114
  } as CSITypes.DocumentImageFieldNonLocalized;
111
115
  }
@@ -1,4 +1,4 @@
1
- import { Logger } from '../content-store-types';
1
+ import { Logger } from '@stackbit/types';
2
2
 
3
3
  export class Timer {
4
4
  private readonly timerCallback: () => void;