@stackbit/cms-core 0.8.4-develop.1 → 0.8.4-develop.2
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.map +1 -1
- package/dist/content-store-utils.js +44 -48
- package/dist/content-store-utils.js.map +1 -1
- package/dist/content-store.d.ts +1 -1
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +14 -7
- package/dist/content-store.js.map +1 -1
- package/dist/types/custom-actions.d.ts +12 -8
- package/dist/types/custom-actions.d.ts.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.d.ts +14 -11
- package/dist/utils/csi-to-store-docs-converter.d.ts.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.js +21 -92
- package/dist/utils/csi-to-store-docs-converter.js.map +1 -1
- package/dist/utils/custom-actions.d.ts +39 -24
- package/dist/utils/custom-actions.d.ts.map +1 -1
- package/dist/utils/custom-actions.js +417 -231
- package/dist/utils/custom-actions.js.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 +40 -3
- package/dist/utils/store-to-api-docs-converter.js.map +1 -1
- package/package.json +4 -4
- package/src/content-store-utils.ts +79 -51
- package/src/content-store.ts +15 -8
- package/src/types/custom-actions.ts +22 -16
- package/src/utils/csi-to-store-docs-converter.ts +89 -227
- package/src/utils/custom-actions.ts +514 -263
- package/src/utils/store-to-api-docs-converter.ts +40 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
import { Config, mapModelFieldsRecursively } from '@stackbit/sdk';
|
|
2
|
+
import { Config, PageModel, DataModel, FieldObjectProps, FieldSpecificProps, mapModelFieldsRecursively, ObjectModel } from '@stackbit/sdk';
|
|
3
3
|
import * as StackbitTypes from '@stackbit/types';
|
|
4
4
|
import { mapPromise, omitByNil } from '@stackbit/utils';
|
|
5
5
|
import * as ContentStoreTypes from '../types';
|
|
@@ -13,16 +13,14 @@ import {
|
|
|
13
13
|
APIGetCustomActionRequest,
|
|
14
14
|
APIRunCustomActionRequest,
|
|
15
15
|
APIRunCustomActionRequestBulk,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
ContentStoreCustomActionObjectModel,
|
|
21
|
-
ContentStoreCustomActionField,
|
|
16
|
+
CustomActionRunStateMap,
|
|
17
|
+
ExtendedCustomActionDocument,
|
|
18
|
+
ExtendedCustomActionObjectModel,
|
|
19
|
+
ExtendedCustomActionField,
|
|
22
20
|
APICustomActionGlobal,
|
|
23
21
|
APICustomActionBulk,
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
ExtendedCustomAction,
|
|
23
|
+
ExtendedCustomActionObjectField
|
|
26
24
|
} from '../types';
|
|
27
25
|
import { createConfigDelegate } from './config-delegate';
|
|
28
26
|
import { getContentSourceActionsForSourceThunk } from './document-hooks';
|
|
@@ -59,7 +57,7 @@ export function stripModelActions({ modelMap }: { modelMap: StackbitTypes.ModelM
|
|
|
59
57
|
|
|
60
58
|
export async function getGlobalAndBulkAPIActions({
|
|
61
59
|
stackbitConfig,
|
|
62
|
-
|
|
60
|
+
customActionRunStateMap,
|
|
63
61
|
contentSourceDataById,
|
|
64
62
|
userLogger,
|
|
65
63
|
pageUrl,
|
|
@@ -68,7 +66,7 @@ export async function getGlobalAndBulkAPIActions({
|
|
|
68
66
|
currentPageDocument
|
|
69
67
|
}: {
|
|
70
68
|
stackbitConfig: Config | null;
|
|
71
|
-
|
|
69
|
+
customActionRunStateMap: CustomActionRunStateMap;
|
|
72
70
|
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
|
|
73
71
|
userLogger: StackbitTypes.Logger;
|
|
74
72
|
pageUrl?: string;
|
|
@@ -86,25 +84,15 @@ export async function getGlobalAndBulkAPIActions({
|
|
|
86
84
|
});
|
|
87
85
|
|
|
88
86
|
return mapPromise(stackbitConfig.actions, async (action) => {
|
|
89
|
-
const actionId =
|
|
90
|
-
const
|
|
91
|
-
const storeAction: ContentStoreCustomActionGlobal | ContentStoreCustomActionBulk = {
|
|
92
|
-
// if configuration is updated, the new action properties will override the stored action properties
|
|
93
|
-
...action,
|
|
94
|
-
actionId,
|
|
95
|
-
label: action.label ?? _.startCase(action.name),
|
|
96
|
-
runningHandler: prevStoreAction?.runningHandler,
|
|
97
|
-
lastResultState: prevStoreAction?.lastResultState
|
|
98
|
-
};
|
|
99
|
-
customActionMap[actionId] = storeAction;
|
|
100
|
-
|
|
87
|
+
const actionId = globalActionId(action);
|
|
88
|
+
const actionRunState = customActionRunStateMap[actionId];
|
|
101
89
|
let state: StackbitTypes.CustomActionState | 'unknown';
|
|
102
90
|
|
|
103
|
-
if (
|
|
91
|
+
if (actionRunState?.runningHandler) {
|
|
104
92
|
state = 'running';
|
|
105
|
-
} else if (
|
|
93
|
+
} else if (action.state) {
|
|
106
94
|
const pageDocument = getCSIDocumentWithSourceFromDocumentSpec(currentPageDocument, configDelegate);
|
|
107
|
-
state = await
|
|
95
|
+
state = await action.state({
|
|
108
96
|
actionId: actionId,
|
|
109
97
|
currentLocale: locale,
|
|
110
98
|
currentUser: user ? { name: user.name, email: user.email } : undefined,
|
|
@@ -113,189 +101,230 @@ export async function getGlobalAndBulkAPIActions({
|
|
|
113
101
|
...configDelegate
|
|
114
102
|
});
|
|
115
103
|
} else {
|
|
116
|
-
state =
|
|
104
|
+
state = actionRunState?.lastResultState ?? 'enabled';
|
|
117
105
|
}
|
|
118
106
|
|
|
119
107
|
return omitByNil({
|
|
108
|
+
type: action.type,
|
|
120
109
|
actionId: actionId,
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
icon: storeAction.icon,
|
|
110
|
+
name: action.name,
|
|
111
|
+
label: action.label ?? _.startCase(action.name),
|
|
112
|
+
icon: action.icon,
|
|
125
113
|
state: state,
|
|
126
|
-
inputFields:
|
|
114
|
+
inputFields: action.inputFields
|
|
127
115
|
});
|
|
128
116
|
});
|
|
129
117
|
}
|
|
130
118
|
|
|
131
|
-
export function
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
119
|
+
export function getDocumentActionsThunk({
|
|
120
|
+
csiDocument,
|
|
121
|
+
model,
|
|
122
|
+
srcType,
|
|
123
|
+
srcProjectId,
|
|
124
|
+
customActionRunStateMap
|
|
135
125
|
}: {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
// if configuration is updated, the new action properties will override the stored action properties
|
|
145
|
-
...action,
|
|
146
|
-
type: 'document',
|
|
147
|
-
actionId,
|
|
148
|
-
label: action.label ?? _.startCase(action.name),
|
|
149
|
-
runningHandler: prevStoreAction?.runningHandler,
|
|
150
|
-
lastResultState: prevStoreAction?.lastResultState,
|
|
151
|
-
documentSpec: {
|
|
152
|
-
srcType: csiDocument.srcType,
|
|
153
|
-
srcProjectId: csiDocument.srcProjectId,
|
|
154
|
-
srcDocumentId: csiDocument.id
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
customActionMap[actionId] = storeAction;
|
|
158
|
-
|
|
159
|
-
let state: StackbitTypes.CustomActionState | 'unknown';
|
|
160
|
-
let needsResolving = false;
|
|
161
|
-
if (storeAction?.runningHandler) {
|
|
162
|
-
state = 'running';
|
|
163
|
-
} else if (action.state) {
|
|
164
|
-
state = 'unknown';
|
|
165
|
-
needsResolving = true;
|
|
166
|
-
} else {
|
|
167
|
-
state = storeAction?.lastResultState ?? 'enabled';
|
|
126
|
+
csiDocument: StackbitTypes.Document;
|
|
127
|
+
model: PageModel | DataModel;
|
|
128
|
+
srcType: string;
|
|
129
|
+
srcProjectId: string;
|
|
130
|
+
customActionRunStateMap: ContentStoreTypes.CustomActionRunStateMap;
|
|
131
|
+
}): () => APICustomActionDocument[] | undefined {
|
|
132
|
+
if (!('actions' in model) || !Array.isArray(model.actions)) {
|
|
133
|
+
return () => undefined;
|
|
168
134
|
}
|
|
169
135
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
136
|
+
const extendedDocumentActions = model.actions.map((action): ExtendedCustomActionDocument => {
|
|
137
|
+
const documentSpec = {
|
|
138
|
+
srcType: srcType,
|
|
139
|
+
srcProjectId: srcProjectId,
|
|
140
|
+
srcDocumentId: csiDocument.id
|
|
141
|
+
};
|
|
142
|
+
return {
|
|
143
|
+
// if configuration is updated, the new action properties will override the stored action properties
|
|
144
|
+
...action,
|
|
145
|
+
type: 'document',
|
|
146
|
+
actionId: documentActionId({ ...documentSpec, actionName: action.name }),
|
|
147
|
+
label: action.label ?? _.startCase(action.name),
|
|
148
|
+
documentSpec: documentSpec
|
|
149
|
+
};
|
|
179
150
|
});
|
|
151
|
+
|
|
152
|
+
return () =>
|
|
153
|
+
extendedDocumentActions.map((extendedAction) => {
|
|
154
|
+
return omitByNil({
|
|
155
|
+
type: 'document',
|
|
156
|
+
actionId: extendedAction.actionId,
|
|
157
|
+
name: extendedAction.name,
|
|
158
|
+
label: extendedAction.label,
|
|
159
|
+
icon: extendedAction.icon,
|
|
160
|
+
inputFields: extendedAction.inputFields,
|
|
161
|
+
...getAPIActionState(extendedAction, customActionRunStateMap)
|
|
162
|
+
});
|
|
163
|
+
});
|
|
180
164
|
}
|
|
181
165
|
|
|
182
|
-
export function
|
|
183
|
-
|
|
184
|
-
customActionMap,
|
|
166
|
+
export function getObjectModelActionsThunk({
|
|
167
|
+
model,
|
|
185
168
|
csiParentDocument,
|
|
169
|
+
srcType,
|
|
170
|
+
srcProjectId,
|
|
171
|
+
customActionRunStateMap,
|
|
186
172
|
fieldPath
|
|
187
173
|
}: {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
174
|
+
model: ObjectModel;
|
|
175
|
+
csiParentDocument: StackbitTypes.Document;
|
|
176
|
+
srcType: string;
|
|
177
|
+
srcProjectId: string;
|
|
178
|
+
customActionRunStateMap: ContentStoreTypes.CustomActionRunStateMap;
|
|
191
179
|
fieldPath: (string | number)[];
|
|
192
|
-
}): APICustomActionObject {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const prevStoreAction = customActionMap[actionId] as ContentStoreCustomActionObjectModel | undefined;
|
|
196
|
-
const storeAction: ContentStoreCustomActionObjectModel = {
|
|
197
|
-
// if configuration is updated, the new action properties will override the stored action properties
|
|
198
|
-
...action,
|
|
199
|
-
type: 'objectModel',
|
|
200
|
-
actionId,
|
|
201
|
-
label: action.label ?? _.startCase(action.name),
|
|
202
|
-
runningHandler: prevStoreAction?.runningHandler,
|
|
203
|
-
lastResultState: prevStoreAction?.lastResultState,
|
|
204
|
-
documentSpec: {
|
|
205
|
-
srcType: csiParentDocument.srcType,
|
|
206
|
-
srcProjectId: csiParentDocument.srcProjectId,
|
|
207
|
-
srcDocumentId: csiParentDocument.id
|
|
208
|
-
},
|
|
209
|
-
fieldPath
|
|
210
|
-
};
|
|
211
|
-
customActionMap[actionId] = storeAction;
|
|
212
|
-
|
|
213
|
-
let state: StackbitTypes.CustomActionState | 'unknown';
|
|
214
|
-
let needsResolving = false;
|
|
215
|
-
if (storeAction?.runningHandler) {
|
|
216
|
-
state = 'running';
|
|
217
|
-
} else if (action.state) {
|
|
218
|
-
state = 'unknown';
|
|
219
|
-
needsResolving = true;
|
|
220
|
-
} else {
|
|
221
|
-
state = storeAction?.lastResultState ?? 'enabled';
|
|
180
|
+
}): () => ContentStoreTypes.APICustomActionObject[] | undefined {
|
|
181
|
+
if (!('actions' in model) || !Array.isArray(model.actions)) {
|
|
182
|
+
return () => undefined;
|
|
222
183
|
}
|
|
223
184
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
185
|
+
const extendedObjectModelActions = model.actions.map((action): ExtendedCustomActionObjectModel => {
|
|
186
|
+
const documentSpec = {
|
|
187
|
+
srcType: srcType,
|
|
188
|
+
srcProjectId: srcProjectId,
|
|
189
|
+
srcDocumentId: csiParentDocument.id
|
|
190
|
+
};
|
|
191
|
+
return {
|
|
192
|
+
// if configuration is updated, the new action properties will override the stored action properties
|
|
193
|
+
...action,
|
|
194
|
+
type: 'objectModel',
|
|
195
|
+
actionId: fieldPathActionId({ ...documentSpec, fieldPath, actionName: action.name }),
|
|
196
|
+
label: action.label ?? _.startCase(action.name),
|
|
197
|
+
documentSpec: documentSpec,
|
|
198
|
+
fieldPath
|
|
199
|
+
};
|
|
233
200
|
});
|
|
201
|
+
|
|
202
|
+
return () =>
|
|
203
|
+
extendedObjectModelActions.map((extendedAction) => {
|
|
204
|
+
return omitByNil({
|
|
205
|
+
type: 'object',
|
|
206
|
+
actionId: extendedAction.actionId,
|
|
207
|
+
name: extendedAction.name,
|
|
208
|
+
label: extendedAction.label,
|
|
209
|
+
icon: extendedAction.icon,
|
|
210
|
+
inputFields: extendedAction.inputFields,
|
|
211
|
+
...getAPIActionState(extendedAction, customActionRunStateMap)
|
|
212
|
+
});
|
|
213
|
+
});
|
|
234
214
|
}
|
|
235
215
|
|
|
236
|
-
export function
|
|
237
|
-
|
|
238
|
-
customActionMap,
|
|
216
|
+
export function getObjectFieldActionsThunk({
|
|
217
|
+
modelField,
|
|
239
218
|
csiParentDocument,
|
|
219
|
+
srcType,
|
|
220
|
+
srcProjectId,
|
|
221
|
+
customActionRunStateMap,
|
|
240
222
|
fieldPath
|
|
241
223
|
}: {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
224
|
+
modelField: FieldObjectProps;
|
|
225
|
+
csiParentDocument: StackbitTypes.Document;
|
|
226
|
+
srcType: string;
|
|
227
|
+
srcProjectId: string;
|
|
228
|
+
customActionRunStateMap: ContentStoreTypes.CustomActionRunStateMap;
|
|
245
229
|
fieldPath: (string | number)[];
|
|
246
|
-
}):
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
runningHandler: prevStoreAction?.runningHandler,
|
|
257
|
-
lastResultState: prevStoreAction?.lastResultState,
|
|
258
|
-
documentSpec: {
|
|
259
|
-
srcType: csiParentDocument.srcType,
|
|
260
|
-
srcProjectId: csiParentDocument.srcProjectId,
|
|
230
|
+
}): () => APICustomActionObject[] | undefined {
|
|
231
|
+
if (!('actions' in modelField) || !Array.isArray(modelField.actions)) {
|
|
232
|
+
return () => undefined;
|
|
233
|
+
}
|
|
234
|
+
const objectFieldActions = modelField.actions.filter((action): action is StackbitTypes.CustomActionObjectField => action.type === 'object');
|
|
235
|
+
|
|
236
|
+
const extendedObjectFieldActions = objectFieldActions.map((action): ExtendedCustomActionObjectField => {
|
|
237
|
+
const documentSpec = {
|
|
238
|
+
srcType: srcType,
|
|
239
|
+
srcProjectId: srcProjectId,
|
|
261
240
|
srcDocumentId: csiParentDocument.id
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
241
|
+
};
|
|
242
|
+
return {
|
|
243
|
+
// if configuration is updated, the new action properties will override the stored action properties
|
|
244
|
+
...action,
|
|
245
|
+
type: 'objectField',
|
|
246
|
+
actionId: fieldPathActionId({ ...documentSpec, fieldPath, actionName: action.name }),
|
|
247
|
+
label: action.label ?? _.startCase(action.name),
|
|
248
|
+
documentSpec: documentSpec,
|
|
249
|
+
fieldPath
|
|
250
|
+
};
|
|
251
|
+
});
|
|
266
252
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
253
|
+
return () =>
|
|
254
|
+
extendedObjectFieldActions.map((extendedAction) => {
|
|
255
|
+
return omitByNil({
|
|
256
|
+
type: 'object',
|
|
257
|
+
actionId: extendedAction.actionId,
|
|
258
|
+
name: extendedAction.name,
|
|
259
|
+
label: extendedAction.label,
|
|
260
|
+
icon: extendedAction.icon,
|
|
261
|
+
inputFields: extendedAction.inputFields,
|
|
262
|
+
...getAPIActionState(extendedAction, customActionRunStateMap)
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function getFieldActions({
|
|
268
|
+
modelField,
|
|
269
|
+
csiParentDocument,
|
|
270
|
+
srcType,
|
|
271
|
+
srcProjectId,
|
|
272
|
+
customActionRunStateMap,
|
|
273
|
+
fieldPath
|
|
274
|
+
}: {
|
|
275
|
+
modelField: FieldSpecificProps;
|
|
276
|
+
csiParentDocument: StackbitTypes.Document;
|
|
277
|
+
srcType: string;
|
|
278
|
+
srcProjectId: string;
|
|
279
|
+
customActionRunStateMap: ContentStoreTypes.CustomActionRunStateMap;
|
|
280
|
+
fieldPath: (string | number)[];
|
|
281
|
+
}): APICustomActionField[] | undefined {
|
|
282
|
+
if (!('actions' in modelField) || !Array.isArray(modelField.actions)) {
|
|
283
|
+
return undefined;
|
|
276
284
|
}
|
|
285
|
+
const fieldActions = modelField.actions.filter((action): action is StackbitTypes.CustomActionField => action.type !== 'object');
|
|
286
|
+
|
|
287
|
+
const extendedFieldActions = fieldActions.map((action): ExtendedCustomActionField => {
|
|
288
|
+
const documentSpec = {
|
|
289
|
+
srcType: srcType,
|
|
290
|
+
srcProjectId: srcProjectId,
|
|
291
|
+
srcDocumentId: csiParentDocument.id
|
|
292
|
+
};
|
|
293
|
+
return {
|
|
294
|
+
// if configuration is updated, the new action properties will override the stored action properties
|
|
295
|
+
...action,
|
|
296
|
+
type: 'field',
|
|
297
|
+
actionId: fieldPathActionId({ ...documentSpec, fieldPath, actionName: action.name }),
|
|
298
|
+
label: action.label ?? _.startCase(action.name),
|
|
299
|
+
documentSpec: documentSpec,
|
|
300
|
+
fieldPath
|
|
301
|
+
};
|
|
302
|
+
});
|
|
277
303
|
|
|
278
|
-
return
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
304
|
+
return extendedFieldActions.map((extendedAction) => {
|
|
305
|
+
return omitByNil({
|
|
306
|
+
type: 'field',
|
|
307
|
+
actionId: extendedAction.actionId,
|
|
308
|
+
name: extendedAction.name,
|
|
309
|
+
label: extendedAction.label,
|
|
310
|
+
icon: extendedAction.icon,
|
|
311
|
+
inputFields: extendedAction.inputFields,
|
|
312
|
+
...getAPIActionState(extendedAction, customActionRunStateMap)
|
|
313
|
+
});
|
|
314
|
+
});
|
|
288
315
|
}
|
|
289
316
|
|
|
290
317
|
export async function resolveCustomActionsById({
|
|
291
318
|
getActionRequest,
|
|
292
|
-
|
|
319
|
+
customActionRunStateMap,
|
|
293
320
|
contentSourceDataById,
|
|
321
|
+
stackbitConfig,
|
|
294
322
|
userLogger
|
|
295
323
|
}: {
|
|
296
324
|
getActionRequest: APIGetCustomActionRequest;
|
|
297
|
-
|
|
325
|
+
customActionRunStateMap: CustomActionRunStateMap;
|
|
298
326
|
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
|
|
327
|
+
stackbitConfig: Config | null;
|
|
299
328
|
userLogger: StackbitTypes.Logger;
|
|
300
329
|
}): Promise<APICustomAction[]> {
|
|
301
330
|
const result: APICustomAction[] = [];
|
|
@@ -307,17 +336,22 @@ export async function resolveCustomActionsById({
|
|
|
307
336
|
});
|
|
308
337
|
|
|
309
338
|
for (const actionId of customActionIds) {
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
339
|
+
const extendedAction = findCustomActionById({
|
|
340
|
+
actionId,
|
|
341
|
+
customActionRunStateMap,
|
|
342
|
+
contentSourceDataById,
|
|
343
|
+
stackbitConfig
|
|
344
|
+
});
|
|
345
|
+
if (!extendedAction) {
|
|
346
|
+
userLogger.debug(`custom action with id: '${actionId}' was not found`);
|
|
313
347
|
continue;
|
|
314
348
|
}
|
|
315
349
|
|
|
316
350
|
try {
|
|
317
351
|
let state: StackbitTypes.CustomActionState;
|
|
318
|
-
if (
|
|
352
|
+
if (extendedAction.runningHandler) {
|
|
319
353
|
state = 'running';
|
|
320
|
-
} else if (
|
|
354
|
+
} else if (extendedAction.state) {
|
|
321
355
|
const pageDocument = getCSIDocumentWithSourceFromDocumentSpec(currentPageDocument, configDelegate);
|
|
322
356
|
const commonStateOptions: StackbitTypes.CustomActionStateCommonOptions = {
|
|
323
357
|
actionId: actionId,
|
|
@@ -332,61 +366,61 @@ export async function resolveCustomActionsById({
|
|
|
332
366
|
currentPageDocument: pageDocument,
|
|
333
367
|
...configDelegate
|
|
334
368
|
};
|
|
335
|
-
if (
|
|
336
|
-
state = await
|
|
337
|
-
} else if (
|
|
369
|
+
if (extendedAction.type === 'global' || extendedAction.type === 'bulk') {
|
|
370
|
+
state = await extendedAction.state(commonStateOptions);
|
|
371
|
+
} else if (extendedAction.type === 'document') {
|
|
338
372
|
const { document, model } = getCSIDocumentAndModelWithSourceFromDocumentSpec({
|
|
339
|
-
documentSpec:
|
|
373
|
+
documentSpec: extendedAction.documentSpec,
|
|
340
374
|
contentSourceDataById
|
|
341
375
|
});
|
|
342
|
-
state = await
|
|
376
|
+
state = await extendedAction.state({
|
|
343
377
|
...commonStateOptions,
|
|
344
378
|
document: document,
|
|
345
379
|
model: model
|
|
346
380
|
});
|
|
347
|
-
} else if (
|
|
381
|
+
} else if (extendedAction.type === 'objectModel') {
|
|
348
382
|
const stateObjectParams = getHandlerParamsForObjectModelAction({
|
|
349
|
-
|
|
383
|
+
extendedAction,
|
|
350
384
|
contentSourceDataById
|
|
351
385
|
});
|
|
352
|
-
state = await
|
|
386
|
+
state = await extendedAction.state({
|
|
353
387
|
...commonStateOptions,
|
|
354
388
|
...stateObjectParams
|
|
355
389
|
});
|
|
356
|
-
} else if (
|
|
390
|
+
} else if (extendedAction.type === 'objectField') {
|
|
357
391
|
const stateObjectParams = getHandlerParamsForObjectFieldAction({
|
|
358
|
-
|
|
392
|
+
extendedAction,
|
|
359
393
|
contentSourceDataById
|
|
360
394
|
});
|
|
361
|
-
state = await
|
|
395
|
+
state = await extendedAction.state({
|
|
362
396
|
...commonStateOptions,
|
|
363
397
|
...stateObjectParams
|
|
364
398
|
});
|
|
365
|
-
} else if (
|
|
399
|
+
} else if (extendedAction.type === 'field') {
|
|
366
400
|
const stateFieldParams = getHandlerParamsForFieldAction({
|
|
367
|
-
|
|
401
|
+
extendedAction,
|
|
368
402
|
contentSourceDataById
|
|
369
403
|
});
|
|
370
|
-
state = await
|
|
404
|
+
state = await extendedAction.state({
|
|
371
405
|
...commonStateOptions,
|
|
372
406
|
...stateFieldParams
|
|
373
407
|
});
|
|
374
408
|
} else {
|
|
375
|
-
const _exhaustiveCheck: never =
|
|
409
|
+
const _exhaustiveCheck: never = extendedAction;
|
|
376
410
|
continue;
|
|
377
411
|
}
|
|
378
412
|
} else {
|
|
379
|
-
state =
|
|
413
|
+
state = extendedAction.lastResultState ?? 'enabled';
|
|
380
414
|
}
|
|
381
415
|
result.push(
|
|
382
416
|
omitByNil({
|
|
383
417
|
actionId: actionId,
|
|
384
|
-
type: storeActionTypeToAPIActionType(
|
|
385
|
-
name:
|
|
386
|
-
label:
|
|
387
|
-
icon:
|
|
418
|
+
type: storeActionTypeToAPIActionType(extendedAction.type),
|
|
419
|
+
name: extendedAction.name,
|
|
420
|
+
label: extendedAction.label,
|
|
421
|
+
icon: extendedAction.icon,
|
|
388
422
|
state: state,
|
|
389
|
-
inputFields:
|
|
423
|
+
inputFields: extendedAction.inputFields
|
|
390
424
|
})
|
|
391
425
|
);
|
|
392
426
|
} catch (error: any) {
|
|
@@ -399,38 +433,45 @@ export async function resolveCustomActionsById({
|
|
|
399
433
|
|
|
400
434
|
export function runCustomAction({
|
|
401
435
|
runActionRequest,
|
|
402
|
-
|
|
436
|
+
customActionRunStateMap,
|
|
403
437
|
contentSourceDataById,
|
|
404
|
-
|
|
405
|
-
|
|
438
|
+
stackbitConfig,
|
|
439
|
+
userLogger
|
|
406
440
|
}: {
|
|
407
441
|
runActionRequest: APIRunCustomActionRequest;
|
|
408
|
-
|
|
442
|
+
customActionRunStateMap: CustomActionRunStateMap;
|
|
409
443
|
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
|
|
410
|
-
userLogger: StackbitTypes.Logger;
|
|
411
444
|
stackbitConfig: Config | null;
|
|
445
|
+
userLogger: StackbitTypes.Logger;
|
|
412
446
|
}): Promise<CustomActionStateChange> {
|
|
413
|
-
const
|
|
414
|
-
|
|
447
|
+
const extendedAction = findCustomActionById({
|
|
448
|
+
actionId: runActionRequest.actionId,
|
|
449
|
+
customActionRunStateMap,
|
|
450
|
+
contentSourceDataById,
|
|
451
|
+
stackbitConfig
|
|
452
|
+
});
|
|
453
|
+
if (!extendedAction) {
|
|
415
454
|
throw new Error(`Error running action: action not found, action name: '${runActionRequest.actionName}' action ID: '${runActionRequest.actionId}'.`);
|
|
416
455
|
}
|
|
417
|
-
const prevResultState =
|
|
418
|
-
if (
|
|
456
|
+
const prevResultState = extendedAction.lastResultState;
|
|
457
|
+
if (extendedAction.lastResultState && extendedAction.lastResultState !== 'enabled') {
|
|
419
458
|
throw new Error(
|
|
420
459
|
`Error running action: action is not enabled, action name: '${runActionRequest.actionName}' action ID: '${runActionRequest.actionId}'.`
|
|
421
460
|
);
|
|
422
461
|
}
|
|
423
462
|
|
|
424
463
|
try {
|
|
425
|
-
const actionLogger = userLogger.createLogger({ label: `action:${
|
|
464
|
+
const actionLogger = userLogger.createLogger({ label: `action:${extendedAction.name}` });
|
|
426
465
|
const configDelegate = createConfigDelegate({ contentSourceDataById: contentSourceDataById, logger: actionLogger });
|
|
427
466
|
const currentPageDocument = getCSIDocumentWithSourceFromDocumentSpec(runActionRequest.currentPageDocument, configDelegate);
|
|
428
467
|
|
|
429
|
-
|
|
430
|
-
|
|
468
|
+
customActionRunStateMap[runActionRequest.actionId] = {
|
|
469
|
+
runningHandler: true,
|
|
470
|
+
lastResultState: 'running'
|
|
471
|
+
};
|
|
431
472
|
|
|
432
473
|
const commonRunOptions: StackbitTypes.CustomActionRunCommonOptions = {
|
|
433
|
-
actionId:
|
|
474
|
+
actionId: extendedAction.actionId,
|
|
434
475
|
inputData: runActionRequest.inputData,
|
|
435
476
|
currentLocale: runActionRequest.locale,
|
|
436
477
|
currentUser: runActionRequest.user,
|
|
@@ -448,9 +489,9 @@ export function runCustomAction({
|
|
|
448
489
|
|
|
449
490
|
let promise;
|
|
450
491
|
|
|
451
|
-
if (
|
|
452
|
-
promise =
|
|
453
|
-
} else if (
|
|
492
|
+
if (extendedAction.type === 'global') {
|
|
493
|
+
promise = extendedAction.run(commonRunOptions);
|
|
494
|
+
} else if (extendedAction.type === 'bulk') {
|
|
454
495
|
const documents = (runActionRequest as APIRunCustomActionRequestBulk).documents.map((documentSpec) => {
|
|
455
496
|
const { document } = getCSIDocumentAndModelWithSourceFromDocumentSpec({
|
|
456
497
|
documentSpec,
|
|
@@ -458,74 +499,76 @@ export function runCustomAction({
|
|
|
458
499
|
});
|
|
459
500
|
return document;
|
|
460
501
|
});
|
|
461
|
-
promise =
|
|
502
|
+
promise = extendedAction.run({
|
|
462
503
|
...commonRunOptions,
|
|
463
504
|
documents
|
|
464
505
|
});
|
|
465
|
-
} else if (
|
|
506
|
+
} else if (extendedAction.type === 'document') {
|
|
466
507
|
const { document, model } = getCSIDocumentAndModelWithSourceFromDocumentSpec({
|
|
467
|
-
documentSpec:
|
|
508
|
+
documentSpec: extendedAction.documentSpec,
|
|
468
509
|
contentSourceDataById
|
|
469
510
|
});
|
|
470
|
-
promise =
|
|
511
|
+
promise = extendedAction.run({
|
|
471
512
|
...commonRunOptions,
|
|
472
513
|
document,
|
|
473
514
|
model,
|
|
474
515
|
contentSourceActions: commonRunOptions.getContentSourceActionsForSource({
|
|
475
|
-
srcType:
|
|
476
|
-
srcProjectId:
|
|
516
|
+
srcType: extendedAction.documentSpec.srcType,
|
|
517
|
+
srcProjectId: extendedAction.documentSpec.srcProjectId
|
|
477
518
|
})!
|
|
478
519
|
});
|
|
479
|
-
} else if (
|
|
520
|
+
} else if (extendedAction.type === 'objectModel') {
|
|
480
521
|
const handlerObjectParams = getHandlerParamsForObjectModelAction({
|
|
481
|
-
|
|
522
|
+
extendedAction,
|
|
482
523
|
contentSourceDataById
|
|
483
524
|
});
|
|
484
|
-
promise =
|
|
525
|
+
promise = extendedAction.run({
|
|
485
526
|
...commonRunOptions,
|
|
486
527
|
...handlerObjectParams,
|
|
487
528
|
contentSourceActions: commonRunOptions.getContentSourceActionsForSource({
|
|
488
|
-
srcType:
|
|
489
|
-
srcProjectId:
|
|
529
|
+
srcType: extendedAction.documentSpec.srcType,
|
|
530
|
+
srcProjectId: extendedAction.documentSpec.srcProjectId
|
|
490
531
|
})!
|
|
491
532
|
});
|
|
492
|
-
} else if (
|
|
533
|
+
} else if (extendedAction.type === 'objectField') {
|
|
493
534
|
const handlerObjectParams = getHandlerParamsForObjectFieldAction({
|
|
494
|
-
|
|
535
|
+
extendedAction,
|
|
495
536
|
contentSourceDataById
|
|
496
537
|
});
|
|
497
|
-
promise =
|
|
538
|
+
promise = extendedAction.run({
|
|
498
539
|
...commonRunOptions,
|
|
499
540
|
...handlerObjectParams,
|
|
500
541
|
contentSourceActions: commonRunOptions.getContentSourceActionsForSource({
|
|
501
|
-
srcType:
|
|
502
|
-
srcProjectId:
|
|
542
|
+
srcType: extendedAction.documentSpec.srcType,
|
|
543
|
+
srcProjectId: extendedAction.documentSpec.srcProjectId
|
|
503
544
|
})!
|
|
504
545
|
});
|
|
505
|
-
} else if (
|
|
506
|
-
const handlerFieldParams = getHandlerParamsForFieldAction({
|
|
507
|
-
promise =
|
|
546
|
+
} else if (extendedAction.type === 'field') {
|
|
547
|
+
const handlerFieldParams = getHandlerParamsForFieldAction({ extendedAction, contentSourceDataById });
|
|
548
|
+
promise = extendedAction.run({
|
|
508
549
|
...commonRunOptions,
|
|
509
550
|
...handlerFieldParams,
|
|
510
551
|
contentSourceActions: commonRunOptions.getContentSourceActionsForSource({
|
|
511
|
-
srcType:
|
|
512
|
-
srcProjectId:
|
|
552
|
+
srcType: extendedAction.documentSpec.srcType,
|
|
553
|
+
srcProjectId: extendedAction.documentSpec.srcProjectId
|
|
513
554
|
})!
|
|
514
555
|
});
|
|
515
556
|
} else {
|
|
516
|
-
throw new Error(`action type ${(
|
|
557
|
+
throw new Error(`action type ${(extendedAction as any).type} not supported`);
|
|
517
558
|
}
|
|
518
559
|
|
|
519
560
|
return promise
|
|
520
561
|
.then((actionResult) => {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
562
|
+
customActionRunStateMap[runActionRequest.actionId] = {
|
|
563
|
+
runningHandler: false,
|
|
564
|
+
lastResultState: actionResult?.state
|
|
565
|
+
};
|
|
566
|
+
userLogger.debug(`Action completed: ${extendedAction.actionId}`);
|
|
524
567
|
return Promise.resolve(
|
|
525
568
|
omitByNil({
|
|
526
|
-
actionId:
|
|
527
|
-
actionName:
|
|
528
|
-
actionType: storeActionTypeToAPIActionType(
|
|
569
|
+
actionId: extendedAction.actionId,
|
|
570
|
+
actionName: extendedAction.name,
|
|
571
|
+
actionType: storeActionTypeToAPIActionType(extendedAction.type),
|
|
529
572
|
// TODO: resolve the state if state function is defined
|
|
530
573
|
state: actionResult?.state ?? 'enabled',
|
|
531
574
|
success: actionResult?.success,
|
|
@@ -534,28 +577,32 @@ export function runCustomAction({
|
|
|
534
577
|
);
|
|
535
578
|
})
|
|
536
579
|
.catch((error: any) => {
|
|
537
|
-
|
|
538
|
-
|
|
580
|
+
customActionRunStateMap[runActionRequest.actionId] = {
|
|
581
|
+
runningHandler: false,
|
|
582
|
+
lastResultState: prevResultState
|
|
583
|
+
};
|
|
539
584
|
userLogger.debug(`Error running action: ${error.message}`);
|
|
540
585
|
return Promise.resolve({
|
|
541
|
-
actionId:
|
|
542
|
-
actionName:
|
|
543
|
-
actionType: storeActionTypeToAPIActionType(
|
|
586
|
+
actionId: extendedAction.actionId,
|
|
587
|
+
actionName: extendedAction.name,
|
|
588
|
+
actionType: storeActionTypeToAPIActionType(extendedAction.type),
|
|
544
589
|
// TODO: resolve the state if state function is defined
|
|
545
590
|
state: prevResultState ?? 'enabled',
|
|
546
591
|
error: `Error running action: ${error.message}`
|
|
547
592
|
});
|
|
548
593
|
});
|
|
549
594
|
} catch (error: any) {
|
|
550
|
-
if (
|
|
551
|
-
|
|
552
|
-
|
|
595
|
+
if (customActionRunStateMap[runActionRequest.actionId]) {
|
|
596
|
+
customActionRunStateMap[runActionRequest.actionId] = {
|
|
597
|
+
runningHandler: false,
|
|
598
|
+
lastResultState: prevResultState
|
|
599
|
+
};
|
|
553
600
|
}
|
|
554
601
|
userLogger.debug(`Error running action: ${error.message}`);
|
|
555
602
|
return Promise.resolve({
|
|
556
603
|
actionId: runActionRequest.actionId,
|
|
557
|
-
actionName:
|
|
558
|
-
actionType: storeActionTypeToAPIActionType(
|
|
604
|
+
actionName: extendedAction?.name ?? runActionRequest.actionName,
|
|
605
|
+
actionType: storeActionTypeToAPIActionType(extendedAction?.type) ?? runActionRequest.actionType,
|
|
559
606
|
// TODO: resolve the state if state function is defined
|
|
560
607
|
state: prevResultState ?? 'enabled',
|
|
561
608
|
error: `Error running action: ${error.message}`
|
|
@@ -576,24 +623,46 @@ function getCSIDocumentWithSourceFromDocumentSpec(
|
|
|
576
623
|
: undefined;
|
|
577
624
|
}
|
|
578
625
|
|
|
626
|
+
function getAPIActionState(
|
|
627
|
+
extendedAction: ExtendedCustomAction,
|
|
628
|
+
customActionRunStateMap: CustomActionRunStateMap
|
|
629
|
+
): {
|
|
630
|
+
state: StackbitTypes.CustomActionState | 'unknown';
|
|
631
|
+
needsResolving: boolean;
|
|
632
|
+
} {
|
|
633
|
+
const actionId = extendedAction.actionId;
|
|
634
|
+
const actionRunState = customActionRunStateMap[actionId];
|
|
635
|
+
let state: StackbitTypes.CustomActionState | 'unknown';
|
|
636
|
+
let needsResolving = false;
|
|
637
|
+
if (actionRunState?.runningHandler) {
|
|
638
|
+
state = 'running';
|
|
639
|
+
} else if (extendedAction.state) {
|
|
640
|
+
state = 'unknown';
|
|
641
|
+
needsResolving = true;
|
|
642
|
+
} else {
|
|
643
|
+
state = actionRunState?.lastResultState ?? 'enabled';
|
|
644
|
+
}
|
|
645
|
+
return { state, needsResolving };
|
|
646
|
+
}
|
|
647
|
+
|
|
579
648
|
function getHandlerParamsForObjectModelAction({
|
|
580
|
-
|
|
649
|
+
extendedAction,
|
|
581
650
|
contentSourceDataById
|
|
582
651
|
}: {
|
|
583
|
-
|
|
652
|
+
extendedAction: Pick<ExtendedCustomActionObjectModel, 'documentSpec' | 'fieldPath'>;
|
|
584
653
|
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
|
|
585
654
|
}): StackbitTypes.CustomActionObjectModelStateParams {
|
|
586
655
|
const fieldActionCommonParams = getHandlerParamsForFieldAction({
|
|
587
|
-
|
|
656
|
+
extendedAction,
|
|
588
657
|
contentSourceDataById
|
|
589
658
|
});
|
|
590
659
|
|
|
591
660
|
if (!fieldActionCommonParams.documentField) {
|
|
592
|
-
throw new Error(`object document field not found at field path: ${
|
|
661
|
+
throw new Error(`object document field not found at field path: ${extendedAction.fieldPath.join('.')}`);
|
|
593
662
|
}
|
|
594
663
|
|
|
595
664
|
const documentField = fieldActionCommonParams.documentField as StackbitTypes.DocumentModelFieldNonLocalized;
|
|
596
|
-
const documentSpec =
|
|
665
|
+
const documentSpec = extendedAction.documentSpec;
|
|
597
666
|
const contentSourceData = getContentSourceDataByTypeAndProjectIdOrThrow(documentSpec.srcType, documentSpec.srcProjectId, contentSourceDataById);
|
|
598
667
|
const objectModel = contentSourceData.modelMap[documentField.modelName];
|
|
599
668
|
if (!objectModel || objectModel.type !== 'object') {
|
|
@@ -613,19 +682,19 @@ function getHandlerParamsForObjectModelAction({
|
|
|
613
682
|
}
|
|
614
683
|
|
|
615
684
|
function getHandlerParamsForObjectFieldAction({
|
|
616
|
-
|
|
685
|
+
extendedAction,
|
|
617
686
|
contentSourceDataById
|
|
618
687
|
}: {
|
|
619
|
-
|
|
688
|
+
extendedAction: Pick<ExtendedCustomActionObjectField, 'documentSpec' | 'fieldPath'>;
|
|
620
689
|
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
|
|
621
690
|
}): StackbitTypes.CustomActionObjectFieldStateParams {
|
|
622
691
|
const fieldActionCommonParams = getHandlerParamsForFieldAction({
|
|
623
|
-
|
|
692
|
+
extendedAction,
|
|
624
693
|
contentSourceDataById
|
|
625
694
|
});
|
|
626
695
|
|
|
627
696
|
if (!fieldActionCommonParams.documentField) {
|
|
628
|
-
throw new Error(`object document field not found at field path: ${
|
|
697
|
+
throw new Error(`object document field not found at field path: ${extendedAction.fieldPath.join('.')}`);
|
|
629
698
|
}
|
|
630
699
|
|
|
631
700
|
return {
|
|
@@ -636,13 +705,13 @@ function getHandlerParamsForObjectFieldAction({
|
|
|
636
705
|
}
|
|
637
706
|
|
|
638
707
|
function getHandlerParamsForFieldAction({
|
|
639
|
-
|
|
708
|
+
extendedAction,
|
|
640
709
|
contentSourceDataById
|
|
641
710
|
}: {
|
|
642
|
-
|
|
711
|
+
extendedAction: Pick<ExtendedCustomActionField, 'documentSpec' | 'fieldPath'>;
|
|
643
712
|
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
|
|
644
713
|
}): StackbitTypes.CustomActionFieldStateParams {
|
|
645
|
-
const documentSpec =
|
|
714
|
+
const documentSpec = extendedAction.documentSpec;
|
|
646
715
|
const contentSourceData = getContentSourceDataByTypeAndProjectIdOrThrow(documentSpec.srcType, documentSpec.srcProjectId, contentSourceDataById);
|
|
647
716
|
const document = contentSourceData.documentMap[documentSpec.srcDocumentId];
|
|
648
717
|
const csiDocument = contentSourceData.csiDocumentMap[documentSpec.srcDocumentId];
|
|
@@ -663,7 +732,7 @@ function getHandlerParamsForFieldAction({
|
|
|
663
732
|
const { modelField, documentField } = getModelAndDocumentFieldForLocalizedFieldPath({
|
|
664
733
|
document,
|
|
665
734
|
model,
|
|
666
|
-
fieldPath:
|
|
735
|
+
fieldPath: extendedAction.fieldPath,
|
|
667
736
|
modelMap: contentSourceData.modelMap
|
|
668
737
|
}) as {
|
|
669
738
|
// list items cannot have actions, therefore we can safely reduce the type to non list item fields
|
|
@@ -682,7 +751,7 @@ function getHandlerParamsForFieldAction({
|
|
|
682
751
|
},
|
|
683
752
|
documentField: csiDocumentField,
|
|
684
753
|
modelField: modelField,
|
|
685
|
-
fieldPath:
|
|
754
|
+
fieldPath: extendedAction.fieldPath
|
|
686
755
|
};
|
|
687
756
|
}
|
|
688
757
|
|
|
@@ -722,9 +791,191 @@ function getCSIDocumentAndModelWithSourceFromDocumentSpec({
|
|
|
722
791
|
};
|
|
723
792
|
}
|
|
724
793
|
|
|
725
|
-
function storeActionTypeToAPIActionType(storeActionType:
|
|
794
|
+
function storeActionTypeToAPIActionType(storeActionType: ExtendedCustomAction['type']): APICustomAction['type'] {
|
|
726
795
|
if (storeActionType === 'objectModel' || storeActionType === 'objectField') {
|
|
727
796
|
return 'object';
|
|
728
797
|
}
|
|
729
798
|
return storeActionType;
|
|
730
799
|
}
|
|
800
|
+
|
|
801
|
+
function findCustomActionById({
|
|
802
|
+
actionId,
|
|
803
|
+
customActionRunStateMap,
|
|
804
|
+
contentSourceDataById,
|
|
805
|
+
stackbitConfig
|
|
806
|
+
}: {
|
|
807
|
+
actionId: string;
|
|
808
|
+
customActionRunStateMap: CustomActionRunStateMap;
|
|
809
|
+
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
|
|
810
|
+
stackbitConfig: Config | null;
|
|
811
|
+
}): ExtendedCustomAction | undefined {
|
|
812
|
+
const actionRunState = customActionRunStateMap[actionId];
|
|
813
|
+
if (isGlobalActionId(actionId)) {
|
|
814
|
+
if (!stackbitConfig || !Array.isArray(stackbitConfig.actions)) {
|
|
815
|
+
return undefined;
|
|
816
|
+
}
|
|
817
|
+
const actionName = getGlobalActionNameFromId(actionId);
|
|
818
|
+
const action = stackbitConfig.actions.find((action) => action.name === actionName);
|
|
819
|
+
if (!action) {
|
|
820
|
+
return undefined;
|
|
821
|
+
}
|
|
822
|
+
return {
|
|
823
|
+
...action,
|
|
824
|
+
actionId,
|
|
825
|
+
label: action.label ?? _.startCase(action.name),
|
|
826
|
+
runningHandler: actionRunState?.runningHandler,
|
|
827
|
+
lastResultState: actionRunState?.lastResultState
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
const { srcType, srcProjectId, srcDocumentId, actionName, fieldPath } = parseActionId(actionId) ?? {};
|
|
831
|
+
if (!srcType || !srcProjectId || !srcDocumentId || !actionName) {
|
|
832
|
+
return undefined;
|
|
833
|
+
}
|
|
834
|
+
const documentSpec: APICustomActionDocumentSpecifier = { srcType, srcProjectId, srcDocumentId };
|
|
835
|
+
const contentSourceData = getContentSourceDataByTypeAndProjectIdOrThrow(srcType, srcProjectId, contentSourceDataById);
|
|
836
|
+
const document = contentSourceData.documentMap[srcDocumentId];
|
|
837
|
+
if (!document) {
|
|
838
|
+
return undefined;
|
|
839
|
+
}
|
|
840
|
+
const modelName = document.srcModelName;
|
|
841
|
+
const model = contentSourceData.modelMap[modelName];
|
|
842
|
+
// The model of a document is always 'page' or 'data',
|
|
843
|
+
// this condition helps TS to infer the right type of model.actions
|
|
844
|
+
if (!model || (model.type !== 'page' && model.type !== 'data')) {
|
|
845
|
+
return undefined;
|
|
846
|
+
}
|
|
847
|
+
if (!('actions' in model) || !Array.isArray(model.actions)) {
|
|
848
|
+
return undefined;
|
|
849
|
+
}
|
|
850
|
+
if (typeof fieldPath === 'undefined') {
|
|
851
|
+
// fieldPath was not provided, therefore the model must be of type "page" or "data",
|
|
852
|
+
// and the action type must be 'document'
|
|
853
|
+
const action = model.actions.find((action) => action.name === actionName);
|
|
854
|
+
if (!action) {
|
|
855
|
+
return undefined;
|
|
856
|
+
}
|
|
857
|
+
return {
|
|
858
|
+
// if configuration is updated, the new action properties will override the stored action properties
|
|
859
|
+
...action,
|
|
860
|
+
type: 'document',
|
|
861
|
+
actionId,
|
|
862
|
+
label: action.label ?? _.startCase(action.name),
|
|
863
|
+
documentSpec,
|
|
864
|
+
runningHandler: actionRunState?.runningHandler,
|
|
865
|
+
lastResultState: actionRunState?.lastResultState
|
|
866
|
+
};
|
|
867
|
+
} else {
|
|
868
|
+
const { modelField, documentField } = getModelAndDocumentFieldForLocalizedFieldPath({
|
|
869
|
+
document,
|
|
870
|
+
model,
|
|
871
|
+
fieldPath,
|
|
872
|
+
modelMap: contentSourceData.modelMap
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
if ('actions' in modelField && Array.isArray(modelField.actions)) {
|
|
876
|
+
const action = modelField.actions.find((action) => action.name === actionName);
|
|
877
|
+
if (action) {
|
|
878
|
+
return {
|
|
879
|
+
// if configuration is updated, the new action properties will override the stored action properties
|
|
880
|
+
...action,
|
|
881
|
+
type: action.type === 'object' ? 'objectField' : 'field',
|
|
882
|
+
actionId,
|
|
883
|
+
label: action.label ?? _.startCase(action.name),
|
|
884
|
+
documentSpec,
|
|
885
|
+
fieldPath,
|
|
886
|
+
runningHandler: actionRunState?.runningHandler,
|
|
887
|
+
lastResultState: actionRunState?.lastResultState
|
|
888
|
+
} as ExtendedCustomActionField | ExtendedCustomActionObjectField;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
if (modelField.type === 'model') {
|
|
893
|
+
if (documentField.type !== 'model' || documentField.localized || documentField.isUnset) {
|
|
894
|
+
return undefined;
|
|
895
|
+
}
|
|
896
|
+
const modelName = documentField.srcModelName;
|
|
897
|
+
const model = contentSourceData.modelMap[modelName];
|
|
898
|
+
if (!model || model.type !== 'object') {
|
|
899
|
+
return undefined;
|
|
900
|
+
}
|
|
901
|
+
if (!('actions' in model && Array.isArray(model.actions))) {
|
|
902
|
+
return undefined;
|
|
903
|
+
}
|
|
904
|
+
// This is a nested model of type "object", so the action must be CustomActionObjectModel
|
|
905
|
+
const action = model.actions.find((action) => action.name === actionName);
|
|
906
|
+
if (!action) {
|
|
907
|
+
return undefined;
|
|
908
|
+
}
|
|
909
|
+
return {
|
|
910
|
+
// if configuration is updated, the new action properties will override the stored action properties
|
|
911
|
+
...action,
|
|
912
|
+
type: 'objectModel',
|
|
913
|
+
actionId,
|
|
914
|
+
label: action.label ?? _.startCase(action.name),
|
|
915
|
+
documentSpec,
|
|
916
|
+
fieldPath,
|
|
917
|
+
runningHandler: actionRunState?.runningHandler,
|
|
918
|
+
lastResultState: actionRunState?.lastResultState
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
function globalActionId(action: StackbitTypes.CustomActionGlobal | StackbitTypes.CustomActionBulk): string {
|
|
925
|
+
return `config.actions.${action.name}`;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
function isGlobalActionId(actionId: string) {
|
|
929
|
+
return actionId.startsWith('config.actions.');
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
function getGlobalActionNameFromId(actionId: string) {
|
|
933
|
+
return actionId.substring('config.actions.'.length);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
function documentActionId({ srcType, srcProjectId, srcDocumentId, actionName }: APICustomActionDocumentSpecifier & { actionName: string }): string {
|
|
937
|
+
return `${srcType}:${srcProjectId}:${srcDocumentId}:${actionName}`;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
function fieldPathActionId({
|
|
941
|
+
srcType,
|
|
942
|
+
srcProjectId,
|
|
943
|
+
srcDocumentId,
|
|
944
|
+
fieldPath,
|
|
945
|
+
actionName
|
|
946
|
+
}: APICustomActionDocumentSpecifier & { fieldPath: (string | number)[]; actionName: string }): string {
|
|
947
|
+
return `${srcType}:${srcProjectId}:${srcDocumentId}:${fieldPath.join('.')}:${actionName}`;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
function parseActionId(actionId: string):
|
|
951
|
+
| {
|
|
952
|
+
srcType?: string;
|
|
953
|
+
srcProjectId?: string;
|
|
954
|
+
srcDocumentId?: string;
|
|
955
|
+
actionName?: string;
|
|
956
|
+
fieldPath?: string[];
|
|
957
|
+
}
|
|
958
|
+
| undefined {
|
|
959
|
+
const parts = actionId.split(':');
|
|
960
|
+
if (parts.length < 4 || parts.length > 5) {
|
|
961
|
+
return undefined;
|
|
962
|
+
}
|
|
963
|
+
const srcType = parts[0];
|
|
964
|
+
const srcProjectId = parts[1];
|
|
965
|
+
const srcDocumentId = parts[2];
|
|
966
|
+
let fieldPath: string[] | undefined;
|
|
967
|
+
let actionName: string | undefined;
|
|
968
|
+
if (parts.length === 5) {
|
|
969
|
+
fieldPath = parts[3]?.split('.');
|
|
970
|
+
actionName = parts[4];
|
|
971
|
+
} else {
|
|
972
|
+
actionName = parts[3];
|
|
973
|
+
}
|
|
974
|
+
return {
|
|
975
|
+
srcType,
|
|
976
|
+
srcProjectId,
|
|
977
|
+
srcDocumentId,
|
|
978
|
+
actionName,
|
|
979
|
+
fieldPath
|
|
980
|
+
};
|
|
981
|
+
}
|