@stackbit/cms-core 0.1.14-alpha.0 → 0.1.14-canary.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.
- package/dist/content-store-types.d.ts.map +1 -1
- package/dist/content-store-utils.d.ts +1 -6
- package/dist/content-store-utils.d.ts.map +1 -1
- package/dist/content-store-utils.js +1 -27
- package/dist/content-store-utils.js.map +1 -1
- package/dist/content-store.d.ts +18 -2
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +237 -102
- package/dist/content-store.js.map +1 -1
- package/dist/utils/preset-utils.d.ts +12 -0
- package/dist/utils/preset-utils.d.ts.map +1 -0
- package/dist/utils/preset-utils.js +92 -0
- package/dist/utils/preset-utils.js.map +1 -0
- package/dist/utils/site-map.d.ts +57 -0
- package/dist/utils/site-map.d.ts.map +1 -0
- package/dist/utils/site-map.js +149 -0
- package/dist/utils/site-map.js.map +1 -0
- package/package.json +5 -5
- package/src/content-store-types.ts +2 -0
- package/src/content-store-utils.ts +0 -33
- package/src/content-store.ts +275 -119
- package/src/utils/preset-utils.ts +94 -0
- package/src/utils/site-map.ts +224 -0
package/dist/content-store.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.ContentStore = void 0;
|
|
6
|
+
exports.ContentStore = exports.StackbitPresetModelName = void 0;
|
|
7
7
|
const lodash_1 = __importDefault(require("lodash"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const sanitize_filename_1 = __importDefault(require("sanitize-filename"));
|
|
@@ -13,13 +13,15 @@ const utils_1 = require("@stackbit/utils");
|
|
|
13
13
|
const timer_1 = require("./utils/timer");
|
|
14
14
|
const search_utils_1 = require("./utils/search-utils");
|
|
15
15
|
const csi_to_store_docs_converter_1 = require("./utils/csi-to-store-docs-converter");
|
|
16
|
-
const store_to_csi_docs_converter_1 = require("./utils/store-to-csi-docs-converter");
|
|
17
16
|
const content_store_utils_1 = require("./content-store-utils");
|
|
17
|
+
const site_map_1 = require("./utils/site-map");
|
|
18
18
|
const store_to_api_docs_converter_1 = require("./utils/store-to-api-docs-converter");
|
|
19
19
|
const create_update_csi_docs_1 = require("./utils/create-update-csi-docs");
|
|
20
20
|
const duplicate_document_1 = require("./utils/duplicate-document");
|
|
21
21
|
const model_utils_1 = require("./utils/model-utils");
|
|
22
22
|
const common_schema_1 = require("./common/common-schema");
|
|
23
|
+
const preset_utils_1 = require("./utils/preset-utils");
|
|
24
|
+
exports.StackbitPresetModelName = 'stackbitPreset';
|
|
23
25
|
class ContentStore {
|
|
24
26
|
constructor(options) {
|
|
25
27
|
this.contentSources = [];
|
|
@@ -29,6 +31,7 @@ class ContentStore {
|
|
|
29
31
|
this.configModels = [];
|
|
30
32
|
this.modelExtensions = null;
|
|
31
33
|
this.presets = {};
|
|
34
|
+
this.siteMapEntryGroups = {};
|
|
32
35
|
this.logger = options.logger.createLogger({ label: 'content-store' });
|
|
33
36
|
this.userLogger = options.userLogger.createLogger({ label: 'content-store' });
|
|
34
37
|
this.localDev = options.localDev;
|
|
@@ -79,7 +82,6 @@ class ContentStore {
|
|
|
79
82
|
this.yamlModels = await this.loadYamlModels({ stackbitConfig });
|
|
80
83
|
this.configModels = this.mergeConfigModels((_a = stackbitConfig.models) !== null && _a !== void 0 ? _a : [], this.yamlModels);
|
|
81
84
|
}
|
|
82
|
-
this.presets = await this.loadPresets({ stackbitConfig });
|
|
83
85
|
}
|
|
84
86
|
await this.loadContentSourcesAndProcessData({ init: true });
|
|
85
87
|
this.contentUpdatesWatchTimer.startTimer();
|
|
@@ -146,10 +148,10 @@ class ContentStore {
|
|
|
146
148
|
// Check if any of the preset files were changed. If presets were changed, reload them.
|
|
147
149
|
const presetDirs = (0, sdk_1.getPresetDirs)(this.stackbitConfig);
|
|
148
150
|
const presetsChanged = updatedFiles.find((updatedFile) => lodash_1.default.some(presetDirs, (presetDir) => updatedFile.startsWith(presetDir)));
|
|
149
|
-
if (presetsChanged) {
|
|
151
|
+
if (presetsChanged && !this.usesContentSourcePresets()) {
|
|
150
152
|
this.logger.debug('identified change in stackbit preset files');
|
|
151
153
|
schemaChanged = true;
|
|
152
|
-
this.presets = await this.
|
|
154
|
+
this.presets = await this.loadPresetsFromConfig({ stackbitConfig: this.stackbitConfig });
|
|
153
155
|
}
|
|
154
156
|
}
|
|
155
157
|
const contentSourceIdsWithChangedSchema = [];
|
|
@@ -169,7 +171,7 @@ class ContentStore {
|
|
|
169
171
|
contentChangeEvents.push({ contentSourceId, contentChangeEvent: onFilesChangeResult.contentChangeEvent });
|
|
170
172
|
}
|
|
171
173
|
}
|
|
172
|
-
|
|
174
|
+
let contentChanges = {
|
|
173
175
|
updatedDocuments: [],
|
|
174
176
|
updatedAssets: [],
|
|
175
177
|
deletedDocuments: [],
|
|
@@ -182,14 +184,21 @@ class ContentStore {
|
|
|
182
184
|
await this.loadContentSourcesAndProcessData({ init: false, contentSourceIds: contentSourceIdsWithChangedSchema });
|
|
183
185
|
}
|
|
184
186
|
else {
|
|
185
|
-
contentChangeEvents.reduce((contentChanges, { contentSourceId, contentChangeEvent }) => {
|
|
187
|
+
contentChanges = contentChangeEvents.reduce((contentChanges, { contentSourceId, contentChangeEvent }) => {
|
|
186
188
|
const contentChangeResult = this.onContentChange(contentSourceId, contentChangeEvent);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
189
|
+
return {
|
|
190
|
+
updatedDocuments: contentChanges.updatedDocuments.concat(contentChangeResult.updatedDocuments),
|
|
191
|
+
updatedAssets: contentChanges.updatedAssets.concat(contentChangeResult.updatedAssets),
|
|
192
|
+
deletedDocuments: contentChanges.deletedDocuments.concat(contentChangeResult.deletedDocuments),
|
|
193
|
+
deletedAssets: contentChanges.deletedAssets.concat(contentChangeResult.deletedAssets)
|
|
194
|
+
};
|
|
192
195
|
}, contentChanges);
|
|
196
|
+
this.siteMapEntryGroups = await (0, site_map_1.updateSiteMapEntriesWithContentChanges)({
|
|
197
|
+
siteMapEntryGroups: this.siteMapEntryGroups,
|
|
198
|
+
contentChanges,
|
|
199
|
+
stackbitConfig: this.stackbitConfig,
|
|
200
|
+
contentSourceDataById: this.contentSourceDataById
|
|
201
|
+
});
|
|
193
202
|
}
|
|
194
203
|
// TODO: maybe instead of returning object with results
|
|
195
204
|
// replace with this.onSchemaChangeCallback() and this.onContentChangeCallback(contentChanges) for consistency of data flow?
|
|
@@ -212,7 +221,7 @@ class ContentStore {
|
|
|
212
221
|
}
|
|
213
222
|
return configModelsResult.models;
|
|
214
223
|
}
|
|
215
|
-
async
|
|
224
|
+
async loadPresetsFromConfig({ stackbitConfig }) {
|
|
216
225
|
var _a;
|
|
217
226
|
const contentSources = (_a = stackbitConfig === null || stackbitConfig === void 0 ? void 0 : stackbitConfig.contentSources) !== null && _a !== void 0 ? _a : [];
|
|
218
227
|
const singleContentSource = contentSources.length === 1 ? contentSources[0] : null;
|
|
@@ -231,6 +240,24 @@ class ContentStore {
|
|
|
231
240
|
const { presets } = await this.handleConfigAssets({ presets: presetResult.presets });
|
|
232
241
|
return presets;
|
|
233
242
|
}
|
|
243
|
+
async loadPresetsFromContentSource(contentSourceData) {
|
|
244
|
+
const presets = lodash_1.default.reduce(contentSourceData.csiDocuments, (result, csiDocument) => {
|
|
245
|
+
if (csiDocument.modelName === exports.StackbitPresetModelName) {
|
|
246
|
+
const preset = (0, preset_utils_1.getPresetFromDocument)({
|
|
247
|
+
srcType: contentSourceData.srcType,
|
|
248
|
+
srcProjectId: contentSourceData.srcProjectId,
|
|
249
|
+
csiDocument,
|
|
250
|
+
csiAssetMap: contentSourceData.csiAssetMap,
|
|
251
|
+
logger: this.logger
|
|
252
|
+
});
|
|
253
|
+
if (preset) {
|
|
254
|
+
result[csiDocument.id] = preset;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return result;
|
|
258
|
+
}, {});
|
|
259
|
+
return presets;
|
|
260
|
+
}
|
|
234
261
|
/**
|
|
235
262
|
* This function reloads the data of the specified content-sources, while
|
|
236
263
|
* reusing the cached data of the rest of the content-sources, then processes
|
|
@@ -249,7 +276,7 @@ class ContentStore {
|
|
|
249
276
|
* @private
|
|
250
277
|
*/
|
|
251
278
|
async loadContentSourcesAndProcessData({ init, contentSourceIds }) {
|
|
252
|
-
var _a, _b, _c, _d;
|
|
279
|
+
var _a, _b, _c, _d, _e;
|
|
253
280
|
this.logger.debug('loadContentSourcesAndProcessData', { init, contentSourceIds });
|
|
254
281
|
const contentSources = (_b = (_a = this.stackbitConfig) === null || _a === void 0 ? void 0 : _a.contentSources) !== null && _b !== void 0 ? _b : [];
|
|
255
282
|
const promises = contentSources.map((contentSourceInstance) => {
|
|
@@ -262,14 +289,38 @@ class ContentStore {
|
|
|
262
289
|
}
|
|
263
290
|
});
|
|
264
291
|
const contentSourceRawDataArr = await Promise.all(promises);
|
|
292
|
+
// find first content source that supports presets
|
|
293
|
+
for (let i = 0; i < contentSources.length; i++) {
|
|
294
|
+
const contentSourceDataRaw = contentSourceRawDataArr[i];
|
|
295
|
+
if ((_c = contentSourceDataRaw === null || contentSourceDataRaw === void 0 ? void 0 : contentSourceDataRaw.csiModelMap) === null || _c === void 0 ? void 0 : _c[exports.StackbitPresetModelName]) {
|
|
296
|
+
this.presetsContentSource = contentSources[i];
|
|
297
|
+
if (this.presetsContentSource) {
|
|
298
|
+
const contentSourceId = (0, content_store_utils_1.getContentSourceIdForContentSource)(this.presetsContentSource);
|
|
299
|
+
// reload presets from content source only if needed
|
|
300
|
+
if (init || !contentSourceIds || contentSourceIds.includes(contentSourceId)) {
|
|
301
|
+
this.presets = await this.loadPresetsFromContentSource(contentSourceDataRaw);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// fallback to loading presets from config as usual
|
|
308
|
+
if (init && this.stackbitConfig && !this.presetsContentSource) {
|
|
309
|
+
this.presets = await this.loadPresetsFromConfig({ stackbitConfig: this.stackbitConfig });
|
|
310
|
+
}
|
|
265
311
|
// update all content sources at once to prevent race conditions
|
|
266
312
|
this.contentSourceDataById = await this.processData({
|
|
267
313
|
stackbitConfig: this.stackbitConfig,
|
|
268
|
-
configModels: (
|
|
314
|
+
configModels: (_e = (_d = this.modelExtensions) !== null && _d !== void 0 ? _d : this.configModels) !== null && _e !== void 0 ? _e : [],
|
|
269
315
|
presets: this.presets,
|
|
270
316
|
contentSourceRawDataArr: contentSourceRawDataArr
|
|
271
317
|
});
|
|
272
318
|
this.contentSources = contentSources;
|
|
319
|
+
// generate create site map entries
|
|
320
|
+
this.siteMapEntryGroups = await (0, site_map_1.getSiteMapEntriesFromStackbitConfig)({
|
|
321
|
+
stackbitConfig: this.stackbitConfig,
|
|
322
|
+
contentSourceDataById: this.contentSourceDataById
|
|
323
|
+
});
|
|
273
324
|
}
|
|
274
325
|
async loadContentSourceData({ contentSourceInstance, init }) {
|
|
275
326
|
var _a;
|
|
@@ -321,9 +372,15 @@ class ContentStore {
|
|
|
321
372
|
getAsset({ assetId }) {
|
|
322
373
|
return csiAssetMap[assetId];
|
|
323
374
|
},
|
|
324
|
-
onContentChange: (contentChangeEvent) => {
|
|
375
|
+
onContentChange: async (contentChangeEvent) => {
|
|
325
376
|
this.logger.debug('content source called onContentChange', { contentSourceId });
|
|
326
377
|
const result = this.onContentChange(contentSourceId, contentChangeEvent);
|
|
378
|
+
this.siteMapEntryGroups = await (0, site_map_1.updateSiteMapEntriesWithContentChanges)({
|
|
379
|
+
siteMapEntryGroups: this.siteMapEntryGroups,
|
|
380
|
+
contentChanges: result,
|
|
381
|
+
stackbitConfig: this.stackbitConfig,
|
|
382
|
+
contentSourceDataById: this.contentSourceDataById
|
|
383
|
+
});
|
|
327
384
|
this.onContentChangeCallback(result);
|
|
328
385
|
},
|
|
329
386
|
onSchemaChange: async () => {
|
|
@@ -351,7 +408,9 @@ class ContentStore {
|
|
|
351
408
|
}
|
|
352
409
|
onContentChange(contentSourceId, contentChangeEvent) {
|
|
353
410
|
// TODO: prevent content change process for contentSourceId if loading content is in progress
|
|
354
|
-
var _a, _b, _c, _d;
|
|
411
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
412
|
+
// certain content changes, like preset changes are interpreted as schema changes
|
|
413
|
+
let schemaChanged = false;
|
|
355
414
|
this.logger.debug('onContentChange', {
|
|
356
415
|
contentSourceId,
|
|
357
416
|
documentCount: contentChangeEvent.documents.length,
|
|
@@ -368,6 +427,19 @@ class ContentStore {
|
|
|
368
427
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
369
428
|
// update contentSourceData with deleted documents
|
|
370
429
|
contentChangeEvent.deletedDocumentIds.forEach((docId) => {
|
|
430
|
+
var _a;
|
|
431
|
+
// remove preset, make sure there is something to remove first because
|
|
432
|
+
// were explicitly calling onContentChange from deletePreset as well
|
|
433
|
+
if (this.presets[docId] && ((_a = contentSourceData.csiDocumentMap[docId]) === null || _a === void 0 ? void 0 : _a.modelName) === exports.StackbitPresetModelName) {
|
|
434
|
+
schemaChanged = true;
|
|
435
|
+
const preset = this.presets[docId];
|
|
436
|
+
const model = contentSourceData.modelMap[preset.modelName];
|
|
437
|
+
delete this.presets[docId];
|
|
438
|
+
if (model && model.presets) {
|
|
439
|
+
const presetIdIndex = model.presets.findIndex((presetId) => presetId === docId);
|
|
440
|
+
model.presets.splice(presetIdIndex, 1);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
371
443
|
// delete document from documents map
|
|
372
444
|
delete contentSourceData.documentMap[docId];
|
|
373
445
|
delete contentSourceData.csiDocumentMap[docId];
|
|
@@ -450,10 +522,26 @@ class ContentStore {
|
|
|
450
522
|
contentSourceData.csiDocuments.push(csiDocument);
|
|
451
523
|
}
|
|
452
524
|
else {
|
|
453
|
-
// the indexes of documents and csiDocuments are always the same as they are always updated at the same time
|
|
454
525
|
contentSourceData.documents.splice(dataIndex, 1, document);
|
|
455
526
|
contentSourceData.csiDocuments.splice(dataIndex, 1, csiDocument);
|
|
456
527
|
}
|
|
528
|
+
if (csiDocument.modelName === exports.StackbitPresetModelName) {
|
|
529
|
+
schemaChanged = true;
|
|
530
|
+
const preset = (0, preset_utils_1.getPresetFromDocument)({
|
|
531
|
+
srcType: contentSourceData.srcType,
|
|
532
|
+
srcProjectId: contentSourceData.srcProjectId,
|
|
533
|
+
csiDocument,
|
|
534
|
+
csiAssetMap: contentSourceData.csiAssetMap,
|
|
535
|
+
logger: this.logger
|
|
536
|
+
});
|
|
537
|
+
if (preset) {
|
|
538
|
+
this.presets[csiDocument.id] = preset;
|
|
539
|
+
if (dataIndex === -1) {
|
|
540
|
+
//TODO recalculate assets as well
|
|
541
|
+
(_f = (_e = contentSourceData.modelMap[preset.modelName]) === null || _e === void 0 ? void 0 : _e.presets) === null || _f === void 0 ? void 0 : _f.push(csiDocument.id);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
457
545
|
result.updatedDocuments.push({
|
|
458
546
|
srcType: contentSourceData.srcType,
|
|
459
547
|
srcProjectId: contentSourceData.srcProjectId,
|
|
@@ -480,6 +568,9 @@ class ContentStore {
|
|
|
480
568
|
srcObjectId: asset.srcObjectId
|
|
481
569
|
});
|
|
482
570
|
}
|
|
571
|
+
if (schemaChanged) {
|
|
572
|
+
(_g = this.onSchemaChangeCallback) === null || _g === void 0 ? void 0 : _g.call(this);
|
|
573
|
+
}
|
|
483
574
|
return result;
|
|
484
575
|
}
|
|
485
576
|
async processData({ stackbitConfig, configModels, presets, contentSourceRawDataArr }) {
|
|
@@ -503,44 +594,58 @@ class ContentStore {
|
|
|
503
594
|
// srcProjectId. If after the comparison, there are more than one model left,
|
|
504
595
|
// log a warning and filter out that config model so it won't be merged with any
|
|
505
596
|
// of the content source models.
|
|
506
|
-
const
|
|
507
|
-
const
|
|
597
|
+
const nonMatchedModels = [];
|
|
598
|
+
const configModelsByContentSourceId = configModels.reduce((modelGroups, configModel) => {
|
|
508
599
|
const csiModels = csiModelGroups[configModel.name];
|
|
509
600
|
if (!csiModels) {
|
|
510
|
-
|
|
601
|
+
nonMatchedModels.push({
|
|
602
|
+
configModel,
|
|
603
|
+
matchedCSIModels: []
|
|
604
|
+
});
|
|
605
|
+
return modelGroups;
|
|
511
606
|
}
|
|
512
607
|
const matchedCSIModels = csiModels.filter((model) => {
|
|
513
608
|
const matchesType = !configModel.srcType || model.srcType === configModel.srcType;
|
|
514
609
|
const matchesId = !configModel.srcProjectId || model.srcProjectId === configModel.srcProjectId;
|
|
515
610
|
return matchesType && matchesId;
|
|
516
611
|
});
|
|
517
|
-
if (matchedCSIModels.length
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
612
|
+
if (matchedCSIModels.length !== 1) {
|
|
613
|
+
nonMatchedModels.push({
|
|
614
|
+
configModel,
|
|
615
|
+
matchedCSIModels
|
|
616
|
+
});
|
|
617
|
+
return modelGroups;
|
|
522
618
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
});
|
|
619
|
+
const contentSource = matchedCSIModels[0];
|
|
620
|
+
const contentSourceId = (0, content_store_utils_1.getContentSourceId)(contentSource.srcType, contentSource.srcProjectId);
|
|
621
|
+
(0, utils_1.append)(modelGroups, contentSourceId, configModel);
|
|
622
|
+
return modelGroups;
|
|
623
|
+
}, {});
|
|
529
624
|
// Log model matching warnings using user logger
|
|
530
|
-
for (const { configModel, matchedCSIModels } of
|
|
531
|
-
let
|
|
625
|
+
for (const { configModel, matchedCSIModels } of nonMatchedModels) {
|
|
626
|
+
let configModelMessage = `model name: '${configModel.name}'`;
|
|
532
627
|
if (configModel.srcType) {
|
|
533
|
-
|
|
628
|
+
configModelMessage += `, srcType: '${configModel.srcType}'`;
|
|
534
629
|
}
|
|
535
630
|
if (configModel.srcProjectId) {
|
|
536
|
-
|
|
631
|
+
configModelMessage += `, srcProjectId: '${configModel.srcProjectId}'`;
|
|
537
632
|
}
|
|
538
|
-
|
|
539
|
-
|
|
633
|
+
configModelMessage = configModelMessage + ` defined in stackbit config`;
|
|
634
|
+
let contentSourceModelsMessage;
|
|
635
|
+
if (matchedCSIModels.length) {
|
|
636
|
+
const matchesModelsMessage = matchedCSIModels.map((model) => `srcType: '${model.srcType}', srcProjectId: '${model.srcProjectId}'`).join('; ');
|
|
637
|
+
contentSourceModelsMessage = ` matches more that 1 model in the following content sources: ${matchesModelsMessage}`;
|
|
638
|
+
}
|
|
639
|
+
else {
|
|
640
|
+
contentSourceModelsMessage = ' does not match any content source model';
|
|
641
|
+
}
|
|
642
|
+
this.userLogger.warn(configModelMessage + contentSourceModelsMessage);
|
|
540
643
|
}
|
|
541
644
|
const modelsWithSource = contentSourceRawDataArr.reduce((accum, csData) => {
|
|
645
|
+
var _a;
|
|
646
|
+
const contentSourceId = (0, content_store_utils_1.getContentSourceId)(csData.srcType, csData.srcProjectId);
|
|
542
647
|
const mergedModels = (0, sdk_1.mergeConfigModelsWithExternalModels)({
|
|
543
|
-
configModels:
|
|
648
|
+
configModels: (_a = configModelsByContentSourceId[contentSourceId]) !== null && _a !== void 0 ? _a : [],
|
|
544
649
|
externalModels: csData.csiModels
|
|
545
650
|
});
|
|
546
651
|
const modelsWithSource = mergedModels.map((model) => {
|
|
@@ -559,27 +664,32 @@ class ContentStore {
|
|
|
559
664
|
const validatedModels = (0, model_utils_1.validateModels)({ models: normalizedModels, logger: this.userLogger });
|
|
560
665
|
const modelsWithPresetsIds = (0, sdk_1.extendModelsWithPresetsIds)({ models: validatedModels, presets });
|
|
561
666
|
const { models } = await this.handleConfigAssets({ models: modelsWithPresetsIds });
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
667
|
+
let documentMapByContentSource = null;
|
|
668
|
+
if (stackbitConfig === null || stackbitConfig === void 0 ? void 0 : stackbitConfig.mapDocuments) {
|
|
669
|
+
const csiDocumentsWithSource = contentSourceRawDataArr.reduce((accum, csData) => {
|
|
670
|
+
const csiDocumentsWithSource = csData.csiDocuments.map((csiDocument) => ({
|
|
671
|
+
srcType: csData.srcType,
|
|
672
|
+
srcProjectId: csData.srcProjectId,
|
|
673
|
+
...csiDocument
|
|
674
|
+
}));
|
|
675
|
+
return accum.concat(csiDocumentsWithSource);
|
|
676
|
+
}, []);
|
|
677
|
+
// TODO: Is there a better way than deep cloning objects before passing them to user methods?
|
|
678
|
+
// Not cloning mutable objects will break the internal state if user mutates the objects.
|
|
679
|
+
const mappedDocs = (_d = (_c = stackbitConfig === null || stackbitConfig === void 0 ? void 0 : stackbitConfig.mapDocuments) === null || _c === void 0 ? void 0 : _c.call(stackbitConfig, {
|
|
680
|
+
documents: lodash_1.default.cloneDeep(csiDocumentsWithSource),
|
|
681
|
+
models: lodash_1.default.cloneDeep(models)
|
|
682
|
+
})) !== null && _d !== void 0 ? _d : csiDocumentsWithSource;
|
|
683
|
+
documentMapByContentSource = (0, content_store_utils_1.groupDocumentsByContentSource)({ documents: mappedDocs });
|
|
684
|
+
}
|
|
576
685
|
const modelMapByContentSource = (0, content_store_utils_1.groupModelsByContentSource)({ models: models });
|
|
577
|
-
const documentMapByContentSource = (0, content_store_utils_1.groupDocumentsByContentSource)({ documents: mappedDocs });
|
|
578
686
|
const contentSourceDataArr = contentSourceRawDataArr.map((csData) => {
|
|
579
687
|
const modelMap = lodash_1.default.get(modelMapByContentSource, [csData.srcType, csData.srcProjectId], {});
|
|
580
|
-
const
|
|
688
|
+
const csiDocuments = documentMapByContentSource
|
|
689
|
+
? lodash_1.default.get(documentMapByContentSource, [csData.srcType, csData.srcProjectId], [])
|
|
690
|
+
: csData.csiDocuments;
|
|
581
691
|
const documents = (0, csi_to_store_docs_converter_1.mapCSIDocumentsToStoreDocuments)({
|
|
582
|
-
csiDocuments:
|
|
692
|
+
csiDocuments: csiDocuments,
|
|
583
693
|
contentSourceInstance: csData.instance,
|
|
584
694
|
defaultLocaleCode: csData.defaultLocaleCode,
|
|
585
695
|
modelMap: modelMap
|
|
@@ -622,6 +732,9 @@ class ContentStore {
|
|
|
622
732
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
623
733
|
return contentSourceData.instance.getProjectEnvironment();
|
|
624
734
|
}
|
|
735
|
+
usesContentSourcePresets() {
|
|
736
|
+
return Boolean(this.presetsContentSource);
|
|
737
|
+
}
|
|
625
738
|
async hasAccess({ srcType, srcProjectId, user }) {
|
|
626
739
|
let contentSourceDataArr;
|
|
627
740
|
if (srcType && srcProjectId) {
|
|
@@ -697,50 +810,22 @@ class ContentStore {
|
|
|
697
810
|
};
|
|
698
811
|
}
|
|
699
812
|
getSiteMapEntries({ locale } = {}) {
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
documents: accum.documents.concat((0, store_to_csi_docs_converter_1.mapStoreDocumentsToCSIDocumentsWithSource)(contentSourceData.documents))
|
|
713
|
-
};
|
|
714
|
-
}, { models: [], documents: [] });
|
|
715
|
-
const siteMapEntries = this.stackbitConfig.siteMap(siteMapOptions).reduce((accum, siteMapEntry) => {
|
|
716
|
-
// The site map entries are provided by user, sanitize them and filter out illegal entries
|
|
717
|
-
if (!siteMapEntry) {
|
|
718
|
-
return accum;
|
|
719
|
-
}
|
|
720
|
-
if (typeof siteMapEntry.urlPath !== 'string') {
|
|
721
|
-
return accum;
|
|
722
|
-
}
|
|
723
|
-
if ('document' in siteMapEntry) {
|
|
724
|
-
const doc = siteMapEntry.document;
|
|
725
|
-
if (!doc.srcType || !doc.srcProjectId || !doc.modelName || !doc.id) {
|
|
726
|
-
return accum;
|
|
813
|
+
const siteMapEntries = lodash_1.default.reduce(this.siteMapEntryGroups, (accum, siteMapEntryGroup) => {
|
|
814
|
+
return lodash_1.default.reduce(siteMapEntryGroup, (accum, siteMapEntry) => {
|
|
815
|
+
if (!siteMapEntry.label) {
|
|
816
|
+
const fieldLabelValue = (0, site_map_1.getDocumentFieldLabelValueForSiteMapEntry)({
|
|
817
|
+
siteMapEntry,
|
|
818
|
+
locale,
|
|
819
|
+
contentSourceDataById: this.contentSourceDataById
|
|
820
|
+
});
|
|
821
|
+
siteMapEntry = {
|
|
822
|
+
...siteMapEntry,
|
|
823
|
+
label: fieldLabelValue !== null && fieldLabelValue !== void 0 ? fieldLabelValue : siteMapEntry.urlPath
|
|
824
|
+
};
|
|
727
825
|
}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
siteMapEntry = {
|
|
732
|
-
...siteMapEntry,
|
|
733
|
-
label: fieldLabelValue !== null && fieldLabelValue !== void 0 ? fieldLabelValue : siteMapEntry.urlPath
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
if (!siteMapEntry.stableId) {
|
|
737
|
-
siteMapEntry = {
|
|
738
|
-
...siteMapEntry,
|
|
739
|
-
stableId: 'document' in siteMapEntry ? siteMapEntry.document.id : siteMapEntry.urlPath
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
accum.push(siteMapEntry);
|
|
743
|
-
return accum;
|
|
826
|
+
accum.push(siteMapEntry);
|
|
827
|
+
return accum;
|
|
828
|
+
}, accum);
|
|
744
829
|
}, []);
|
|
745
830
|
return lodash_1.default.isEmpty(locale) ? siteMapEntries : siteMapEntries.filter((siteMapEntry) => !siteMapEntry.locale || siteMapEntry.locale === locale);
|
|
746
831
|
}
|
|
@@ -754,7 +839,8 @@ class ContentStore {
|
|
|
754
839
|
const currentDocuments = lodash_1.default.isEmpty(locale)
|
|
755
840
|
? contentSourceData.documents
|
|
756
841
|
: contentSourceData.documents.filter((document) => !document.locale || document.locale === locale);
|
|
757
|
-
|
|
842
|
+
const filteredDocuments = currentDocuments.filter((document) => document.srcModelName !== exports.StackbitPresetModelName);
|
|
843
|
+
return documents.concat(filteredDocuments);
|
|
758
844
|
}, []);
|
|
759
845
|
}
|
|
760
846
|
getAsset({ srcAssetId, srcProjectId, srcType }) {
|
|
@@ -780,7 +866,8 @@ class ContentStore {
|
|
|
780
866
|
? contentSourceData.assets.filter((asset) => !asset.locale || asset.locale === locale)
|
|
781
867
|
: contentSourceData.assets;
|
|
782
868
|
const currentLocale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
|
|
783
|
-
const
|
|
869
|
+
const filteredDocuments = documents.filter((document) => document.srcModelName !== exports.StackbitPresetModelName);
|
|
870
|
+
const documentObjects = (0, store_to_api_docs_converter_1.mapDocumentsToLocalizedApiObjects)(filteredDocuments, currentLocale);
|
|
784
871
|
const imageObjects = (0, store_to_api_docs_converter_1.mapAssetsToLocalizedApiImages)(assets, currentLocale);
|
|
785
872
|
return objects.concat(documentObjects, imageObjects);
|
|
786
873
|
}, []);
|
|
@@ -889,6 +976,53 @@ class ContentStore {
|
|
|
889
976
|
});
|
|
890
977
|
return { srcDocumentId: updatedDocument.id };
|
|
891
978
|
}
|
|
979
|
+
async createPreset({ preset, thumbnailAsset, user }) {
|
|
980
|
+
var _a;
|
|
981
|
+
if (!this.presetsContentSource) {
|
|
982
|
+
throw new Error('No content source available for preset saving');
|
|
983
|
+
}
|
|
984
|
+
let thumbnail;
|
|
985
|
+
if (thumbnailAsset) {
|
|
986
|
+
const assets = await this.uploadAssets({
|
|
987
|
+
srcType: this.presetsContentSource.getContentSourceType(),
|
|
988
|
+
srcProjectId: this.presetsContentSource.getProjectId(),
|
|
989
|
+
assets: [thumbnailAsset],
|
|
990
|
+
user
|
|
991
|
+
});
|
|
992
|
+
thumbnail = (_a = assets[0]) === null || _a === void 0 ? void 0 : _a.objectId;
|
|
993
|
+
}
|
|
994
|
+
const contentSourceData = this.getContentSourceDataByIdOrThrow((0, content_store_utils_1.getContentSourceIdForContentSource)(this.presetsContentSource));
|
|
995
|
+
const document = await this.createDocument({
|
|
996
|
+
srcType: this.presetsContentSource.getContentSourceType(),
|
|
997
|
+
srcProjectId: this.presetsContentSource.getProjectId(),
|
|
998
|
+
modelName: exports.StackbitPresetModelName,
|
|
999
|
+
object: {
|
|
1000
|
+
...(0, preset_utils_1.getDocumentObjectFromPreset)(preset, contentSourceData.modelMap[exports.StackbitPresetModelName]),
|
|
1001
|
+
thumbnail
|
|
1002
|
+
},
|
|
1003
|
+
user
|
|
1004
|
+
});
|
|
1005
|
+
return { srcDocumentId: document.srcDocumentId };
|
|
1006
|
+
}
|
|
1007
|
+
async deletePreset({ presetId, user }) {
|
|
1008
|
+
if (!this.presetsContentSource) {
|
|
1009
|
+
throw new Error('No content source available for preset deleting');
|
|
1010
|
+
}
|
|
1011
|
+
await this.deleteDocument({
|
|
1012
|
+
srcType: this.presetsContentSource.getContentSourceType(),
|
|
1013
|
+
srcProjectId: this.presetsContentSource.getProjectId(),
|
|
1014
|
+
srcDocumentId: presetId,
|
|
1015
|
+
user
|
|
1016
|
+
});
|
|
1017
|
+
// we delete presets immediately because some CMSs don't notify us
|
|
1018
|
+
// when documents have been deleted.
|
|
1019
|
+
this.onContentChange((0, content_store_utils_1.getContentSourceIdForContentSource)(this.presetsContentSource), {
|
|
1020
|
+
documents: [],
|
|
1021
|
+
deletedDocumentIds: [presetId],
|
|
1022
|
+
assets: [],
|
|
1023
|
+
deletedAssetIds: []
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
892
1026
|
async uploadAndLinkAsset({ srcType, srcProjectId, srcDocumentId, fieldPath, asset, index, locale, user }) {
|
|
893
1027
|
this.logger.debug('uploadAndLinkAsset', { srcType, srcProjectId, srcDocumentId, fieldPath, index, locale });
|
|
894
1028
|
// get the document that is being updated
|
|
@@ -1199,7 +1333,8 @@ class ContentStore {
|
|
|
1199
1333
|
const contentSourceDocuments = lodash_1.default.isEmpty(locale)
|
|
1200
1334
|
? contentSourceData.documents
|
|
1201
1335
|
: contentSourceData.documents.filter((document) => !document.locale || document.locale === locale);
|
|
1202
|
-
|
|
1336
|
+
const filteredDocuments = contentSourceDocuments.filter((document) => document.srcModelName !== exports.StackbitPresetModelName);
|
|
1337
|
+
documents.push(...filteredDocuments);
|
|
1203
1338
|
if (contentSourceData.defaultLocaleCode) {
|
|
1204
1339
|
defaultLocales[contentSourceId] = contentSourceData.defaultLocaleCode;
|
|
1205
1340
|
}
|