@stackbit/cms-core 0.2.1 → 0.3.0-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.
- package/dist/content-store-utils.d.ts +5 -1
- package/dist/content-store-utils.d.ts.map +1 -1
- package/dist/content-store-utils.js +28 -3
- package/dist/content-store-utils.js.map +1 -1
- package/dist/content-store.d.ts +12 -1
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +399 -177
- package/dist/content-store.js.map +1 -1
- package/dist/types/content-store-document-fields.d.ts +26 -4
- package/dist/types/content-store-document-fields.d.ts.map +1 -1
- package/dist/types/content-store-documents.d.ts +14 -3
- package/dist/types/content-store-documents.d.ts.map +1 -1
- package/dist/types/content-store-types.d.ts +7 -1
- package/dist/types/content-store-types.d.ts.map +1 -1
- package/dist/utils/backward-compatibility.d.ts +184 -0
- package/dist/utils/backward-compatibility.d.ts.map +1 -0
- package/dist/utils/backward-compatibility.js +151 -0
- package/dist/utils/backward-compatibility.js.map +1 -0
- package/dist/utils/config-delegate.d.ts +11 -0
- package/dist/utils/config-delegate.d.ts.map +1 -0
- package/dist/utils/config-delegate.js +226 -0
- package/dist/utils/config-delegate.js.map +1 -0
- package/dist/utils/create-update-csi-docs.d.ts +7 -5
- package/dist/utils/create-update-csi-docs.d.ts.map +1 -1
- package/dist/utils/create-update-csi-docs.js +24 -24
- package/dist/utils/create-update-csi-docs.js.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.d.ts +17 -3
- package/dist/utils/csi-to-store-docs-converter.d.ts.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.js +187 -47
- package/dist/utils/csi-to-store-docs-converter.js.map +1 -1
- package/dist/utils/site-map.d.ts.map +1 -1
- package/dist/utils/site-map.js +4 -1
- package/dist/utils/site-map.js.map +1 -1
- package/dist/utils/store-to-api-docs-converter.d.ts +6 -1
- package/dist/utils/store-to-api-docs-converter.d.ts.map +1 -1
- package/dist/utils/store-to-api-docs-converter.js +140 -51
- package/dist/utils/store-to-api-docs-converter.js.map +1 -1
- package/dist/utils/store-to-csi-docs-converter.d.ts +1 -0
- package/dist/utils/store-to-csi-docs-converter.d.ts.map +1 -1
- package/dist/utils/store-to-csi-docs-converter.js +2 -1
- package/dist/utils/store-to-csi-docs-converter.js.map +1 -1
- package/package.json +5 -5
- package/src/content-store-utils.ts +40 -6
- package/src/content-store.ts +552 -299
- package/src/types/content-store-document-fields.ts +16 -4
- package/src/types/content-store-documents.ts +12 -3
- package/src/types/content-store-types.ts +4 -1
- package/src/utils/backward-compatibility.ts +269 -0
- package/src/utils/config-delegate.ts +277 -0
- package/src/utils/create-update-csi-docs.ts +47 -50
- package/src/utils/csi-to-store-docs-converter.ts +256 -43
- package/src/utils/site-map.ts +19 -7
- package/src/utils/store-to-api-docs-converter.ts +185 -52
- package/src/utils/store-to-csi-docs-converter.ts +1 -1
package/dist/content-store.js
CHANGED
|
@@ -21,6 +21,14 @@ 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
23
|
const preset_utils_1 = require("./utils/preset-utils");
|
|
24
|
+
const backward_compatibility_1 = require("./utils/backward-compatibility");
|
|
25
|
+
const config_delegate_1 = require("./utils/config-delegate");
|
|
26
|
+
const ContentStoreEventType = {
|
|
27
|
+
YamlModelFilesChange: 'yamlModelFilesChange',
|
|
28
|
+
PresetFilesChange: 'presetFilesChange',
|
|
29
|
+
ContentSourceInvalidateSchema: 'contentSourceInvalidateSchema',
|
|
30
|
+
ContentSourceContentChange: 'contentSourceContentChange'
|
|
31
|
+
};
|
|
24
32
|
exports.StackbitPresetModelName = 'stackbitPreset';
|
|
25
33
|
class ContentStore {
|
|
26
34
|
constructor(options) {
|
|
@@ -32,6 +40,8 @@ class ContentStore {
|
|
|
32
40
|
this.modelExtensions = null;
|
|
33
41
|
this.presets = {};
|
|
34
42
|
this.siteMapEntryGroups = {};
|
|
43
|
+
this.processingContentSourcesPromise = null;
|
|
44
|
+
this.contentStoreEventQueue = [];
|
|
35
45
|
this.logger = options.logger.createLogger({ label: 'content-store' });
|
|
36
46
|
this.userLogger = options.userLogger.createLogger({ label: 'content-store' });
|
|
37
47
|
this.localDev = options.localDev;
|
|
@@ -112,8 +122,9 @@ class ContentStore {
|
|
|
112
122
|
* reducing the CMS API usage.
|
|
113
123
|
*/
|
|
114
124
|
handleTimerTimeout() {
|
|
125
|
+
var _a;
|
|
115
126
|
for (const contentSourceInstance of this.contentSources) {
|
|
116
|
-
contentSourceInstance.stopWatchingContentUpdates();
|
|
127
|
+
(_a = contentSourceInstance.stopWatchingContentUpdates) === null || _a === void 0 ? void 0 : _a.call(contentSourceInstance);
|
|
117
128
|
}
|
|
118
129
|
}
|
|
119
130
|
/**
|
|
@@ -134,9 +145,8 @@ class ContentStore {
|
|
|
134
145
|
this.contentUpdatesWatchTimer.stopTimer();
|
|
135
146
|
}
|
|
136
147
|
async onFilesChange(updatedFiles) {
|
|
137
|
-
var _a
|
|
148
|
+
var _a;
|
|
138
149
|
this.logger.debug('onFilesChange');
|
|
139
|
-
let schemaChanged = false;
|
|
140
150
|
if (this.stackbitConfig && !this.stackbitConfig.modelExtensions) {
|
|
141
151
|
// Check if any of the yaml models files were changed. If yaml model files were changed,
|
|
142
152
|
// reload them and merge them with models defined in stackbit config.
|
|
@@ -144,9 +154,11 @@ class ContentStore {
|
|
|
144
154
|
const yamlModelsChanged = updatedFiles.find((updatedFile) => lodash_1.default.some(modelDirs, (modelDir) => updatedFile.startsWith(modelDir)));
|
|
145
155
|
if (yamlModelsChanged) {
|
|
146
156
|
this.logger.debug('identified change in stackbit model files');
|
|
147
|
-
schemaChanged = true;
|
|
148
157
|
this.yamlModels = await this.loadYamlModels({ stackbitConfig: this.stackbitConfig });
|
|
149
158
|
this.configModels = this.mergeConfigModels((_a = this.stackbitConfig.models) !== null && _a !== void 0 ? _a : [], this.yamlModels);
|
|
159
|
+
this.pushContentSourceEvent({
|
|
160
|
+
eventName: ContentStoreEventType.YamlModelFilesChange
|
|
161
|
+
});
|
|
150
162
|
}
|
|
151
163
|
}
|
|
152
164
|
if (this.stackbitConfig) {
|
|
@@ -155,57 +167,36 @@ class ContentStore {
|
|
|
155
167
|
const presetsChanged = updatedFiles.find((updatedFile) => lodash_1.default.some(presetDirs, (presetDir) => updatedFile.startsWith(presetDir)));
|
|
156
168
|
if (presetsChanged && !this.usesContentSourcePresets()) {
|
|
157
169
|
this.logger.debug('identified change in stackbit preset files');
|
|
158
|
-
schemaChanged = true;
|
|
159
170
|
this.presets = await this.loadPresetsFromConfig({ stackbitConfig: this.stackbitConfig });
|
|
171
|
+
this.pushContentSourceEvent({
|
|
172
|
+
eventName: ContentStoreEventType.PresetFilesChange
|
|
173
|
+
});
|
|
160
174
|
}
|
|
161
175
|
}
|
|
162
|
-
const contentSourceIdsWithChangedSchema = [];
|
|
163
|
-
const contentChangeEvents = [];
|
|
164
176
|
for (const contentSourceInstance of this.contentSources) {
|
|
165
177
|
const contentSourceId = (0, content_store_utils_1.getContentSourceIdForContentSource)(contentSourceInstance);
|
|
166
178
|
this.logger.debug(`call onFilesChange for contentSource: ${contentSourceId}`);
|
|
167
|
-
const onFilesChangeResult =
|
|
168
|
-
|
|
169
|
-
//
|
|
170
|
-
//
|
|
171
|
-
if (onFilesChangeResult.
|
|
172
|
-
|
|
173
|
-
|
|
179
|
+
const onFilesChangeResult = await contentSourceInstance.onFilesChange({ updatedFiles: updatedFiles });
|
|
180
|
+
// If the schema was changed in a specific content source, there is no need to process and notify for content changes.
|
|
181
|
+
// Because the schema changes will trigger loadContentSourcesAndProcessData and reload all models and content of that
|
|
182
|
+
// content source and send the schemaChanged notification that will cause the Studio to reload the schema and documents.
|
|
183
|
+
if (onFilesChangeResult.invalidateSchema) {
|
|
184
|
+
this.logger.debug(`schema was invalidated for contentSource: ${contentSourceId}`);
|
|
185
|
+
this.pushContentSourceEvent({
|
|
186
|
+
eventName: ContentStoreEventType.ContentSourceInvalidateSchema,
|
|
187
|
+
contentSourceId: contentSourceId
|
|
188
|
+
});
|
|
174
189
|
}
|
|
175
|
-
else if (onFilesChangeResult.
|
|
176
|
-
|
|
190
|
+
else if (!(0, content_store_utils_1.isContentChangesEmpty)(onFilesChangeResult.contentChanges)) {
|
|
191
|
+
this.logger.debug(`content was changed for contentSource: ${contentSourceId}`);
|
|
192
|
+
this.pushContentSourceEvent({
|
|
193
|
+
eventName: ContentStoreEventType.ContentSourceContentChange,
|
|
194
|
+
contentSourceId: contentSourceId,
|
|
195
|
+
contentChanges: onFilesChangeResult.contentChanges
|
|
196
|
+
});
|
|
177
197
|
}
|
|
178
198
|
}
|
|
179
|
-
|
|
180
|
-
// The processData will update the store with the latest data. And once the Studio receives
|
|
181
|
-
// the schemaChanged notification it will reload all the models and the documents with their latest state.
|
|
182
|
-
if (schemaChanged) {
|
|
183
|
-
await this.loadContentSourcesAndProcessData({ init: false, contentSourceIds: contentSourceIdsWithChangedSchema });
|
|
184
|
-
this.onSchemaChangeCallback();
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
const contentChanges = contentChangeEvents.reduce((contentChanges, { contentSourceId, contentChangeEvent }) => {
|
|
188
|
-
const contentChangeResult = this.onContentChange(contentSourceId, contentChangeEvent);
|
|
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
|
-
};
|
|
195
|
-
}, {
|
|
196
|
-
updatedDocuments: [],
|
|
197
|
-
updatedAssets: [],
|
|
198
|
-
deletedDocuments: [],
|
|
199
|
-
deletedAssets: []
|
|
200
|
-
});
|
|
201
|
-
this.siteMapEntryGroups = await (0, site_map_1.updateSiteMapEntriesWithContentChanges)({
|
|
202
|
-
siteMapEntryGroups: this.siteMapEntryGroups,
|
|
203
|
-
contentChanges,
|
|
204
|
-
stackbitConfig: this.stackbitConfig,
|
|
205
|
-
contentSourceDataById: this.contentSourceDataById
|
|
206
|
-
});
|
|
207
|
-
this.onContentChangeCallback(contentChanges);
|
|
208
|
-
}
|
|
199
|
+
await this.processContentStoreEvents();
|
|
209
200
|
}
|
|
210
201
|
async loadYamlModels({ stackbitConfig }) {
|
|
211
202
|
const yamlModelsResult = await (0, sdk_1.loadYamlModelsFromFiles)(stackbitConfig);
|
|
@@ -278,7 +269,10 @@ class ContentStore {
|
|
|
278
269
|
async loadContentSourcesAndProcessData({ init, contentSourceIds }) {
|
|
279
270
|
var _a, _b, _c, _d, _e;
|
|
280
271
|
this.logger.debug('loadContentSourcesAndProcessData', { init, contentSourceIds });
|
|
281
|
-
|
|
272
|
+
this.processingContentSourcesPromise = (0, utils_1.deferredPromise)();
|
|
273
|
+
const contentSources = ((_b = (_a = this.stackbitConfig) === null || _a === void 0 ? void 0 : _a.contentSources) !== null && _b !== void 0 ? _b : []).map((contentSource) => {
|
|
274
|
+
return (0, backward_compatibility_1.backwardCompatibleContentSource)(contentSource);
|
|
275
|
+
});
|
|
282
276
|
const promises = contentSources.map((contentSourceInstance) => {
|
|
283
277
|
const contentSourceId = (0, content_store_utils_1.getContentSourceIdForContentSource)(contentSourceInstance);
|
|
284
278
|
if (init || !contentSourceIds || contentSourceIds.includes(contentSourceId)) {
|
|
@@ -293,13 +287,10 @@ class ContentStore {
|
|
|
293
287
|
for (let i = 0; i < contentSources.length; i++) {
|
|
294
288
|
const contentSourceDataRaw = contentSourceRawDataArr[i];
|
|
295
289
|
if ((_c = contentSourceDataRaw === null || contentSourceDataRaw === void 0 ? void 0 : contentSourceDataRaw.csiModelMap) === null || _c === void 0 ? void 0 : _c[exports.StackbitPresetModelName]) {
|
|
296
|
-
this.presetsContentSource =
|
|
297
|
-
if
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (init || !contentSourceIds || contentSourceIds.includes(contentSourceId)) {
|
|
301
|
-
this.presets = await this.loadPresetsFromContentSource(contentSourceDataRaw);
|
|
302
|
-
}
|
|
290
|
+
this.presetsContentSource = contentSourceDataRaw.instance;
|
|
291
|
+
// reload presets from content source only if needed
|
|
292
|
+
if (init || !contentSourceIds || contentSourceIds.includes(contentSourceDataRaw.id)) {
|
|
293
|
+
this.presets = await this.loadPresetsFromContentSource(contentSourceDataRaw);
|
|
303
294
|
}
|
|
304
295
|
break;
|
|
305
296
|
}
|
|
@@ -321,37 +312,274 @@ class ContentStore {
|
|
|
321
312
|
stackbitConfig: this.stackbitConfig,
|
|
322
313
|
contentSourceDataById: this.contentSourceDataById
|
|
323
314
|
});
|
|
315
|
+
if (!init) {
|
|
316
|
+
this.onSchemaChangeCallback();
|
|
317
|
+
}
|
|
318
|
+
const processingPromise = this.processingContentSourcesPromise;
|
|
319
|
+
this.processingContentSourcesPromise = null;
|
|
320
|
+
// Do not "await" on processContentStoreEvents as it may introduce a deadlock with
|
|
321
|
+
// the nested loadContentSourcesAndProcessData call which is wrapped by deferWhileRunning.
|
|
322
|
+
this.processContentStoreEvents()
|
|
323
|
+
.catch((error) => {
|
|
324
|
+
this.logger.error('error processing content source events', { error });
|
|
325
|
+
})
|
|
326
|
+
.finally(() => {
|
|
327
|
+
processingPromise.resolve();
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
async processContentStoreEvents() {
|
|
331
|
+
// If the ContentStore is currently loading content sources, return to prevent parallel data updates.
|
|
332
|
+
// This method will be called once current loading cycle ends.
|
|
333
|
+
if (this.processingContentSourcesPromise) {
|
|
334
|
+
return this.processingContentSourcesPromise.promise;
|
|
335
|
+
}
|
|
336
|
+
const contentSourceIdsWithInvalidatedSchema = [];
|
|
337
|
+
const contentChanges = {
|
|
338
|
+
updatedDocuments: [],
|
|
339
|
+
updatedAssets: [],
|
|
340
|
+
deletedDocuments: [],
|
|
341
|
+
deletedAssets: []
|
|
342
|
+
};
|
|
343
|
+
let invalidateSchema = false;
|
|
344
|
+
let presetsUpdated = false;
|
|
345
|
+
const contentSourceEvents = this.contentStoreEventQueue;
|
|
346
|
+
this.contentStoreEventQueue = [];
|
|
347
|
+
for (const contentSourceEvent of contentSourceEvents) {
|
|
348
|
+
if (contentSourceEvent.eventName === ContentStoreEventType.YamlModelFilesChange ||
|
|
349
|
+
contentSourceEvent.eventName === ContentStoreEventType.PresetFilesChange) {
|
|
350
|
+
invalidateSchema = true;
|
|
351
|
+
}
|
|
352
|
+
else if (contentSourceEvent.eventName === ContentStoreEventType.ContentSourceInvalidateSchema) {
|
|
353
|
+
invalidateSchema = true;
|
|
354
|
+
contentSourceIdsWithInvalidatedSchema.push(contentSourceEvent.contentSourceId);
|
|
355
|
+
}
|
|
356
|
+
else if (contentSourceEvent.eventName === ContentStoreEventType.ContentSourceContentChange) {
|
|
357
|
+
const result = this.onContentChange(contentSourceEvent.contentSourceId, contentSourceEvent.contentChanges);
|
|
358
|
+
contentChanges.updatedDocuments = contentChanges.updatedDocuments.concat(result.contentChangeResult.updatedDocuments);
|
|
359
|
+
contentChanges.updatedAssets = contentChanges.updatedAssets.concat(result.contentChangeResult.updatedAssets);
|
|
360
|
+
contentChanges.deletedDocuments = contentChanges.deletedDocuments.concat(result.contentChangeResult.deletedDocuments);
|
|
361
|
+
contentChanges.deletedAssets = contentChanges.deletedAssets.concat(result.contentChangeResult.deletedAssets);
|
|
362
|
+
if (result.presetsUpdated) {
|
|
363
|
+
presetsUpdated = true;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
// If the schema was changed, call loadContentSourcesAndProcessData method, this will reload all the SiteMapEntries and call the onSchemaChangeCallback.
|
|
368
|
+
// As soon as the Studio receives the schemaChanged notification it will reload all the models and the documents.
|
|
369
|
+
if (invalidateSchema) {
|
|
370
|
+
await this.loadContentSourcesAndProcessData({
|
|
371
|
+
init: false,
|
|
372
|
+
contentSourceIds: contentSourceIdsWithInvalidatedSchema
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
// If the schema wasn't changed, update SiteMapEntries with the changed content.
|
|
377
|
+
this.siteMapEntryGroups = await (0, site_map_1.updateSiteMapEntriesWithContentChanges)({
|
|
378
|
+
siteMapEntryGroups: this.siteMapEntryGroups,
|
|
379
|
+
contentChanges: contentChanges,
|
|
380
|
+
stackbitConfig: this.stackbitConfig,
|
|
381
|
+
contentSourceDataById: this.contentSourceDataById
|
|
382
|
+
});
|
|
383
|
+
// If presets were updated, call onSchemaChangeCallback to notify the Studio.
|
|
384
|
+
// The Studio will refresh the models and the documents, so no need to notify
|
|
385
|
+
// content changes in this case.
|
|
386
|
+
if (presetsUpdated) {
|
|
387
|
+
this.onSchemaChangeCallback();
|
|
388
|
+
}
|
|
389
|
+
else if (!(0, content_store_utils_1.isContentChangeResultEmpty)(contentChanges)) {
|
|
390
|
+
this.onContentChangeCallback(contentChanges);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
pushContentSourceEvent(contentStoreEvent) {
|
|
395
|
+
if (contentStoreEvent.eventName === ContentStoreEventType.ContentSourceContentChange) {
|
|
396
|
+
// If a content source enqueued the 'contentSourceInvalidateSchema' event,
|
|
397
|
+
// don't push the 'contentSourceContentChange' event, because 'contentSourceInvalidateSchema'
|
|
398
|
+
// will reload all the content source data.
|
|
399
|
+
const hasContentSourceSchemaChangeEvent = this.contentStoreEventQueue.find((event) => event.eventName === ContentStoreEventType.ContentSourceInvalidateSchema && event.contentSourceId === contentStoreEvent.contentSourceId);
|
|
400
|
+
if (!hasContentSourceSchemaChangeEvent) {
|
|
401
|
+
this.contentStoreEventQueue.push(contentStoreEvent);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
else if (contentStoreEvent.eventName === ContentStoreEventType.ContentSourceInvalidateSchema) {
|
|
405
|
+
// Clear any 'contentSourceContentChange' events for a content source,
|
|
406
|
+
// the 'contentSourceInvalidateSchema' will reload all the content source data.
|
|
407
|
+
this.clearEventsForContentSourceId(contentStoreEvent.contentSourceId);
|
|
408
|
+
this.contentStoreEventQueue.push(contentStoreEvent);
|
|
409
|
+
}
|
|
410
|
+
else if (contentStoreEvent.eventName === ContentStoreEventType.YamlModelFilesChange) {
|
|
411
|
+
this.contentStoreEventQueue = this.contentStoreEventQueue.filter((event) => event.eventName !== ContentStoreEventType.YamlModelFilesChange);
|
|
412
|
+
this.contentStoreEventQueue.push(contentStoreEvent);
|
|
413
|
+
}
|
|
414
|
+
else if (contentStoreEvent.eventName === ContentStoreEventType.PresetFilesChange) {
|
|
415
|
+
this.contentStoreEventQueue = this.contentStoreEventQueue.filter((event) => event.eventName !== ContentStoreEventType.PresetFilesChange);
|
|
416
|
+
this.contentStoreEventQueue.push(contentStoreEvent);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
clearEventsForContentSourceId(contentSourceId) {
|
|
420
|
+
this.contentStoreEventQueue = this.contentStoreEventQueue.filter((contentSourceEvent) => {
|
|
421
|
+
if (contentSourceEvent.eventName === ContentStoreEventType.ContentSourceContentChange ||
|
|
422
|
+
contentSourceEvent.eventName === ContentStoreEventType.ContentSourceInvalidateSchema) {
|
|
423
|
+
return contentSourceEvent.contentSourceId !== contentSourceId;
|
|
424
|
+
}
|
|
425
|
+
return true;
|
|
426
|
+
});
|
|
324
427
|
}
|
|
325
428
|
async loadContentSourceData({ contentSourceInstance, init }) {
|
|
326
|
-
var _a;
|
|
429
|
+
var _a, _b, _c, _d, _e;
|
|
327
430
|
const contentSourceId = (0, content_store_utils_1.getContentSourceIdForContentSource)(contentSourceInstance);
|
|
328
431
|
this.logger.debug('loadContentSourceData', { contentSourceId, init });
|
|
432
|
+
// clear content source events emitted by this content source because all the content source data is reloaded
|
|
433
|
+
this.clearEventsForContentSourceId(contentSourceId);
|
|
434
|
+
const localCache = {};
|
|
435
|
+
const getContentSourceDataForCurrentInstance = (methodName) => {
|
|
436
|
+
const contentSourceData = this.contentSourceDataById[contentSourceId];
|
|
437
|
+
if (!contentSourceData) {
|
|
438
|
+
// When loading the content sources for the first time, this.contentSourceDataById will be empty.
|
|
439
|
+
// However, while being loaded, content sources may call cache methods, for example a content
|
|
440
|
+
// source may call getModelByName from within getDocuments. In this case, return locally cached data.
|
|
441
|
+
if (this.processingContentSourcesPromise) {
|
|
442
|
+
return localCache;
|
|
443
|
+
}
|
|
444
|
+
const atLine = (0, content_store_utils_1.getErrorAtLine)(2, getContentSourceDataForCurrentInstance);
|
|
445
|
+
const errorMessage = `Error executing 'cache.${methodName}' method${atLine}. The content source with id '${contentSourceId}' was not found.`;
|
|
446
|
+
this.logger.error(errorMessage);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
if (contentSourceData.instance !== contentSourceInstance) {
|
|
450
|
+
const atLine = (0, content_store_utils_1.getErrorAtLine)(2, getContentSourceDataForCurrentInstance);
|
|
451
|
+
const errorMessage = `Content source life cycle error! The content source with id '${contentSourceId}' called the 'cache.${methodName}' ` +
|
|
452
|
+
`method${atLine} after the destroy() method was called.`;
|
|
453
|
+
this.logger.error(errorMessage);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
// While loading the content source, it may call cache methods, when this happens, return the
|
|
457
|
+
// stale data overridden with the most frequent loaded data
|
|
458
|
+
if (this.processingContentSourcesPromise) {
|
|
459
|
+
return Object.assign(contentSourceData, localCache);
|
|
460
|
+
}
|
|
461
|
+
return contentSourceData;
|
|
462
|
+
};
|
|
463
|
+
const cache = {
|
|
464
|
+
getSchema: () => {
|
|
465
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('getSchema');
|
|
466
|
+
if (!(contentSourceData === null || contentSourceData === void 0 ? void 0 : contentSourceData.csiSchema)) {
|
|
467
|
+
const atLine = (0, content_store_utils_1.getErrorAtLine)(1);
|
|
468
|
+
const errorMessage = `Content source life cycle error! The content source with id '${contentSourceId}' called the 'cache.getSchema' ` +
|
|
469
|
+
`method${atLine} before the content source's getSchema() method was called.`;
|
|
470
|
+
this.logger.error(errorMessage);
|
|
471
|
+
return { models: [], locales: [], context: null };
|
|
472
|
+
}
|
|
473
|
+
return contentSourceData.csiSchema;
|
|
474
|
+
},
|
|
475
|
+
getModelByName: (modelName) => {
|
|
476
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('getModelByName');
|
|
477
|
+
if (!(contentSourceData === null || contentSourceData === void 0 ? void 0 : contentSourceData.csiModelMap)) {
|
|
478
|
+
const atLine = (0, content_store_utils_1.getErrorAtLine)(1);
|
|
479
|
+
const errorMessage = `Content source life cycle error! The content source with id '${contentSourceId}' called the 'cache.getModelByName' ` +
|
|
480
|
+
`method${atLine} before the content source's getSchema() method was called.`;
|
|
481
|
+
this.logger.error(errorMessage);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
return contentSourceData.csiModelMap[modelName];
|
|
485
|
+
},
|
|
486
|
+
getDocuments: () => {
|
|
487
|
+
var _a;
|
|
488
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('getDocuments');
|
|
489
|
+
return (_a = contentSourceData === null || contentSourceData === void 0 ? void 0 : contentSourceData.csiDocuments) !== null && _a !== void 0 ? _a : [];
|
|
490
|
+
},
|
|
491
|
+
getDocumentById: (documentId) => {
|
|
492
|
+
var _a;
|
|
493
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('getDocumentById');
|
|
494
|
+
return (_a = contentSourceData === null || contentSourceData === void 0 ? void 0 : contentSourceData.csiDocumentMap) === null || _a === void 0 ? void 0 : _a[documentId];
|
|
495
|
+
},
|
|
496
|
+
getAssets: () => {
|
|
497
|
+
var _a;
|
|
498
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('getAssets');
|
|
499
|
+
return (_a = contentSourceData === null || contentSourceData === void 0 ? void 0 : contentSourceData.csiAssets) !== null && _a !== void 0 ? _a : [];
|
|
500
|
+
},
|
|
501
|
+
getAssetById: (assetId) => {
|
|
502
|
+
var _a;
|
|
503
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('getAssetById');
|
|
504
|
+
return (_a = contentSourceData === null || contentSourceData === void 0 ? void 0 : contentSourceData.csiAssetMap) === null || _a === void 0 ? void 0 : _a[assetId];
|
|
505
|
+
},
|
|
506
|
+
updateContent: async (contentChanges) => {
|
|
507
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('updateContent');
|
|
508
|
+
if (!contentSourceData) {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
this.logger.debug('content source called updateContent', { contentSourceId });
|
|
512
|
+
this.pushContentSourceEvent({
|
|
513
|
+
eventName: ContentStoreEventType.ContentSourceContentChange,
|
|
514
|
+
contentSourceId: contentSourceId,
|
|
515
|
+
contentChanges: contentChanges
|
|
516
|
+
});
|
|
517
|
+
await this.processContentStoreEvents();
|
|
518
|
+
},
|
|
519
|
+
invalidateSchema: async () => {
|
|
520
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('invalidateSchema');
|
|
521
|
+
if (!contentSourceData) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
this.logger.debug('content source called invalidateSchema', { contentSourceId });
|
|
525
|
+
this.pushContentSourceEvent({
|
|
526
|
+
eventName: ContentStoreEventType.ContentSourceInvalidateSchema,
|
|
527
|
+
contentSourceId: contentSourceId
|
|
528
|
+
});
|
|
529
|
+
await this.processContentStoreEvents();
|
|
530
|
+
}
|
|
531
|
+
};
|
|
329
532
|
if (init) {
|
|
533
|
+
this.userLogger.info(`Initializing content source: ${contentSourceInstance.getContentSourceType()} (project: ${contentSourceInstance.getProjectId()})`);
|
|
534
|
+
// When stackbit.config.js reloads, it loads new content source instances.
|
|
535
|
+
// Previously loaded content source instances must be destroyed.
|
|
536
|
+
const contentSourceData = this.contentSourceDataById[contentSourceId];
|
|
537
|
+
if (contentSourceData && contentSourceData.instance !== contentSourceInstance) {
|
|
538
|
+
this.logger.debug('destroy previous content source instance', { contentSourceId });
|
|
539
|
+
try {
|
|
540
|
+
(_b = (_a = contentSourceData.instance).stopWatchingContentUpdates) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
541
|
+
await contentSourceData.instance.destroy();
|
|
542
|
+
}
|
|
543
|
+
catch (error) {
|
|
544
|
+
this.logger.debug('error destroying content source instance', { error });
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
// If an instance that wasn't destroyed calls one of the InitOptions method don't return any data.
|
|
330
548
|
await contentSourceInstance.init({
|
|
331
549
|
logger: this.logger,
|
|
332
550
|
userLogger: this.userLogger,
|
|
333
|
-
userCommandSpawner: this.userCommandSpawner,
|
|
334
551
|
localDev: this.localDev,
|
|
335
552
|
webhookUrl: this.getWebhookUrl(contentSourceInstance.getContentSourceType(), contentSourceInstance.getProjectId()),
|
|
553
|
+
userCommandSpawner: this.userCommandSpawner,
|
|
336
554
|
devAppRestartNeeded: this.devAppRestartNeeded,
|
|
555
|
+
cache: cache,
|
|
337
556
|
runCommand: this.runCommand,
|
|
338
557
|
git: this.git
|
|
339
558
|
});
|
|
340
559
|
}
|
|
341
560
|
else {
|
|
342
|
-
contentSourceInstance.stopWatchingContentUpdates();
|
|
343
561
|
await contentSourceInstance.reset();
|
|
344
562
|
}
|
|
345
|
-
const
|
|
563
|
+
const version = await contentSourceInstance.getVersion();
|
|
564
|
+
const csiSchema = await contentSourceInstance.getSchema();
|
|
565
|
+
const csiModels = csiSchema.models;
|
|
346
566
|
const csiModelMap = lodash_1.default.keyBy(csiModels, 'name');
|
|
347
|
-
const locales =
|
|
348
|
-
const defaultLocaleCode = (
|
|
567
|
+
const locales = csiSchema.locales;
|
|
568
|
+
const defaultLocaleCode = (_c = locales === null || locales === void 0 ? void 0 : locales.find((locale) => locale.default)) === null || _c === void 0 ? void 0 : _c.code;
|
|
569
|
+
localCache.csiSchema = csiSchema;
|
|
570
|
+
localCache.csiModels = csiModels;
|
|
571
|
+
localCache.csiModelMap = csiModelMap;
|
|
572
|
+
localCache.locales = locales;
|
|
349
573
|
const csiDocuments = await contentSourceInstance.getDocuments({ modelMap: csiModelMap });
|
|
350
|
-
const csiAssets = await contentSourceInstance.getAssets();
|
|
351
574
|
const csiDocumentMap = lodash_1.default.keyBy(csiDocuments, 'id');
|
|
575
|
+
localCache.csiDocuments = csiDocuments;
|
|
576
|
+
localCache.csiDocumentMap = csiDocumentMap;
|
|
577
|
+
const csiAssets = await contentSourceInstance.getAssets();
|
|
352
578
|
const csiAssetMap = lodash_1.default.keyBy(csiAssets, 'id');
|
|
579
|
+
localCache.csiAssets = csiAssets;
|
|
580
|
+
localCache.csiAssetMap = csiAssetMap;
|
|
353
581
|
const contentStoreAssets = (0, csi_to_store_docs_converter_1.mapCSIAssetsToStoreAssets)({
|
|
354
|
-
csiAssets,
|
|
582
|
+
csiAssets: csiAssets,
|
|
355
583
|
contentSourceInstance,
|
|
356
584
|
defaultLocaleCode
|
|
357
585
|
});
|
|
@@ -359,55 +587,43 @@ class ContentStore {
|
|
|
359
587
|
this.logger.debug('loaded content source data', {
|
|
360
588
|
contentSourceId,
|
|
361
589
|
defaultLocaleCode,
|
|
362
|
-
localesCount: locales.length,
|
|
590
|
+
localesCount: (_d = locales === null || locales === void 0 ? void 0 : locales.length) !== null && _d !== void 0 ? _d : 0,
|
|
363
591
|
modelCount: csiModels.length,
|
|
364
592
|
documentCount: csiDocuments.length,
|
|
365
593
|
assetCount: csiAssets.length
|
|
366
594
|
});
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
});
|
|
391
|
-
this.onContentChangeCallback(result);
|
|
392
|
-
},
|
|
393
|
-
onSchemaChange: async () => {
|
|
394
|
-
var _a;
|
|
395
|
-
if (((_a = this.contentSourceDataById[contentSourceId]) === null || _a === void 0 ? void 0 : _a.instance) !== contentSourceInstance) {
|
|
396
|
-
this.logger.debug('old content source called onSchemaChange', { contentSourceId });
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
this.logger.debug('content source called onSchemaChange', { contentSourceId });
|
|
400
|
-
await this.loadContentSourcesAndProcessData({ init: false, contentSourceIds: [contentSourceId] });
|
|
401
|
-
this.onSchemaChangeCallback();
|
|
402
|
-
}
|
|
403
|
-
});
|
|
595
|
+
if (init) {
|
|
596
|
+
this.userLogger.info(`→ Loaded content source data: ${csiModels.length} model${csiModels.length !== 1 ? 's' : ''}, ${csiDocuments.length} document${csiDocuments.length !== 1 ? 's' : ''} and ${csiAssets.length} asset${csiAssets.length !== 1 ? 's' : ''}`);
|
|
597
|
+
// backward compatibility
|
|
598
|
+
(_e = contentSourceInstance.startWatchingContentUpdates) === null || _e === void 0 ? void 0 : _e.call(contentSourceInstance, {
|
|
599
|
+
getModelMap: () => {
|
|
600
|
+
var _a;
|
|
601
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('getModelMap');
|
|
602
|
+
return (_a = contentSourceData === null || contentSourceData === void 0 ? void 0 : contentSourceData.csiModelMap) !== null && _a !== void 0 ? _a : {};
|
|
603
|
+
},
|
|
604
|
+
getDocument: ({ documentId }) => {
|
|
605
|
+
var _a;
|
|
606
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('getDocument');
|
|
607
|
+
return (_a = contentSourceData === null || contentSourceData === void 0 ? void 0 : contentSourceData.csiDocumentMap) === null || _a === void 0 ? void 0 : _a[documentId];
|
|
608
|
+
},
|
|
609
|
+
getAsset: ({ assetId }) => {
|
|
610
|
+
var _a;
|
|
611
|
+
const contentSourceData = getContentSourceDataForCurrentInstance('getAsset');
|
|
612
|
+
return (_a = contentSourceData === null || contentSourceData === void 0 ? void 0 : contentSourceData.csiAssetMap) === null || _a === void 0 ? void 0 : _a[assetId];
|
|
613
|
+
},
|
|
614
|
+
onContentChange: cache.updateContent,
|
|
615
|
+
onSchemaChange: cache.invalidateSchema
|
|
616
|
+
});
|
|
617
|
+
}
|
|
404
618
|
return {
|
|
405
619
|
id: contentSourceId,
|
|
620
|
+
version: version,
|
|
406
621
|
srcType: contentSourceInstance.getContentSourceType(),
|
|
407
622
|
srcProjectId: contentSourceInstance.getProjectId(),
|
|
408
623
|
instance: contentSourceInstance,
|
|
409
624
|
locales: locales,
|
|
410
625
|
defaultLocaleCode: defaultLocaleCode,
|
|
626
|
+
csiSchema: csiSchema,
|
|
411
627
|
csiModels: csiModels,
|
|
412
628
|
csiModelMap: csiModelMap,
|
|
413
629
|
csiDocuments: csiDocuments,
|
|
@@ -418,17 +634,22 @@ class ContentStore {
|
|
|
418
634
|
assetMap: assetMap
|
|
419
635
|
};
|
|
420
636
|
}
|
|
421
|
-
onContentChange(contentSourceId,
|
|
422
|
-
|
|
423
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
637
|
+
onContentChange(contentSourceId, contentChanges) {
|
|
638
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
424
639
|
// certain content changes, like preset changes are interpreted as schema changes
|
|
425
|
-
let
|
|
640
|
+
let presetsUpdated = false;
|
|
641
|
+
const contentChangesReq = {
|
|
642
|
+
documents: (_a = contentChanges.documents) !== null && _a !== void 0 ? _a : [],
|
|
643
|
+
assets: (_b = contentChanges.assets) !== null && _b !== void 0 ? _b : [],
|
|
644
|
+
deletedDocumentIds: (_c = contentChanges.deletedDocumentIds) !== null && _c !== void 0 ? _c : [],
|
|
645
|
+
deletedAssetIds: (_d = contentChanges.deletedAssetIds) !== null && _d !== void 0 ? _d : []
|
|
646
|
+
};
|
|
426
647
|
this.logger.debug('onContentChange', {
|
|
427
648
|
contentSourceId,
|
|
428
|
-
documentCount:
|
|
429
|
-
assetCount:
|
|
430
|
-
deletedDocumentCount:
|
|
431
|
-
deletedAssetCount:
|
|
649
|
+
documentCount: contentChangesReq.documents.length,
|
|
650
|
+
assetCount: contentChangesReq.assets.length,
|
|
651
|
+
deletedDocumentCount: contentChangesReq.deletedDocumentIds.length,
|
|
652
|
+
deletedAssetCount: contentChangesReq.deletedAssetIds.length
|
|
432
653
|
});
|
|
433
654
|
const result = {
|
|
434
655
|
updatedDocuments: [],
|
|
@@ -438,12 +659,12 @@ class ContentStore {
|
|
|
438
659
|
};
|
|
439
660
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
440
661
|
// update contentSourceData with deleted documents
|
|
441
|
-
|
|
662
|
+
contentChangesReq.deletedDocumentIds.forEach((docId) => {
|
|
442
663
|
var _a;
|
|
443
664
|
// remove preset, make sure there is something to remove first because
|
|
444
665
|
// were explicitly calling onContentChange from deletePreset as well
|
|
445
666
|
if (this.presets[docId] && ((_a = contentSourceData.csiDocumentMap[docId]) === null || _a === void 0 ? void 0 : _a.modelName) === exports.StackbitPresetModelName) {
|
|
446
|
-
|
|
667
|
+
presetsUpdated = true;
|
|
447
668
|
const preset = this.presets[docId];
|
|
448
669
|
const model = contentSourceData.modelMap[preset.modelName];
|
|
449
670
|
delete this.presets[docId];
|
|
@@ -469,7 +690,7 @@ class ContentStore {
|
|
|
469
690
|
});
|
|
470
691
|
});
|
|
471
692
|
// update contentSourceData with deleted assets
|
|
472
|
-
|
|
693
|
+
contentChangesReq.deletedAssetIds.forEach((assetId) => {
|
|
473
694
|
// delete document from asset map
|
|
474
695
|
delete contentSourceData.assetMap[assetId];
|
|
475
696
|
delete contentSourceData.csiAssetMap[assetId];
|
|
@@ -487,9 +708,9 @@ class ContentStore {
|
|
|
487
708
|
});
|
|
488
709
|
});
|
|
489
710
|
// map csi documents through stackbitConfig.mapDocuments
|
|
490
|
-
let mappedDocs =
|
|
491
|
-
if ((
|
|
492
|
-
const csiDocumentsWithSource =
|
|
711
|
+
let mappedDocs = contentChangesReq.documents;
|
|
712
|
+
if ((_e = this.stackbitConfig) === null || _e === void 0 ? void 0 : _e.mapDocuments) {
|
|
713
|
+
const csiDocumentsWithSource = contentChangesReq.documents.map((csiDocument) => ({
|
|
493
714
|
srcType: contentSourceData.srcType,
|
|
494
715
|
srcProjectId: contentSourceData.srcProjectId,
|
|
495
716
|
...csiDocument
|
|
@@ -502,32 +723,36 @@ class ContentStore {
|
|
|
502
723
|
};
|
|
503
724
|
});
|
|
504
725
|
mappedDocs =
|
|
505
|
-
(
|
|
726
|
+
(_h = (_g = (_f = this.stackbitConfig) === null || _f === void 0 ? void 0 : _f.mapDocuments) === null || _g === void 0 ? void 0 : _g.call(_f, {
|
|
506
727
|
documents: lodash_1.default.cloneDeep(csiDocumentsWithSource),
|
|
507
728
|
models: lodash_1.default.cloneDeep(modelsWithSource)
|
|
508
|
-
})) !== null &&
|
|
729
|
+
})) !== null && _h !== void 0 ? _h : csiDocumentsWithSource;
|
|
509
730
|
}
|
|
510
731
|
// map csi documents and assets to content store documents and assets
|
|
511
732
|
const documents = (0, csi_to_store_docs_converter_1.mapCSIDocumentsToStoreDocuments)({
|
|
512
733
|
csiDocuments: mappedDocs,
|
|
513
734
|
contentSourceInstance: contentSourceData.instance,
|
|
514
735
|
modelMap: contentSourceData.modelMap,
|
|
515
|
-
defaultLocaleCode: contentSourceData.defaultLocaleCode
|
|
736
|
+
defaultLocaleCode: contentSourceData.defaultLocaleCode,
|
|
737
|
+
createConfigDelegate: (0, config_delegate_1.getCreateConfigDelegateThunk)({
|
|
738
|
+
getContentSourceDataById: () => this.contentSourceDataById,
|
|
739
|
+
logger: this.userLogger
|
|
740
|
+
})
|
|
516
741
|
});
|
|
517
742
|
const assets = (0, csi_to_store_docs_converter_1.mapCSIAssetsToStoreAssets)({
|
|
518
|
-
csiAssets:
|
|
743
|
+
csiAssets: contentChangesReq.assets,
|
|
519
744
|
contentSourceInstance: contentSourceData.instance,
|
|
520
745
|
defaultLocaleCode: contentSourceData.defaultLocaleCode
|
|
521
746
|
});
|
|
522
747
|
// update contentSourceData with new or updated documents and assets
|
|
523
|
-
Object.assign(contentSourceData.csiDocumentMap, lodash_1.default.keyBy(
|
|
524
|
-
Object.assign(contentSourceData.csiAssetMap, lodash_1.default.keyBy(
|
|
748
|
+
Object.assign(contentSourceData.csiDocumentMap, lodash_1.default.keyBy(contentChangesReq.documents, 'id'));
|
|
749
|
+
Object.assign(contentSourceData.csiAssetMap, lodash_1.default.keyBy(contentChangesReq.assets, 'id'));
|
|
525
750
|
Object.assign(contentSourceData.documentMap, lodash_1.default.keyBy(documents, 'srcObjectId'));
|
|
526
751
|
Object.assign(contentSourceData.assetMap, lodash_1.default.keyBy(assets, 'srcObjectId'));
|
|
527
752
|
for (let idx = 0; idx < documents.length; idx++) {
|
|
528
753
|
// the indexes of mapped documents and documents from changeEvent are the same
|
|
529
754
|
const document = documents[idx];
|
|
530
|
-
const csiDocument =
|
|
755
|
+
const csiDocument = contentChangesReq.documents[idx];
|
|
531
756
|
const dataIndex = contentSourceData.documents.findIndex((existingDoc) => existingDoc.srcObjectId === document.srcObjectId);
|
|
532
757
|
if (dataIndex === -1) {
|
|
533
758
|
contentSourceData.documents.push(document);
|
|
@@ -538,7 +763,7 @@ class ContentStore {
|
|
|
538
763
|
contentSourceData.csiDocuments.splice(dataIndex, 1, csiDocument);
|
|
539
764
|
}
|
|
540
765
|
if (csiDocument.modelName === exports.StackbitPresetModelName) {
|
|
541
|
-
|
|
766
|
+
presetsUpdated = true;
|
|
542
767
|
const preset = (0, preset_utils_1.getPresetFromDocument)({
|
|
543
768
|
srcType: contentSourceData.srcType,
|
|
544
769
|
srcProjectId: contentSourceData.srcProjectId,
|
|
@@ -550,7 +775,7 @@ class ContentStore {
|
|
|
550
775
|
this.presets[csiDocument.id] = preset;
|
|
551
776
|
if (dataIndex === -1) {
|
|
552
777
|
//TODO recalculate assets as well
|
|
553
|
-
(
|
|
778
|
+
(_k = (_j = contentSourceData.modelMap[preset.modelName]) === null || _j === void 0 ? void 0 : _j.presets) === null || _k === void 0 ? void 0 : _k.push(csiDocument.id);
|
|
554
779
|
}
|
|
555
780
|
}
|
|
556
781
|
}
|
|
@@ -563,7 +788,7 @@ class ContentStore {
|
|
|
563
788
|
for (let idx = 0; idx < assets.length; idx++) {
|
|
564
789
|
// the indexes of mapped assets and assets from changeEvent are the same
|
|
565
790
|
const asset = assets[idx];
|
|
566
|
-
const csiAsset =
|
|
791
|
+
const csiAsset = contentChangesReq.assets[idx];
|
|
567
792
|
const index = contentSourceData.assets.findIndex((existingAsset) => existingAsset.srcObjectId === asset.srcObjectId);
|
|
568
793
|
if (index === -1) {
|
|
569
794
|
contentSourceData.assets.push(asset);
|
|
@@ -580,10 +805,10 @@ class ContentStore {
|
|
|
580
805
|
srcObjectId: asset.srcObjectId
|
|
581
806
|
});
|
|
582
807
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
808
|
+
return {
|
|
809
|
+
contentChangeResult: result,
|
|
810
|
+
presetsUpdated
|
|
811
|
+
};
|
|
587
812
|
}
|
|
588
813
|
async processData({ stackbitConfig, configModels, presets, contentSourceRawDataArr }) {
|
|
589
814
|
// Group models from all content sources by their names
|
|
@@ -704,8 +929,12 @@ class ContentStore {
|
|
|
704
929
|
const documents = (0, csi_to_store_docs_converter_1.mapCSIDocumentsToStoreDocuments)({
|
|
705
930
|
csiDocuments: csiDocuments,
|
|
706
931
|
contentSourceInstance: csData.instance,
|
|
932
|
+
modelMap: modelMap,
|
|
707
933
|
defaultLocaleCode: csData.defaultLocaleCode,
|
|
708
|
-
|
|
934
|
+
createConfigDelegate: (0, config_delegate_1.getCreateConfigDelegateThunk)({
|
|
935
|
+
getContentSourceDataById: () => this.contentSourceDataById,
|
|
936
|
+
logger: this.userLogger
|
|
937
|
+
})
|
|
709
938
|
});
|
|
710
939
|
return {
|
|
711
940
|
...csData,
|
|
@@ -717,6 +946,16 @@ class ContentStore {
|
|
|
717
946
|
});
|
|
718
947
|
return lodash_1.default.keyBy(contentSourceDataArr, 'id');
|
|
719
948
|
}
|
|
949
|
+
getContentSourceMeta() {
|
|
950
|
+
return lodash_1.default.reduce(this.contentSourceDataById, (result, contentSourceData) => {
|
|
951
|
+
return result.concat({
|
|
952
|
+
srcType: contentSourceData.srcType,
|
|
953
|
+
srcProjectId: contentSourceData.srcProjectId,
|
|
954
|
+
srcVersion: contentSourceData.version.contentSourceVersion,
|
|
955
|
+
csiVersion: contentSourceData.version.interfaceVersion
|
|
956
|
+
});
|
|
957
|
+
}, []);
|
|
958
|
+
}
|
|
720
959
|
getModels() {
|
|
721
960
|
return lodash_1.default.reduce(this.contentSourceDataById, (result, contentSourceData) => {
|
|
722
961
|
const contentSourceType = contentSourceData.instance.getContentSourceType();
|
|
@@ -762,14 +1001,7 @@ class ContentStore {
|
|
|
762
1001
|
const srcType = contentSourceData.srcType;
|
|
763
1002
|
const srcProjectId = contentSourceData.srcProjectId;
|
|
764
1003
|
const userContext = (0, content_store_utils_1.getUserContextForSrcType)(srcType, user);
|
|
765
|
-
|
|
766
|
-
// backwards compatibility with older CSI version
|
|
767
|
-
if (typeof result === 'boolean') {
|
|
768
|
-
result = {
|
|
769
|
-
hasConnection: result,
|
|
770
|
-
hasPermissions: result
|
|
771
|
-
};
|
|
772
|
-
}
|
|
1004
|
+
const result = await contentSourceData.instance.hasAccess({ userContext });
|
|
773
1005
|
return {
|
|
774
1006
|
hasConnection: accum.hasConnection && result.hasConnection,
|
|
775
1007
|
hasPermissions: accum.hasPermissions && result.hasPermissions,
|
|
@@ -857,7 +1089,7 @@ class ContentStore {
|
|
|
857
1089
|
const contentSourceData = this.getContentSourceDataByIdOrThrow(contentSourceId);
|
|
858
1090
|
return contentSourceData.documentMap[srcDocumentId];
|
|
859
1091
|
}
|
|
860
|
-
getDocuments({ locale }) {
|
|
1092
|
+
getDocuments({ locale } = {}) {
|
|
861
1093
|
return lodash_1.default.reduce(this.contentSourceDataById, (documents, contentSourceData) => {
|
|
862
1094
|
const currentDocuments = lodash_1.default.isEmpty(locale)
|
|
863
1095
|
? contentSourceData.documents
|
|
@@ -885,18 +1117,16 @@ class ContentStore {
|
|
|
885
1117
|
let documents = objectIds
|
|
886
1118
|
? contentSourceData.documents.filter((document) => objectIds.includes(document.srcObjectId))
|
|
887
1119
|
: contentSourceData.documents;
|
|
888
|
-
documents = hasExplicitLocale
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
let assets = objectIds
|
|
892
|
-
? contentSourceData.assets.filter((asset) => objectIds.includes(asset.srcObjectId))
|
|
893
|
-
: contentSourceData.assets;
|
|
894
|
-
assets = hasExplicitLocale
|
|
895
|
-
? assets.filter((asset) => !asset.locale || asset.locale === locale)
|
|
896
|
-
: assets;
|
|
1120
|
+
documents = hasExplicitLocale ? documents.filter((document) => !document.locale || document.locale === locale) : documents;
|
|
1121
|
+
let assets = objectIds ? contentSourceData.assets.filter((asset) => objectIds.includes(asset.srcObjectId)) : contentSourceData.assets;
|
|
1122
|
+
assets = hasExplicitLocale ? assets.filter((asset) => !asset.locale || asset.locale === locale) : assets;
|
|
897
1123
|
const currentLocale = locale !== null && locale !== void 0 ? locale : contentSourceData.defaultLocaleCode;
|
|
898
1124
|
const filteredDocuments = documents.filter((document) => document.srcModelName !== exports.StackbitPresetModelName);
|
|
899
|
-
const documentObjects = (0, store_to_api_docs_converter_1.mapDocumentsToLocalizedApiObjects)(
|
|
1125
|
+
const documentObjects = (0, store_to_api_docs_converter_1.mapDocumentsToLocalizedApiObjects)({
|
|
1126
|
+
documents: filteredDocuments,
|
|
1127
|
+
locale: currentLocale,
|
|
1128
|
+
delegate: (0, config_delegate_1.createConfigDelegate)({ contentSourceDataById: this.contentSourceDataById, logger: this.userLogger })
|
|
1129
|
+
});
|
|
900
1130
|
const imageObjects = (0, store_to_api_docs_converter_1.mapAssetsToLocalizedApiImages)(assets, this.staticAssetsPublicPath, currentLocale);
|
|
901
1131
|
return objects.concat(documentObjects, imageObjects);
|
|
902
1132
|
}, []);
|
|
@@ -1009,7 +1239,7 @@ class ContentStore {
|
|
|
1009
1239
|
refProjectId: refProjectId
|
|
1010
1240
|
});
|
|
1011
1241
|
}
|
|
1012
|
-
|
|
1242
|
+
await contentSourceData.instance.updateDocument({
|
|
1013
1243
|
document: csiDocument,
|
|
1014
1244
|
modelMap: csiModelMap,
|
|
1015
1245
|
userContext: userContext,
|
|
@@ -1032,7 +1262,7 @@ class ContentStore {
|
|
|
1032
1262
|
}
|
|
1033
1263
|
]
|
|
1034
1264
|
});
|
|
1035
|
-
return { srcDocumentId:
|
|
1265
|
+
return { srcDocumentId: srcDocumentId, createdDocumentId: result.srcDocumentId };
|
|
1036
1266
|
}
|
|
1037
1267
|
async createPreset({ preset, thumbnailAsset, user }) {
|
|
1038
1268
|
var _a;
|
|
@@ -1074,12 +1304,18 @@ class ContentStore {
|
|
|
1074
1304
|
});
|
|
1075
1305
|
// we delete presets immediately because some CMSs don't notify us
|
|
1076
1306
|
// when documents have been deleted.
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1307
|
+
const contentSourceId = (0, content_store_utils_1.getContentSourceIdForContentSource)(this.presetsContentSource);
|
|
1308
|
+
this.pushContentSourceEvent({
|
|
1309
|
+
eventName: ContentStoreEventType.ContentSourceContentChange,
|
|
1310
|
+
contentSourceId: contentSourceId,
|
|
1311
|
+
contentChanges: {
|
|
1312
|
+
documents: [],
|
|
1313
|
+
deletedDocumentIds: [presetId],
|
|
1314
|
+
assets: [],
|
|
1315
|
+
deletedAssetIds: []
|
|
1316
|
+
}
|
|
1082
1317
|
});
|
|
1318
|
+
await this.processContentStoreEvents();
|
|
1083
1319
|
}
|
|
1084
1320
|
async uploadAndLinkAsset({ srcType, srcProjectId, srcDocumentId, fieldPath, asset, index, locale, user }) {
|
|
1085
1321
|
this.logger.debug('uploadAndLinkAsset', { srcType, srcProjectId, srcDocumentId, fieldPath, index, locale });
|
|
@@ -1123,7 +1359,7 @@ class ContentStore {
|
|
|
1123
1359
|
refType: 'asset',
|
|
1124
1360
|
refId: result.id
|
|
1125
1361
|
};
|
|
1126
|
-
|
|
1362
|
+
await contentSourceData.instance.updateDocument({
|
|
1127
1363
|
document: csiDocument,
|
|
1128
1364
|
modelMap: csiModelMap,
|
|
1129
1365
|
userContext: userContext,
|
|
@@ -1146,7 +1382,7 @@ class ContentStore {
|
|
|
1146
1382
|
}
|
|
1147
1383
|
]
|
|
1148
1384
|
});
|
|
1149
|
-
return { srcDocumentId:
|
|
1385
|
+
return { srcDocumentId: srcDocumentId };
|
|
1150
1386
|
}
|
|
1151
1387
|
async createDocument({ srcType, srcProjectId, modelName, object, locale, defaultLocaleDocumentId, user }) {
|
|
1152
1388
|
this.logger.debug('createDocument', { srcType, srcProjectId, modelName, locale });
|
|
@@ -1164,13 +1400,8 @@ class ContentStore {
|
|
|
1164
1400
|
user
|
|
1165
1401
|
})
|
|
1166
1402
|
});
|
|
1167
|
-
this.logger.debug('created document', { srcType, srcProjectId, srcDocumentId: result.
|
|
1168
|
-
|
|
1169
|
-
// instead wait for contentSource to call onContentChange(contentChangeEvent)
|
|
1170
|
-
// and use data from contentChangeEvent to update the cache
|
|
1171
|
-
// const newDocuments = [result.document, ...result.referencedDocuments];
|
|
1172
|
-
// contentSourceData.documentMap = Object.assign(contentSourceData.documentMap, _.keyBy(newDocuments, 'srcObjectId'));
|
|
1173
|
-
return { srcDocumentId: result.document.id };
|
|
1403
|
+
this.logger.debug('created document', { srcType, srcProjectId, srcDocumentId: result.documentId, modelName });
|
|
1404
|
+
return { srcDocumentId: result.documentId };
|
|
1174
1405
|
}
|
|
1175
1406
|
async updateDocument({ srcType, srcProjectId, srcDocumentId, updateOperations, user }) {
|
|
1176
1407
|
this.logger.debug('updateDocument');
|
|
@@ -1256,17 +1487,13 @@ class ContentStore {
|
|
|
1256
1487
|
};
|
|
1257
1488
|
}
|
|
1258
1489
|
});
|
|
1259
|
-
|
|
1490
|
+
await contentSourceData.instance.updateDocument({
|
|
1260
1491
|
document: csiDocument,
|
|
1261
1492
|
modelMap: csiModelMap,
|
|
1262
1493
|
userContext,
|
|
1263
1494
|
operations
|
|
1264
1495
|
});
|
|
1265
|
-
|
|
1266
|
-
// instead wait for contentSource to call onContentChange(contentChangeEvent)
|
|
1267
|
-
// and use data from contentChangeEvent to update the cache
|
|
1268
|
-
// contentSourceData.documentMap = Object.assign(contentSourceData.documentMap, { [document.srcObjectId]: document });
|
|
1269
|
-
return { srcDocumentId: updatedDocumentResult.id };
|
|
1496
|
+
return { srcDocumentId: srcDocumentId };
|
|
1270
1497
|
}
|
|
1271
1498
|
async duplicateDocument({ srcType, srcProjectId, srcDocumentId, object, locale, user }) {
|
|
1272
1499
|
var _a, _b, _c;
|
|
@@ -1278,7 +1505,6 @@ class ContentStore {
|
|
|
1278
1505
|
throw new Error(`no document with id '${srcDocumentId}' was found in ${contentSourceData.id}`);
|
|
1279
1506
|
}
|
|
1280
1507
|
const modelMap = contentSourceData.modelMap;
|
|
1281
|
-
const csiModelMap = contentSourceData.csiModelMap;
|
|
1282
1508
|
const model = modelMap[document.srcModelName];
|
|
1283
1509
|
if (!model) {
|
|
1284
1510
|
throw new Error(`no model with name '${document.srcModelName}' was found`);
|
|
@@ -1304,8 +1530,8 @@ class ContentStore {
|
|
|
1304
1530
|
user
|
|
1305
1531
|
})
|
|
1306
1532
|
});
|
|
1307
|
-
this.logger.debug('duplicated document', { srcType, srcProjectId, srcDocumentId, newDocumentId: result.
|
|
1308
|
-
return { srcDocumentId: result.
|
|
1533
|
+
this.logger.debug('duplicated document', { srcType, srcProjectId, srcDocumentId, newDocumentId: result.documentId, modelName: model.name });
|
|
1534
|
+
return { srcDocumentId: result.documentId };
|
|
1309
1535
|
}
|
|
1310
1536
|
async uploadAssets({ srcType, srcProjectId, assets, locale, user }) {
|
|
1311
1537
|
this.logger.debug('uploadAssets');
|
|
@@ -1349,10 +1575,6 @@ class ContentStore {
|
|
|
1349
1575
|
throw new Error(`no document with id '${srcDocumentId}' was found in ${contentSourceData.id}`);
|
|
1350
1576
|
}
|
|
1351
1577
|
await contentSourceData.instance.deleteDocument({ document: csiDocument, userContext });
|
|
1352
|
-
// do not update cache in contentSourceData.documents and documentMap,
|
|
1353
|
-
// instead wait for contentSource to call onContentChange(contentChangeEvent)
|
|
1354
|
-
// and use data from contentChangeEvent to update the cache
|
|
1355
|
-
// delete contentSourceData.documentMap[srcDocumentId];
|
|
1356
1578
|
}
|
|
1357
1579
|
async validateDocuments({ objects, locale, user }) {
|
|
1358
1580
|
this.logger.debug('validateDocuments');
|