@stackbit/cms-core 0.7.6-develop.2 → 0.8.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/.tsbuildinfo +1 -1
- package/dist/content-store-utils.d.ts +44 -0
- package/dist/content-store-utils.d.ts.map +1 -1
- package/dist/content-store-utils.js +213 -1
- 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 +45 -6
- package/dist/content-store.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/types/content-store-document-fields.d.ts +105 -0
- package/dist/types/content-store-document-fields.d.ts.map +1 -1
- package/dist/types/content-store-documents.d.ts +4 -1
- package/dist/types/content-store-documents.d.ts.map +1 -1
- package/dist/types/content-store-types.d.ts +10 -10
- package/dist/types/content-store-types.d.ts.map +1 -1
- package/dist/types/custom-actions.d.ts +108 -0
- package/dist/types/custom-actions.d.ts.map +1 -0
- package/dist/types/custom-actions.js +3 -0
- package/dist/types/custom-actions.js.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.d.ts +2 -1
- package/dist/utils/csi-to-store-docs-converter.d.ts.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.js +144 -11
- package/dist/utils/csi-to-store-docs-converter.js.map +1 -1
- package/dist/utils/custom-actions.d.ts +53 -0
- package/dist/utils/custom-actions.d.ts.map +1 -0
- package/dist/utils/custom-actions.js +586 -0
- package/dist/utils/custom-actions.js.map +1 -0
- package/dist/utils/document-hooks.d.ts +9 -0
- package/dist/utils/document-hooks.d.ts.map +1 -1
- package/dist/utils/document-hooks.js +3 -2
- package/dist/utils/document-hooks.js.map +1 -1
- package/dist/utils/search-utils.d.ts +1 -1
- package/dist/utils/search-utils.d.ts.map +1 -1
- package/dist/utils/store-to-api-docs-converter.d.ts.map +1 -1
- package/dist/utils/store-to-api-docs-converter.js +77 -29
- package/dist/utils/store-to-api-docs-converter.js.map +1 -1
- package/dist/utils/store-to-csi-docs-converter.d.ts +3 -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 +247 -0
- package/src/content-store.ts +62 -7
- package/src/index.ts +0 -1
- package/src/types/content-store-document-fields.ts +55 -2
- package/src/types/content-store-documents.ts +4 -1
- package/src/types/content-store-types.ts +10 -10
- package/src/types/custom-actions.ts +154 -0
- package/src/types/index.ts +1 -0
- package/src/utils/csi-to-store-docs-converter.ts +220 -12
- package/src/utils/custom-actions.ts +730 -0
- package/src/utils/document-hooks.ts +3 -3
- package/src/utils/search-utils.ts +1 -1
- package/src/utils/store-to-api-docs-converter.ts +88 -33
- package/src/utils/store-to-csi-docs-converter.ts +4 -4
|
@@ -14,6 +14,23 @@ export function getContentSourceId(contentSourceType: string, srcProjectId: stri
|
|
|
14
14
|
return contentSourceType + ':' + srcProjectId;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export function getContentSourceDataByTypeAndProjectIdOrThrow(
|
|
18
|
+
srcType: string,
|
|
19
|
+
srcProjectId: string,
|
|
20
|
+
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>
|
|
21
|
+
) {
|
|
22
|
+
const contentSourceId = getContentSourceId(srcType, srcProjectId);
|
|
23
|
+
return getContentSourceDataByIdOrThrow(contentSourceId, contentSourceDataById);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getContentSourceDataByIdOrThrow(contentSourceId: string, contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>) {
|
|
27
|
+
const contentSourceData = contentSourceDataById[contentSourceId];
|
|
28
|
+
if (!contentSourceData) {
|
|
29
|
+
throw new Error(`Content source not found: '${contentSourceId}'.`);
|
|
30
|
+
}
|
|
31
|
+
return contentSourceData;
|
|
32
|
+
}
|
|
33
|
+
|
|
17
34
|
export function findContentSourcesDataForTypeOrId({
|
|
18
35
|
contentSourceDataById,
|
|
19
36
|
srcType,
|
|
@@ -30,6 +47,10 @@ export function findContentSourcesDataForTypeOrId({
|
|
|
30
47
|
});
|
|
31
48
|
}
|
|
32
49
|
|
|
50
|
+
export function getUserContextForSrcTypeThunk(user?: ContentStoreTypes.User) {
|
|
51
|
+
return (srcType: string) => getUserContextForSrcType(srcType, user);
|
|
52
|
+
}
|
|
53
|
+
|
|
33
54
|
export function getUserContextForSrcType(srcType: string, user?: ContentStoreTypes.User): CSITypes.User | undefined {
|
|
34
55
|
if (!user) {
|
|
35
56
|
return undefined;
|
|
@@ -184,6 +205,232 @@ export function getModelFieldForFieldAtPath(
|
|
|
184
205
|
return getField(childDocField, childModelField, childFieldPath);
|
|
185
206
|
}
|
|
186
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Returns a model field and a document field at the specified field path.
|
|
210
|
+
*
|
|
211
|
+
* If some fields along the fieldPath are localized, the fieldPath must
|
|
212
|
+
* container the locale of the field under the "locales" property. The locales
|
|
213
|
+
* along the field path don't have to be the same.
|
|
214
|
+
* @example
|
|
215
|
+
* fieldPath: ['fields', 'button', 'locales', 'en', 'fields', 'title', 'locales', 'es']
|
|
216
|
+
*
|
|
217
|
+
* If the provided fieldPath points to a list item, the returned model field
|
|
218
|
+
* and document field will belong to a list item. In this case, the model field
|
|
219
|
+
* will contain only field-specific properties and the document field will be
|
|
220
|
+
* localized.
|
|
221
|
+
* @example
|
|
222
|
+
* fieldPath: ['fields', 'buttons', 'items', 2]
|
|
223
|
+
*
|
|
224
|
+
* The "fullFieldPath" flag specifies if the fieldPath includes container specifiers
|
|
225
|
+
* such as "fields", "items" and "locales".
|
|
226
|
+
* @example
|
|
227
|
+
* fullFieldPath: false => fieldPath: ['sections', 1, 'title', 'es']
|
|
228
|
+
* fullFieldPath: true => fieldPath: ['fields', 'sections', 'items', 1, 'fields', 'title', 'locales', 'es']
|
|
229
|
+
*
|
|
230
|
+
* @param document
|
|
231
|
+
* @param model
|
|
232
|
+
* @param fieldPath
|
|
233
|
+
* @param modelMap
|
|
234
|
+
* @param fullFieldPath
|
|
235
|
+
*/
|
|
236
|
+
export function getModelAndDocumentFieldForLocalizedFieldPath({
|
|
237
|
+
document,
|
|
238
|
+
model,
|
|
239
|
+
fieldPath,
|
|
240
|
+
modelMap,
|
|
241
|
+
fullFieldPath
|
|
242
|
+
}: {
|
|
243
|
+
document: ContentStoreTypes.Document;
|
|
244
|
+
model: Model;
|
|
245
|
+
fieldPath: (string | number)[];
|
|
246
|
+
modelMap: Record<string, Model>;
|
|
247
|
+
fullFieldPath?: boolean;
|
|
248
|
+
}): { modelField: Field | FieldListItems; documentField: ContentStoreTypes.DocumentField | ContentStoreTypes.DocumentListFieldItems } {
|
|
249
|
+
const origFieldPath = fieldPath;
|
|
250
|
+
if (fullFieldPath) {
|
|
251
|
+
if (_.head(fieldPath) !== 'fields') {
|
|
252
|
+
throw new Error('fieldPath must start with "fields" specifier');
|
|
253
|
+
}
|
|
254
|
+
fieldPath = _.tail(fieldPath);
|
|
255
|
+
}
|
|
256
|
+
if (_.isEmpty(fieldPath)) {
|
|
257
|
+
throw new Error('the fieldPath can not be empty');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function getFieldPathPrefixOfTail(fieldPath: (string | number)[]) {
|
|
261
|
+
return origFieldPath.slice(0, origFieldPath.length - fieldPath.length);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function getField(
|
|
265
|
+
docField: ContentStoreTypes.DocumentField | ContentStoreTypes.DocumentListFieldItems,
|
|
266
|
+
modelField: Field | FieldListItems,
|
|
267
|
+
fieldPath: (string | number)[]
|
|
268
|
+
): { modelField: Field | FieldListItems; documentField: ContentStoreTypes.DocumentField | ContentStoreTypes.DocumentListFieldItems } {
|
|
269
|
+
if (docField.localized) {
|
|
270
|
+
if (fullFieldPath) {
|
|
271
|
+
if (_.head(fieldPath) !== 'locales') {
|
|
272
|
+
throw new Error('fieldPath must contain "locales" specifier for localized field');
|
|
273
|
+
}
|
|
274
|
+
fieldPath = _.tail(fieldPath);
|
|
275
|
+
}
|
|
276
|
+
const locale = _.head(fieldPath);
|
|
277
|
+
if (typeof locale !== 'string') {
|
|
278
|
+
throw new Error('fieldPath must contain string locale');
|
|
279
|
+
}
|
|
280
|
+
fieldPath = _.tail(fieldPath);
|
|
281
|
+
const localizedDocField = getDocumentFieldForLocale(docField, locale);
|
|
282
|
+
if (!localizedDocField) {
|
|
283
|
+
throw new Error(`locale for field was not found`);
|
|
284
|
+
}
|
|
285
|
+
docField = localizedDocField;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
switch (docField.type) {
|
|
289
|
+
case 'object': {
|
|
290
|
+
if (docField.isUnset) {
|
|
291
|
+
throw new Error(`field is not set`);
|
|
292
|
+
}
|
|
293
|
+
if (fullFieldPath) {
|
|
294
|
+
if (_.head(fieldPath) !== 'fields') {
|
|
295
|
+
throw new Error('fieldPath must contain "fields" specifier for "object" field');
|
|
296
|
+
}
|
|
297
|
+
fieldPath = _.tail(fieldPath);
|
|
298
|
+
}
|
|
299
|
+
const fieldName = _.head(fieldPath);
|
|
300
|
+
if (typeof fieldName === 'undefined') {
|
|
301
|
+
throw new Error('the field path of object must contain a field name');
|
|
302
|
+
}
|
|
303
|
+
fieldPath = _.tail(fieldPath);
|
|
304
|
+
|
|
305
|
+
const childDocField = docField.fields[fieldName];
|
|
306
|
+
if (!childDocField) {
|
|
307
|
+
throw new Error(`document field doesn't exist at field path: '${getFieldPathPrefixOfTail(fieldPath).join('.')}'`);
|
|
308
|
+
}
|
|
309
|
+
if (modelField.type !== 'object') {
|
|
310
|
+
throw new Error(`model field type '${modelField.type}' doesn't match document field type '${docField.type}'`);
|
|
311
|
+
}
|
|
312
|
+
const childModelField = _.find(modelField.fields, (field) => field.name === fieldName);
|
|
313
|
+
if (!childModelField) {
|
|
314
|
+
throw new Error(`model field doesn't exist at field path: '${getFieldPathPrefixOfTail(fieldPath).join('.')}'`);
|
|
315
|
+
}
|
|
316
|
+
if (fieldPath.length === 0) {
|
|
317
|
+
return {
|
|
318
|
+
modelField: childModelField,
|
|
319
|
+
documentField: childDocField
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
return getField(childDocField, childModelField, fieldPath);
|
|
323
|
+
}
|
|
324
|
+
case 'model': {
|
|
325
|
+
if (docField.isUnset) {
|
|
326
|
+
throw new Error(`field is not set`);
|
|
327
|
+
}
|
|
328
|
+
if (fullFieldPath) {
|
|
329
|
+
if (_.head(fieldPath) !== 'fields') {
|
|
330
|
+
throw new Error('fieldPath must contain "fields" specifier for "model" field');
|
|
331
|
+
}
|
|
332
|
+
fieldPath = _.tail(fieldPath);
|
|
333
|
+
}
|
|
334
|
+
const fieldName = _.head(fieldPath);
|
|
335
|
+
if (typeof fieldName === 'undefined') {
|
|
336
|
+
throw new Error('the field path of model must contain a field name');
|
|
337
|
+
}
|
|
338
|
+
fieldPath = _.tail(fieldPath);
|
|
339
|
+
|
|
340
|
+
const modelName = docField.srcModelName;
|
|
341
|
+
const childModel = modelMap[modelName];
|
|
342
|
+
if (!childModel) {
|
|
343
|
+
throw new Error(`model ${modelName} doesn't exist`);
|
|
344
|
+
}
|
|
345
|
+
const childModelField = _.find(childModel.fields, (field) => field.name === fieldName);
|
|
346
|
+
if (!childModelField) {
|
|
347
|
+
throw new Error(`model field doesn't exist at field path: '${getFieldPathPrefixOfTail(fieldPath).join('.')}'`);
|
|
348
|
+
}
|
|
349
|
+
const childDocField = docField.fields[fieldName];
|
|
350
|
+
if (!childDocField) {
|
|
351
|
+
throw new Error(`document field doesn't exist at field path: '${getFieldPathPrefixOfTail(fieldPath).join('.')}'`);
|
|
352
|
+
}
|
|
353
|
+
if (fieldPath.length === 0) {
|
|
354
|
+
return {
|
|
355
|
+
modelField: childModelField,
|
|
356
|
+
documentField: childDocField
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
return getField(childDocField, childModelField, fieldPath);
|
|
360
|
+
}
|
|
361
|
+
case 'list': {
|
|
362
|
+
if (fullFieldPath) {
|
|
363
|
+
if (_.head(fieldPath) !== 'items') {
|
|
364
|
+
throw new Error('fieldPath must contain "items" specifier for "list" field');
|
|
365
|
+
}
|
|
366
|
+
fieldPath = _.tail(fieldPath);
|
|
367
|
+
}
|
|
368
|
+
const itemIndex = _.head(fieldPath) as number;
|
|
369
|
+
if (typeof itemIndex === 'undefined') {
|
|
370
|
+
throw new Error('the field path of list must contain an item index');
|
|
371
|
+
}
|
|
372
|
+
fieldPath = _.tail(fieldPath);
|
|
373
|
+
|
|
374
|
+
const listItem = docField.items && docField.items[itemIndex as number];
|
|
375
|
+
if (!listItem) {
|
|
376
|
+
throw new Error(`list item doesn't exist at field path: '${getFieldPathPrefixOfTail(fieldPath).join('.')}'`);
|
|
377
|
+
}
|
|
378
|
+
if (modelField.type !== 'list') {
|
|
379
|
+
throw new Error(`model field type '${modelField.type}' doesn't match document field type '${docField.type}'`);
|
|
380
|
+
}
|
|
381
|
+
const listItemsModel = modelField.items;
|
|
382
|
+
if (fieldPath.length === 0) {
|
|
383
|
+
return {
|
|
384
|
+
modelField: listItemsModel,
|
|
385
|
+
documentField: listItem
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
if (!Array.isArray(listItemsModel)) {
|
|
389
|
+
return getField(listItem, listItemsModel, fieldPath);
|
|
390
|
+
} else {
|
|
391
|
+
const fieldListItems = (listItemsModel as FieldListItems[]).find((listItemsModel) => listItemsModel.type === listItem.type);
|
|
392
|
+
if (!fieldListItems) {
|
|
393
|
+
throw new Error(
|
|
394
|
+
`cannot find list item model for document field of type '${listItem.type}' at field path: '${getFieldPathPrefixOfTail(
|
|
395
|
+
fieldPath
|
|
396
|
+
).join('.')}'`
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
return getField(listItem, fieldListItems, fieldPath);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
default:
|
|
403
|
+
if (!_.isEmpty(fieldPath)) {
|
|
404
|
+
throw new Error('illegal fieldPath');
|
|
405
|
+
}
|
|
406
|
+
return {
|
|
407
|
+
modelField,
|
|
408
|
+
documentField: docField
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const fieldName = _.head(fieldPath);
|
|
414
|
+
const childFieldPath = _.tail(fieldPath);
|
|
415
|
+
|
|
416
|
+
if (typeof fieldName !== 'string') {
|
|
417
|
+
throw new Error('the first fieldPath item must be string');
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const childDocField: ContentStoreTypes.DocumentField | undefined = document.fields[fieldName];
|
|
421
|
+
const childModelField: Field | undefined = _.find(model.fields, { name: fieldName });
|
|
422
|
+
|
|
423
|
+
if (!childDocField || !childModelField) {
|
|
424
|
+
throw new Error(`field ${fieldName} doesn't exist`);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (childFieldPath.length === 0) {
|
|
428
|
+
return { modelField: childModelField, documentField: childDocField };
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return getField(childDocField, childModelField, childFieldPath);
|
|
432
|
+
}
|
|
433
|
+
|
|
187
434
|
export function groupModelsByContentSource({ models }: { models: CSITypes.ModelWithSource[] }): Record<string, Record<string, Record<string, Model>>> {
|
|
188
435
|
const modelMapByContentSource: Record<string, Record<string, Record<string, Model>>> = {};
|
|
189
436
|
for (const model of models) {
|
package/src/content-store.ts
CHANGED
|
@@ -22,11 +22,12 @@ import { append, DeferredPromise, deferredPromise, deferWhileRunning, mapPromise
|
|
|
22
22
|
|
|
23
23
|
import * as ContentStoreTypes from './types';
|
|
24
24
|
import { Timer } from './utils/timer';
|
|
25
|
-
import { SearchFilter } from './types
|
|
25
|
+
import { SearchFilter } from './types';
|
|
26
26
|
import { searchDocuments } from './utils/search-utils';
|
|
27
27
|
import { mapCSIAssetsToStoreAssets, mapCSIDocumentsToStoreDocuments } from './utils/csi-to-store-docs-converter';
|
|
28
28
|
import {
|
|
29
29
|
getContentSourceId,
|
|
30
|
+
getContentSourceDataByIdOrThrow,
|
|
30
31
|
getContentSourceIdForContentSource,
|
|
31
32
|
getCSIDocumentsAndAssetsFromContentSourceDataByIds,
|
|
32
33
|
getModelFieldForFieldAtPath,
|
|
@@ -58,6 +59,7 @@ import { createConfigDelegate, getCreateConfigDelegateThunk } from './utils/conf
|
|
|
58
59
|
import { GitService } from './services';
|
|
59
60
|
import { getAssetSourcesForClient } from './utils/asset-sources-utils';
|
|
60
61
|
import { deleteDocumentHooked, publishDocumentHooked, updateDocumentHooked } from './utils/document-hooks';
|
|
62
|
+
import { resolveCustomActionsById, getGlobalAndBulkAPIActions, runCustomAction, stripModelActions } from './utils/custom-actions';
|
|
61
63
|
import {
|
|
62
64
|
logCreateDocument,
|
|
63
65
|
logDeleteDocument,
|
|
@@ -82,6 +84,7 @@ export interface ContentSourceOptions {
|
|
|
82
84
|
userCommandSpawner?: UserCommandSpawner; //TODO remove
|
|
83
85
|
onSchemaChangeCallback: () => void;
|
|
84
86
|
onContentChangeCallback: (contentChanges: ContentStoreTypes.ContentChangeResult) => void;
|
|
87
|
+
onActionStateChangeCallback: (actionResult: ContentStoreTypes.CustomActionStateChange) => void;
|
|
85
88
|
handleConfigAssets: HandleConfigAssets;
|
|
86
89
|
devAppRestartNeeded?: () => void;
|
|
87
90
|
}
|
|
@@ -127,6 +130,7 @@ export class ContentStore {
|
|
|
127
130
|
private readonly git: GitService;
|
|
128
131
|
private readonly onSchemaChangeCallback: () => void;
|
|
129
132
|
private readonly onContentChangeCallback: (contentChanges: ContentStoreTypes.ContentChangeResult) => void;
|
|
133
|
+
private readonly onActionStateChangeCallback: (actionStateChange: ContentStoreTypes.CustomActionStateChange) => void;
|
|
130
134
|
private readonly handleConfigAssets: HandleConfigAssets;
|
|
131
135
|
private readonly devAppRestartNeeded?: () => void;
|
|
132
136
|
private contentSources: BackCompatContentSourceInterface[] = [];
|
|
@@ -142,6 +146,7 @@ export class ContentStore {
|
|
|
142
146
|
private processingContentSourcesPromise: DeferredPromise<void> | null = null;
|
|
143
147
|
private contentStoreEventQueue: ContentStoreEventQueue = [];
|
|
144
148
|
private treeViews: CSITypes.TreeViewNode[] = [];
|
|
149
|
+
private customActionMap: ContentStoreTypes.ContentStoreCustomActionMap = {};
|
|
145
150
|
|
|
146
151
|
constructor(options: ContentSourceOptions) {
|
|
147
152
|
this.logger = options.logger.createLogger({ label: 'content-store' });
|
|
@@ -154,6 +159,7 @@ export class ContentStore {
|
|
|
154
159
|
this.userCommandSpawner = options.userCommandSpawner;
|
|
155
160
|
this.onSchemaChangeCallback = options.onSchemaChangeCallback;
|
|
156
161
|
this.onContentChangeCallback = options.onContentChangeCallback;
|
|
162
|
+
this.onActionStateChangeCallback = options.onActionStateChangeCallback;
|
|
157
163
|
this.handleConfigAssets = options.handleConfigAssets;
|
|
158
164
|
this.contentUpdatesWatchTimer = new Timer({ timerCallback: () => this.handleTimerTimeout(), logger: this.logger });
|
|
159
165
|
this.devAppRestartNeeded = options.devAppRestartNeeded;
|
|
@@ -1040,6 +1046,7 @@ export class ContentStore {
|
|
|
1040
1046
|
modelMap: contentSourceData.modelMap,
|
|
1041
1047
|
defaultLocaleCode: contentSourceData.defaultLocaleCode,
|
|
1042
1048
|
assetSources: this.stackbitConfig?.assetSources ?? [],
|
|
1049
|
+
customActionMap: this.customActionMap,
|
|
1043
1050
|
createConfigDelegate: getCreateConfigDelegateThunk({
|
|
1044
1051
|
getContentSourceDataById: () => this.contentSourceDataById,
|
|
1045
1052
|
logger: this.userLogger
|
|
@@ -1278,6 +1285,7 @@ export class ContentStore {
|
|
|
1278
1285
|
modelMap: modelMap,
|
|
1279
1286
|
defaultLocaleCode: csData.defaultLocaleCode,
|
|
1280
1287
|
assetSources: this.stackbitConfig?.assetSources ?? [],
|
|
1288
|
+
customActionMap: this.customActionMap,
|
|
1281
1289
|
createConfigDelegate: getCreateConfigDelegateThunk({
|
|
1282
1290
|
getContentSourceDataById: () => this.contentSourceDataById,
|
|
1283
1291
|
logger: this.userLogger
|
|
@@ -1326,9 +1334,10 @@ export class ContentStore {
|
|
|
1326
1334
|
const contentSourceType = contentSourceData.instance.getContentSourceType();
|
|
1327
1335
|
const srcProjectId = contentSourceData.instance.getProjectId();
|
|
1328
1336
|
const filteredModels = _.omitBy(contentSourceData.modelMap, (model) => model.name === StackbitPresetModelName);
|
|
1337
|
+
const mappedModels = stripModelActions({ modelMap: filteredModels });
|
|
1329
1338
|
// if `projectId` is number (even as string) e.g., '1234', _.set() will create an array of length 1235 and insert the item at the end.
|
|
1330
1339
|
// _.setWith(..., Object) ensures the values are always created as object keys, not as array indexes.
|
|
1331
|
-
_.setWith(result, [contentSourceType, srcProjectId],
|
|
1340
|
+
_.setWith(result, [contentSourceType, srcProjectId], mappedModels, Object);
|
|
1332
1341
|
_.setWith(result, [contentSourceType, srcProjectId, '__image_model'], IMAGE_MODEL, Object);
|
|
1333
1342
|
return result;
|
|
1334
1343
|
},
|
|
@@ -1351,6 +1360,56 @@ export class ContentStore {
|
|
|
1351
1360
|
);
|
|
1352
1361
|
}
|
|
1353
1362
|
|
|
1363
|
+
async getGlobalActions({
|
|
1364
|
+
pageUrl,
|
|
1365
|
+
user,
|
|
1366
|
+
locale,
|
|
1367
|
+
currentPageDocument
|
|
1368
|
+
}: {
|
|
1369
|
+
pageUrl?: string;
|
|
1370
|
+
user?: ContentStoreTypes.User;
|
|
1371
|
+
locale?: string;
|
|
1372
|
+
currentPageDocument?: ContentStoreTypes.APICustomActionDocumentSpecifier;
|
|
1373
|
+
}): Promise<(ContentStoreTypes.APICustomActionGlobal | ContentStoreTypes.APICustomActionBulk)[]> {
|
|
1374
|
+
return getGlobalAndBulkAPIActions({
|
|
1375
|
+
stackbitConfig: this.stackbitConfig,
|
|
1376
|
+
customActionMap: this.customActionMap,
|
|
1377
|
+
contentSourceDataById: this.contentSourceDataById,
|
|
1378
|
+
userLogger: this.userLogger,
|
|
1379
|
+
locale,
|
|
1380
|
+
pageUrl,
|
|
1381
|
+
user,
|
|
1382
|
+
currentPageDocument
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
async getCustomActions(getActionRequest: ContentStoreTypes.APIGetCustomActionRequest): Promise<ContentStoreTypes.APICustomAction[]> {
|
|
1387
|
+
return resolveCustomActionsById({
|
|
1388
|
+
getActionRequest,
|
|
1389
|
+
customActionMap: this.customActionMap,
|
|
1390
|
+
contentSourceDataById: this.contentSourceDataById,
|
|
1391
|
+
userLogger: this.userLogger
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
async runCustomAction(runActionRequest: ContentStoreTypes.APIRunCustomActionRequest): Promise<void> {
|
|
1396
|
+
this.onActionStateChangeCallback({
|
|
1397
|
+
actionId: runActionRequest.actionId,
|
|
1398
|
+
actionName: runActionRequest.actionName,
|
|
1399
|
+
actionType: runActionRequest.actionType,
|
|
1400
|
+
state: 'running'
|
|
1401
|
+
});
|
|
1402
|
+
runCustomAction({
|
|
1403
|
+
runActionRequest: runActionRequest,
|
|
1404
|
+
contentSourceDataById: this.contentSourceDataById,
|
|
1405
|
+
customActionMap: this.customActionMap,
|
|
1406
|
+
userLogger: this.userLogger,
|
|
1407
|
+
stackbitConfig: this.stackbitConfig
|
|
1408
|
+
}).then((actionStateChange) => {
|
|
1409
|
+
this.onActionStateChangeCallback(actionStateChange);
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1354
1413
|
getPresets({ locale }: { locale?: string } = {}): Record<string, any> {
|
|
1355
1414
|
if (!this.presets || !locale) {
|
|
1356
1415
|
return this.presets ?? {};
|
|
@@ -2560,11 +2619,7 @@ export class ContentStore {
|
|
|
2560
2619
|
}
|
|
2561
2620
|
|
|
2562
2621
|
private getContentSourceDataByIdOrThrow(contentSourceId: string): ContentSourceData {
|
|
2563
|
-
|
|
2564
|
-
if (!contentSourceData) {
|
|
2565
|
-
throw new Error(`Connection failed for content source: '${contentSourceId}'.`);
|
|
2566
|
-
}
|
|
2567
|
-
return contentSourceData;
|
|
2622
|
+
return getContentSourceDataByIdOrThrow(contentSourceId, this.contentSourceDataById);
|
|
2568
2623
|
}
|
|
2569
2624
|
|
|
2570
2625
|
onWebhook({ srcType, srcProjectId, data, headers }: { srcType: string; srcProjectId: string; data: unknown; headers: Record<string, string> }) {
|