@webiny/api-headless-cms 0.0.0-unstable.d65ec29d44 → 0.0.0-unstable.da99e0b846
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/context.js +47 -43
- package/context.js.map +1 -1
- package/crud/contentEntry/markLockedFields.d.ts +1 -1
- package/crud/contentEntry/markLockedFields.js +3 -0
- package/crud/contentEntry/markLockedFields.js.map +1 -1
- package/crud/contentEntry.crud.d.ts +5 -2
- package/crud/contentEntry.crud.js +848 -830
- package/crud/contentEntry.crud.js.map +1 -1
- package/crud/contentModel/beforeCreate.js +39 -76
- package/crud/contentModel/beforeCreate.js.map +1 -1
- package/crud/contentModel/beforeDelete.d.ts +1 -1
- package/crud/contentModel/beforeDelete.js +1 -5
- package/crud/contentModel/beforeDelete.js.map +1 -1
- package/crud/contentModel/beforeUpdate.js +31 -3
- package/crud/contentModel/beforeUpdate.js.map +1 -1
- package/crud/contentModel/compatibility/modelApiName.d.ts +3 -0
- package/crud/contentModel/compatibility/modelApiName.js +24 -0
- package/crud/contentModel/compatibility/modelApiName.js.map +1 -0
- package/crud/contentModel/defaultFields.d.ts +5 -0
- package/crud/contentModel/defaultFields.js +58 -0
- package/crud/contentModel/defaultFields.js.map +1 -0
- package/crud/contentModel/fields/descriptionField.d.ts +2 -0
- package/crud/contentModel/fields/descriptionField.js +42 -0
- package/crud/contentModel/fields/descriptionField.js.map +1 -0
- package/crud/contentModel/fields/imageField.d.ts +2 -0
- package/crud/contentModel/fields/imageField.js +46 -0
- package/crud/contentModel/fields/imageField.js.map +1 -0
- package/crud/contentModel/fields/titleField.d.ts +2 -0
- package/crud/contentModel/fields/titleField.js +58 -0
- package/crud/contentModel/fields/titleField.js.map +1 -0
- package/crud/contentModel/systemFields.js.map +1 -1
- package/crud/contentModel/validate/endingAllowed.d.ts +6 -0
- package/crud/contentModel/validate/endingAllowed.js +26 -0
- package/crud/contentModel/validate/endingAllowed.js.map +1 -0
- package/crud/contentModel/validate/isModelEndingAllowed.d.ts +6 -0
- package/crud/contentModel/validate/isModelEndingAllowed.js +24 -0
- package/crud/contentModel/validate/isModelEndingAllowed.js.map +1 -0
- package/crud/contentModel/validate/modelId.d.ts +11 -0
- package/crud/contentModel/validate/modelId.js +36 -0
- package/crud/contentModel/validate/modelId.js.map +1 -0
- package/crud/contentModel/validate/pluralApiName.d.ts +7 -0
- package/crud/contentModel/validate/pluralApiName.js +24 -0
- package/crud/contentModel/validate/pluralApiName.js.map +1 -0
- package/crud/contentModel/validate/singularApiName.d.ts +7 -0
- package/crud/contentModel/validate/singularApiName.js +24 -0
- package/crud/contentModel/validate/singularApiName.js.map +1 -0
- package/crud/contentModel/validateModel.d.ts +1 -0
- package/crud/contentModel/validateModel.js.map +1 -1
- package/crud/contentModel/validateModelFields.d.ts +2 -1
- package/crud/contentModel/validateModelFields.js +19 -57
- package/crud/contentModel/validateModelFields.js.map +1 -1
- package/crud/contentModel/validation.d.ts +136 -62
- package/crud/contentModel/validation.js +61 -13
- package/crud/contentModel/validation.js.map +1 -1
- package/crud/contentModel.crud.js +346 -285
- package/crud/contentModel.crud.js.map +1 -1
- package/crud/contentModelGroup.crud.js +170 -142
- package/crud/contentModelGroup.crud.js.map +1 -1
- package/crud/settings.crud.d.ts +1 -1
- package/crud/settings.crud.js +5 -10
- package/crud/settings.crud.js.map +1 -1
- package/crud/system.crud.js +0 -60
- package/crud/system.crud.js.map +1 -1
- package/graphql/checkEndpointAccess.d.ts +2 -0
- package/graphql/checkEndpointAccess.js +18 -0
- package/graphql/checkEndpointAccess.js.map +1 -0
- package/graphql/createExecutableSchema.d.ts +2 -3
- package/graphql/createExecutableSchema.js.map +1 -1
- package/graphql/createRequestBody.d.ts +2 -0
- package/graphql/createRequestBody.js +14 -0
- package/graphql/createRequestBody.js.map +1 -0
- package/graphql/formatErrorPayload.d.ts +1 -0
- package/graphql/formatErrorPayload.js +25 -0
- package/graphql/formatErrorPayload.js.map +1 -0
- package/graphql/generateSchema.js.map +1 -1
- package/graphql/getSchema.d.ts +17 -0
- package/graphql/getSchema.js +102 -0
- package/graphql/getSchema.js.map +1 -0
- package/graphql/graphQLHandlerFactory.js +6 -145
- package/graphql/graphQLHandlerFactory.js.map +1 -1
- package/graphql/handleRequest.d.ts +11 -0
- package/graphql/handleRequest.js +81 -0
- package/graphql/handleRequest.js.map +1 -0
- package/graphql/schema/baseContentSchema.js +1 -7
- package/graphql/schema/baseContentSchema.js.map +1 -1
- package/graphql/schema/contentEntries.js +90 -53
- package/graphql/schema/contentEntries.js.map +1 -1
- package/graphql/schema/contentModelGroups.js +7 -7
- package/graphql/schema/contentModelGroups.js.map +1 -1
- package/graphql/schema/contentModels.js +23 -4
- package/graphql/schema/contentModels.js.map +1 -1
- package/graphql/schema/createManageResolvers.d.ts +1 -1
- package/graphql/schema/createManageResolvers.js +33 -17
- package/graphql/schema/createManageResolvers.js.map +1 -1
- package/graphql/schema/createManageSDL.d.ts +1 -0
- package/graphql/schema/createManageSDL.js +55 -49
- package/graphql/schema/createManageSDL.js.map +1 -1
- package/graphql/schema/createPreviewResolvers.js +3 -7
- package/graphql/schema/createPreviewResolvers.js.map +1 -1
- package/graphql/schema/createReadResolvers.js +4 -8
- package/graphql/schema/createReadResolvers.js.map +1 -1
- package/graphql/schema/createReadSDL.d.ts +1 -0
- package/graphql/schema/createReadSDL.js +24 -22
- package/graphql/schema/createReadSDL.js.map +1 -1
- package/graphql/schema/resolvers/commonFieldResolvers.d.ts +3 -2
- package/graphql/schema/resolvers/commonFieldResolvers.js +2 -1
- package/graphql/schema/resolvers/commonFieldResolvers.js.map +1 -1
- package/graphql/schema/schemaPlugins.js +12 -12
- package/graphql/schema/schemaPlugins.js.map +1 -1
- package/graphql/system.js +0 -16
- package/graphql/system.js.map +1 -1
- package/graphqlFields/dynamicZone/dynamicZoneField.js +12 -4
- package/graphqlFields/dynamicZone/dynamicZoneField.js.map +1 -1
- package/graphqlFields/object.js +21 -2
- package/graphqlFields/object.js.map +1 -1
- package/graphqlFields/ref.js +42 -14
- package/graphqlFields/ref.js.map +1 -1
- package/index.d.ts +3 -1
- package/index.js +25 -2
- package/index.js.map +1 -1
- package/package.json +22 -23
- package/plugins/CmsModelPlugin.d.ts +19 -3
- package/plugins/CmsModelPlugin.js +28 -2
- package/plugins/CmsModelPlugin.js.map +1 -1
- package/plugins/StorageOperationsCmsModelPlugin.d.ts +23 -0
- package/plugins/StorageOperationsCmsModelPlugin.js +42 -0
- package/plugins/StorageOperationsCmsModelPlugin.js.map +1 -0
- package/plugins/index.d.ts +1 -0
- package/plugins/index.js +11 -0
- package/plugins/index.js.map +1 -1
- package/types.d.ts +118 -66
- package/types.js +1 -1
- package/types.js.map +1 -1
- package/upgrades/5.33.0/index.js +26 -3
- package/upgrades/5.33.0/index.js.map +1 -1
- package/upgrades/index.js +3 -0
- package/upgrades/index.js.map +1 -1
- package/utils/converters/valueKeyStorageConverter.d.ts +1 -5
- package/utils/converters/valueKeyStorageConverter.js +21 -18
- package/utils/converters/valueKeyStorageConverter.js.map +1 -1
- package/utils/createTypeFromFields.d.ts +1 -0
- package/utils/createTypeFromFields.js +7 -5
- package/utils/createTypeFromFields.js.map +1 -1
- package/utils/createTypeName.d.ts +0 -2
- package/utils/createTypeName.js +2 -10
- package/utils/createTypeName.js.map +1 -1
- package/utils/getEntryDescription.d.ts +2 -0
- package/utils/getEntryDescription.js +17 -0
- package/utils/getEntryDescription.js.map +1 -0
- package/utils/getEntryImage.d.ts +2 -0
- package/utils/getEntryImage.js +17 -0
- package/utils/getEntryImage.js.map +1 -0
- package/utils/incrementEntryIdVersion.d.ts +5 -0
- package/utils/incrementEntryIdVersion.js +29 -0
- package/utils/incrementEntryIdVersion.js.map +1 -0
- package/utils/ownership.d.ts +3 -3
- package/utils/ownership.js.map +1 -1
- package/utils/pluralizedTypeName.js +6 -0
- package/utils/pluralizedTypeName.js.map +1 -1
- package/utils/renderFields.d.ts +2 -1
- package/utils/renderFields.js +8 -1
- package/utils/renderFields.js.map +1 -1
- package/utils/renderInputFields.d.ts +2 -1
- package/utils/renderInputFields.js +4 -0
- package/utils/renderInputFields.js.map +1 -1
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.createModelsCrud = void 0;
|
|
8
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
|
8
9
|
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
|
9
10
|
var _dataloader = _interopRequireDefault(require("dataloader"));
|
|
10
11
|
var _error = _interopRequireDefault(require("@webiny/error"));
|
|
@@ -25,6 +26,9 @@ var _ownership = require("../utils/ownership");
|
|
|
25
26
|
var _access = require("../utils/access");
|
|
26
27
|
var _validation = require("./contentModel/validation");
|
|
27
28
|
var _utils = require("@webiny/utils");
|
|
29
|
+
var _defaultFields = require("./contentModel/defaultFields");
|
|
30
|
+
var _modelApiName = require("./contentModel/compatibility/modelApiName");
|
|
31
|
+
const _excluded = ["defaultFields"];
|
|
28
32
|
/**
|
|
29
33
|
* Given a model, return an array of tags ensuring the `type` tag is set.
|
|
30
34
|
*/
|
|
@@ -57,7 +61,13 @@ const createModelsCrud = params => {
|
|
|
57
61
|
return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, model), {}, {
|
|
58
62
|
tags: ensureTypeTag(model),
|
|
59
63
|
tenant: model.tenant || getTenant().id,
|
|
60
|
-
locale: model.locale || getLocale().code
|
|
64
|
+
locale: model.locale || getLocale().code,
|
|
65
|
+
/**
|
|
66
|
+
* TODO: remove in v5.36.0
|
|
67
|
+
* This is for backward compatibility while migrations are not yet executed.
|
|
68
|
+
*/
|
|
69
|
+
singularApiName: (0, _modelApiName.ensureSingularApiName)(model),
|
|
70
|
+
pluralApiName: (0, _modelApiName.ensurePluralApiName)(model)
|
|
61
71
|
});
|
|
62
72
|
})];
|
|
63
73
|
})
|
|
@@ -130,21 +140,25 @@ const createModelsCrud = params => {
|
|
|
130
140
|
return databaseModels.concat(pluginsModels);
|
|
131
141
|
};
|
|
132
142
|
const listModels = async () => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
return context.benchmark.measure("headlessCms.crud.models.listModels", async () => {
|
|
144
|
+
const permission = await checkModelPermissions("r");
|
|
145
|
+
const models = await modelsList();
|
|
146
|
+
return (0, _filterAsync.filterAsync)(models, async model => {
|
|
147
|
+
if (!(0, _ownership.validateOwnership)(context, permission, model)) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
return (0, _access.validateModelAccess)(context, model);
|
|
151
|
+
});
|
|
140
152
|
});
|
|
141
153
|
};
|
|
142
154
|
const getModel = async modelId => {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
155
|
+
return context.benchmark.measure("headlessCms.crud.models.getModel", async () => {
|
|
156
|
+
const permission = await checkModelPermissions("r");
|
|
157
|
+
const model = await modelsGet(modelId);
|
|
158
|
+
(0, _ownership.checkOwnership)(context, permission, model);
|
|
159
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
160
|
+
return model;
|
|
161
|
+
});
|
|
148
162
|
};
|
|
149
163
|
const getModelManager = async target => {
|
|
150
164
|
const modelId = typeof target === "string" ? target : target.modelId;
|
|
@@ -221,6 +235,311 @@ const createModelsCrud = params => {
|
|
|
221
235
|
context,
|
|
222
236
|
onModelAfterDelete
|
|
223
237
|
});
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* CRUD methods
|
|
241
|
+
*/
|
|
242
|
+
const createModel = async input => {
|
|
243
|
+
await checkModelPermissions("w");
|
|
244
|
+
const result = await (0, _validation.createModelCreateValidation)().safeParseAsync(input);
|
|
245
|
+
if (!result.success) {
|
|
246
|
+
throw (0, _utils.createZodError)(result.error);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* We need to extract the defaultFields because it is not for the CmsModel object.
|
|
250
|
+
*/
|
|
251
|
+
const _removeUndefinedValue = (0, _utils.removeUndefinedValues)(result.data),
|
|
252
|
+
{
|
|
253
|
+
defaultFields
|
|
254
|
+
} = _removeUndefinedValue,
|
|
255
|
+
data = (0, _objectWithoutProperties2.default)(_removeUndefinedValue, _excluded);
|
|
256
|
+
if (defaultFields) {
|
|
257
|
+
(0, _defaultFields.assignModelDefaultFields)(data);
|
|
258
|
+
}
|
|
259
|
+
const group = await context.security.withoutAuthorization(async () => {
|
|
260
|
+
return context.cms.getGroup(data.group);
|
|
261
|
+
});
|
|
262
|
+
if (!group) {
|
|
263
|
+
throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
|
|
264
|
+
}
|
|
265
|
+
const identity = getIdentity();
|
|
266
|
+
const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, data), {}, {
|
|
267
|
+
modelId: data.modelId || "",
|
|
268
|
+
singularApiName: data.singularApiName,
|
|
269
|
+
pluralApiName: data.pluralApiName,
|
|
270
|
+
titleFieldId: "id",
|
|
271
|
+
descriptionFieldId: null,
|
|
272
|
+
imageFieldId: null,
|
|
273
|
+
description: data.description || "",
|
|
274
|
+
locale: getLocale().code,
|
|
275
|
+
tenant: getTenant().id,
|
|
276
|
+
group: {
|
|
277
|
+
id: group.id,
|
|
278
|
+
name: group.name
|
|
279
|
+
},
|
|
280
|
+
createdBy: {
|
|
281
|
+
id: identity.id,
|
|
282
|
+
displayName: identity.displayName,
|
|
283
|
+
type: identity.type
|
|
284
|
+
},
|
|
285
|
+
createdOn: new Date().toISOString(),
|
|
286
|
+
savedOn: new Date().toISOString(),
|
|
287
|
+
lockedFields: [],
|
|
288
|
+
webinyVersion: context.WEBINY_VERSION
|
|
289
|
+
});
|
|
290
|
+
model.tags = ensureTypeTag(model);
|
|
291
|
+
try {
|
|
292
|
+
await onModelBeforeCreate.publish({
|
|
293
|
+
input: data,
|
|
294
|
+
model
|
|
295
|
+
});
|
|
296
|
+
const createdModel = await storageOperations.models.create({
|
|
297
|
+
model
|
|
298
|
+
});
|
|
299
|
+
loaders.listModels.clearAll();
|
|
300
|
+
await updateManager(context, model);
|
|
301
|
+
await onModelAfterCreate.publish({
|
|
302
|
+
input: data,
|
|
303
|
+
model: createdModel
|
|
304
|
+
});
|
|
305
|
+
return createdModel;
|
|
306
|
+
} catch (ex) {
|
|
307
|
+
await onModelCreateError.publish({
|
|
308
|
+
input: data,
|
|
309
|
+
model,
|
|
310
|
+
error: ex
|
|
311
|
+
});
|
|
312
|
+
throw ex;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
const updateModel = async (modelId, input) => {
|
|
316
|
+
await checkModelPermissions("w");
|
|
317
|
+
|
|
318
|
+
// Get a model record; this will also perform ownership validation.
|
|
319
|
+
const original = await getModel(modelId);
|
|
320
|
+
const result = await (0, _validation.createModelUpdateValidation)().safeParseAsync(input);
|
|
321
|
+
if (!result.success) {
|
|
322
|
+
throw (0, _utils.createZodError)(result.error);
|
|
323
|
+
}
|
|
324
|
+
const data = (0, _utils.removeUndefinedValues)(result.data);
|
|
325
|
+
if (Object.keys(data).length === 0) {
|
|
326
|
+
/**
|
|
327
|
+
* We need to return the original if nothing is to be updated.
|
|
328
|
+
*/
|
|
329
|
+
return original;
|
|
330
|
+
}
|
|
331
|
+
let group = {
|
|
332
|
+
id: original.group.id,
|
|
333
|
+
name: original.group.name
|
|
334
|
+
};
|
|
335
|
+
const groupId = data.group;
|
|
336
|
+
if (groupId) {
|
|
337
|
+
const groupData = await context.security.withoutAuthorization(async () => {
|
|
338
|
+
return context.cms.getGroup(groupId);
|
|
339
|
+
});
|
|
340
|
+
if (!groupData) {
|
|
341
|
+
throw new _handlerGraphql.NotFoundError(`There is no group "${groupId}".`);
|
|
342
|
+
}
|
|
343
|
+
group = {
|
|
344
|
+
id: groupData.id,
|
|
345
|
+
name: groupData.name
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
const model = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, original), data), {}, {
|
|
349
|
+
titleFieldId: data.titleFieldId === undefined ? original.titleFieldId : data.titleFieldId,
|
|
350
|
+
descriptionFieldId: data.descriptionFieldId === undefined ? original.descriptionFieldId : data.descriptionFieldId,
|
|
351
|
+
imageFieldId: data.imageFieldId === undefined ? original.imageFieldId : data.imageFieldId,
|
|
352
|
+
group,
|
|
353
|
+
description: data.description || original.description,
|
|
354
|
+
tenant: original.tenant || getTenant().id,
|
|
355
|
+
locale: original.locale || getLocale().code,
|
|
356
|
+
webinyVersion: context.WEBINY_VERSION,
|
|
357
|
+
savedOn: new Date().toISOString()
|
|
358
|
+
});
|
|
359
|
+
model.tags = ensureTypeTag(model);
|
|
360
|
+
try {
|
|
361
|
+
await onModelBeforeUpdate.publish({
|
|
362
|
+
input: data,
|
|
363
|
+
original,
|
|
364
|
+
model
|
|
365
|
+
});
|
|
366
|
+
const resultModel = await storageOperations.models.update({
|
|
367
|
+
model
|
|
368
|
+
});
|
|
369
|
+
await updateManager(context, resultModel);
|
|
370
|
+
await onModelAfterUpdate.publish({
|
|
371
|
+
input: data,
|
|
372
|
+
original,
|
|
373
|
+
model: resultModel
|
|
374
|
+
});
|
|
375
|
+
return resultModel;
|
|
376
|
+
} catch (ex) {
|
|
377
|
+
await onModelUpdateError.publish({
|
|
378
|
+
input: data,
|
|
379
|
+
model,
|
|
380
|
+
original,
|
|
381
|
+
error: ex
|
|
382
|
+
});
|
|
383
|
+
throw ex;
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
const updateModelDirect = async params => {
|
|
387
|
+
const {
|
|
388
|
+
model: initialModel,
|
|
389
|
+
original
|
|
390
|
+
} = params;
|
|
391
|
+
const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, initialModel), {}, {
|
|
392
|
+
tenant: initialModel.tenant || getTenant().id,
|
|
393
|
+
locale: initialModel.locale || getLocale().code,
|
|
394
|
+
webinyVersion: context.WEBINY_VERSION
|
|
395
|
+
});
|
|
396
|
+
try {
|
|
397
|
+
await onModelBeforeUpdate.publish({
|
|
398
|
+
input: {},
|
|
399
|
+
original,
|
|
400
|
+
model
|
|
401
|
+
});
|
|
402
|
+
const resultModel = await storageOperations.models.update({
|
|
403
|
+
model
|
|
404
|
+
});
|
|
405
|
+
await updateManager(context, resultModel);
|
|
406
|
+
loaders.listModels.clearAll();
|
|
407
|
+
await onModelAfterUpdate.publish({
|
|
408
|
+
input: {},
|
|
409
|
+
original,
|
|
410
|
+
model: resultModel
|
|
411
|
+
});
|
|
412
|
+
return resultModel;
|
|
413
|
+
} catch (ex) {
|
|
414
|
+
await onModelUpdateError.publish({
|
|
415
|
+
input: {},
|
|
416
|
+
original,
|
|
417
|
+
model,
|
|
418
|
+
error: ex
|
|
419
|
+
});
|
|
420
|
+
throw ex;
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
const createModelFrom = async (modelId, input) => {
|
|
424
|
+
await checkModelPermissions("w");
|
|
425
|
+
/**
|
|
426
|
+
* Get a model record; this will also perform ownership validation.
|
|
427
|
+
*/
|
|
428
|
+
const original = await getModel(modelId);
|
|
429
|
+
const result = await (0, _validation.createModelCreateFromValidation)().safeParseAsync((0, _objectSpread2.default)((0, _objectSpread2.default)({}, input), {}, {
|
|
430
|
+
description: input.description || original.description
|
|
431
|
+
}));
|
|
432
|
+
if (!result.success) {
|
|
433
|
+
throw (0, _utils.createZodError)(result.error);
|
|
434
|
+
}
|
|
435
|
+
const data = (0, _utils.removeUndefinedValues)(result.data);
|
|
436
|
+
const locale = await context.i18n.getLocale(data.locale || original.locale);
|
|
437
|
+
if (!locale) {
|
|
438
|
+
throw new _handlerGraphql.NotFoundError(`There is no locale "${data.locale}".`);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Use storage operations directly because we cannot get group from different locale via context methods.
|
|
442
|
+
*/
|
|
443
|
+
const group = await context.cms.storageOperations.groups.get({
|
|
444
|
+
id: data.group,
|
|
445
|
+
tenant: original.tenant,
|
|
446
|
+
locale: locale.code
|
|
447
|
+
});
|
|
448
|
+
if (!group) {
|
|
449
|
+
throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
|
|
450
|
+
}
|
|
451
|
+
const identity = getIdentity();
|
|
452
|
+
const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, original), {}, {
|
|
453
|
+
singularApiName: data.singularApiName,
|
|
454
|
+
pluralApiName: data.pluralApiName,
|
|
455
|
+
locale: locale.code,
|
|
456
|
+
group: {
|
|
457
|
+
id: group.id,
|
|
458
|
+
name: group.name
|
|
459
|
+
},
|
|
460
|
+
icon: data.icon,
|
|
461
|
+
name: data.name,
|
|
462
|
+
modelId: data.modelId || "",
|
|
463
|
+
description: data.description || "",
|
|
464
|
+
createdBy: {
|
|
465
|
+
id: identity.id,
|
|
466
|
+
displayName: identity.displayName,
|
|
467
|
+
type: identity.type
|
|
468
|
+
},
|
|
469
|
+
createdOn: new Date().toISOString(),
|
|
470
|
+
savedOn: new Date().toISOString(),
|
|
471
|
+
lockedFields: [],
|
|
472
|
+
webinyVersion: context.WEBINY_VERSION
|
|
473
|
+
});
|
|
474
|
+
try {
|
|
475
|
+
await onModelBeforeCreateFrom.publish({
|
|
476
|
+
input: data,
|
|
477
|
+
model,
|
|
478
|
+
original
|
|
479
|
+
});
|
|
480
|
+
const createdModel = await storageOperations.models.create({
|
|
481
|
+
model
|
|
482
|
+
});
|
|
483
|
+
loaders.listModels.clearAll();
|
|
484
|
+
await updateManager(context, model);
|
|
485
|
+
await onModelAfterCreateFrom.publish({
|
|
486
|
+
input: data,
|
|
487
|
+
original,
|
|
488
|
+
model: createdModel
|
|
489
|
+
});
|
|
490
|
+
return createdModel;
|
|
491
|
+
} catch (ex) {
|
|
492
|
+
await onModelCreateFromError.publish({
|
|
493
|
+
input: data,
|
|
494
|
+
original,
|
|
495
|
+
model,
|
|
496
|
+
error: ex
|
|
497
|
+
});
|
|
498
|
+
throw ex;
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
const deleteModel = async modelId => {
|
|
502
|
+
await checkModelPermissions("d");
|
|
503
|
+
const model = await getModel(modelId);
|
|
504
|
+
try {
|
|
505
|
+
await onModelBeforeDelete.publish({
|
|
506
|
+
model
|
|
507
|
+
});
|
|
508
|
+
try {
|
|
509
|
+
await storageOperations.models.delete({
|
|
510
|
+
model
|
|
511
|
+
});
|
|
512
|
+
} catch (ex) {
|
|
513
|
+
throw new _error.default(ex.message || "Could not delete the content model", ex.code || "CONTENT_MODEL_DELETE_ERROR", {
|
|
514
|
+
error: ex,
|
|
515
|
+
modelId: model.modelId
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
await onModelAfterDelete.publish({
|
|
519
|
+
model
|
|
520
|
+
});
|
|
521
|
+
managers.delete(model.modelId);
|
|
522
|
+
} catch (ex) {
|
|
523
|
+
await onModelDeleteError.publish({
|
|
524
|
+
model,
|
|
525
|
+
error: ex
|
|
526
|
+
});
|
|
527
|
+
throw ex;
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
const initializeModel = async (modelId, data) => {
|
|
531
|
+
/**
|
|
532
|
+
* We require that users have write permissions to initialize models.
|
|
533
|
+
* Maybe introduce another permission for it?
|
|
534
|
+
*/
|
|
535
|
+
await checkModelPermissions("w");
|
|
536
|
+
const model = await getModel(modelId);
|
|
537
|
+
await onModelInitialize.publish({
|
|
538
|
+
model,
|
|
539
|
+
data
|
|
540
|
+
});
|
|
541
|
+
return true;
|
|
542
|
+
};
|
|
224
543
|
return {
|
|
225
544
|
/**
|
|
226
545
|
* Deprecated - will be removed in 5.36.0
|
|
@@ -253,296 +572,38 @@ const createModelsCrud = params => {
|
|
|
253
572
|
getModel,
|
|
254
573
|
listModels,
|
|
255
574
|
async createModel(input) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
throw (0, _utils.createZodError)(result.error);
|
|
260
|
-
}
|
|
261
|
-
const data = result.data;
|
|
262
|
-
context.security.disableAuthorization();
|
|
263
|
-
const group = await context.cms.getGroup(data.group);
|
|
264
|
-
context.security.enableAuthorization();
|
|
265
|
-
if (!group) {
|
|
266
|
-
throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
|
|
267
|
-
}
|
|
268
|
-
const identity = getIdentity();
|
|
269
|
-
const model = {
|
|
270
|
-
name: data.name,
|
|
271
|
-
description: data.description || "",
|
|
272
|
-
modelId: data.modelId || "",
|
|
273
|
-
titleFieldId: "id",
|
|
274
|
-
locale: getLocale().code,
|
|
275
|
-
tenant: getTenant().id,
|
|
276
|
-
group: {
|
|
277
|
-
id: group.id,
|
|
278
|
-
name: group.name
|
|
279
|
-
},
|
|
280
|
-
createdBy: {
|
|
281
|
-
id: identity.id,
|
|
282
|
-
displayName: identity.displayName,
|
|
283
|
-
type: identity.type
|
|
284
|
-
},
|
|
285
|
-
createdOn: new Date().toISOString(),
|
|
286
|
-
savedOn: new Date().toISOString(),
|
|
287
|
-
fields: data.fields,
|
|
288
|
-
lockedFields: [],
|
|
289
|
-
layout: data.layout || [],
|
|
290
|
-
tags: [...(data.tags || [])],
|
|
291
|
-
webinyVersion: context.WEBINY_VERSION
|
|
292
|
-
};
|
|
293
|
-
model.tags = ensureTypeTag(model);
|
|
294
|
-
try {
|
|
295
|
-
await onModelBeforeCreate.publish({
|
|
296
|
-
input: data,
|
|
297
|
-
model
|
|
298
|
-
});
|
|
299
|
-
const createdModel = await storageOperations.models.create({
|
|
300
|
-
model
|
|
301
|
-
});
|
|
302
|
-
loaders.listModels.clearAll();
|
|
303
|
-
await updateManager(context, model);
|
|
304
|
-
await onModelAfterCreate.publish({
|
|
305
|
-
input: data,
|
|
306
|
-
model: createdModel
|
|
307
|
-
});
|
|
308
|
-
return createdModel;
|
|
309
|
-
} catch (ex) {
|
|
310
|
-
await onModelCreateError.publish({
|
|
311
|
-
input: data,
|
|
312
|
-
model,
|
|
313
|
-
error: ex
|
|
314
|
-
});
|
|
315
|
-
throw ex;
|
|
316
|
-
}
|
|
575
|
+
return context.benchmark.measure("headlessCms.crud.models.createModel", async () => {
|
|
576
|
+
return createModel(input);
|
|
577
|
+
});
|
|
317
578
|
},
|
|
318
579
|
/**
|
|
319
580
|
* Method does not check for permissions or ownership.
|
|
320
581
|
* @internal
|
|
321
582
|
*/
|
|
322
583
|
async updateModelDirect(params) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
original
|
|
326
|
-
} = params;
|
|
327
|
-
const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, initialModel), {}, {
|
|
328
|
-
tenant: initialModel.tenant || getTenant().id,
|
|
329
|
-
locale: initialModel.locale || getLocale().code,
|
|
330
|
-
webinyVersion: context.WEBINY_VERSION
|
|
584
|
+
return context.benchmark.measure("headlessCms.crud.models.updateModelDirect", async () => {
|
|
585
|
+
return updateModelDirect(params);
|
|
331
586
|
});
|
|
332
|
-
try {
|
|
333
|
-
await onModelBeforeUpdate.publish({
|
|
334
|
-
input: {},
|
|
335
|
-
original,
|
|
336
|
-
model
|
|
337
|
-
});
|
|
338
|
-
const resultModel = await storageOperations.models.update({
|
|
339
|
-
model
|
|
340
|
-
});
|
|
341
|
-
await updateManager(context, resultModel);
|
|
342
|
-
loaders.listModels.clearAll();
|
|
343
|
-
await onModelAfterUpdate.publish({
|
|
344
|
-
input: {},
|
|
345
|
-
original,
|
|
346
|
-
model: resultModel
|
|
347
|
-
});
|
|
348
|
-
return resultModel;
|
|
349
|
-
} catch (ex) {
|
|
350
|
-
await onModelUpdateError.publish({
|
|
351
|
-
input: {},
|
|
352
|
-
original,
|
|
353
|
-
model,
|
|
354
|
-
error: ex
|
|
355
|
-
});
|
|
356
|
-
throw ex;
|
|
357
|
-
}
|
|
358
587
|
},
|
|
359
588
|
async createModelFrom(modelId, userInput) {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
* Get a model record; this will also perform ownership validation.
|
|
363
|
-
*/
|
|
364
|
-
const original = await getModel(modelId);
|
|
365
|
-
const result = await (0, _validation.createModelCreateFromValidation)().safeParseAsync({
|
|
366
|
-
name: userInput.name,
|
|
367
|
-
modelId: userInput.modelId,
|
|
368
|
-
description: userInput.description || original.description,
|
|
369
|
-
group: userInput.group,
|
|
370
|
-
locale: userInput.locale
|
|
371
|
-
});
|
|
372
|
-
if (!result.success) {
|
|
373
|
-
throw (0, _utils.createZodError)(result.error);
|
|
374
|
-
}
|
|
375
|
-
const data = result.data;
|
|
376
|
-
const locale = await context.i18n.getLocale(data.locale || original.locale);
|
|
377
|
-
if (!locale) {
|
|
378
|
-
throw new _handlerGraphql.NotFoundError(`There is no locale "${data.locale}".`);
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* Use storage operations directly because we cannot get group from different locale via context methods.
|
|
382
|
-
*/
|
|
383
|
-
const group = await context.cms.storageOperations.groups.get({
|
|
384
|
-
id: data.group,
|
|
385
|
-
tenant: original.tenant,
|
|
386
|
-
locale: locale.code
|
|
387
|
-
});
|
|
388
|
-
if (!group) {
|
|
389
|
-
throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
|
|
390
|
-
}
|
|
391
|
-
const identity = getIdentity();
|
|
392
|
-
const model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, original), {}, {
|
|
393
|
-
locale: locale.code,
|
|
394
|
-
group: {
|
|
395
|
-
id: group.id,
|
|
396
|
-
name: group.name
|
|
397
|
-
},
|
|
398
|
-
name: data.name,
|
|
399
|
-
modelId: data.modelId || "",
|
|
400
|
-
description: data.description || "",
|
|
401
|
-
createdBy: {
|
|
402
|
-
id: identity.id,
|
|
403
|
-
displayName: identity.displayName,
|
|
404
|
-
type: identity.type
|
|
405
|
-
},
|
|
406
|
-
createdOn: new Date().toISOString(),
|
|
407
|
-
savedOn: new Date().toISOString(),
|
|
408
|
-
lockedFields: [],
|
|
409
|
-
webinyVersion: context.WEBINY_VERSION
|
|
589
|
+
return context.benchmark.measure("headlessCms.crud.models.createModelFrom", async () => {
|
|
590
|
+
return createModelFrom(modelId, userInput);
|
|
410
591
|
});
|
|
411
|
-
try {
|
|
412
|
-
await onModelBeforeCreateFrom.publish({
|
|
413
|
-
input: data,
|
|
414
|
-
model,
|
|
415
|
-
original
|
|
416
|
-
});
|
|
417
|
-
const createdModel = await storageOperations.models.create({
|
|
418
|
-
model
|
|
419
|
-
});
|
|
420
|
-
loaders.listModels.clearAll();
|
|
421
|
-
await updateManager(context, model);
|
|
422
|
-
await onModelAfterCreateFrom.publish({
|
|
423
|
-
input: data,
|
|
424
|
-
original,
|
|
425
|
-
model: createdModel
|
|
426
|
-
});
|
|
427
|
-
return createdModel;
|
|
428
|
-
} catch (ex) {
|
|
429
|
-
await onModelCreateFromError.publish({
|
|
430
|
-
input: data,
|
|
431
|
-
original,
|
|
432
|
-
model,
|
|
433
|
-
error: ex
|
|
434
|
-
});
|
|
435
|
-
throw ex;
|
|
436
|
-
}
|
|
437
592
|
},
|
|
438
593
|
async updateModel(modelId, input) {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
// Get a model record; this will also perform ownership validation.
|
|
442
|
-
const original = await getModel(modelId);
|
|
443
|
-
const result = await (0, _validation.createModelUpdateValidation)().safeParseAsync(input);
|
|
444
|
-
if (!result.success) {
|
|
445
|
-
throw (0, _utils.createZodError)(result.error);
|
|
446
|
-
}
|
|
447
|
-
const data = result.data;
|
|
448
|
-
if (Object.keys(data).length === 0) {
|
|
449
|
-
/**
|
|
450
|
-
* We need to return the original if nothing is to be updated.
|
|
451
|
-
*/
|
|
452
|
-
return original;
|
|
453
|
-
}
|
|
454
|
-
let group = {
|
|
455
|
-
id: original.group.id,
|
|
456
|
-
name: original.group.name
|
|
457
|
-
};
|
|
458
|
-
if (data.group) {
|
|
459
|
-
context.security.disableAuthorization();
|
|
460
|
-
const groupData = await context.cms.getGroup(data.group);
|
|
461
|
-
context.security.enableAuthorization();
|
|
462
|
-
if (!groupData) {
|
|
463
|
-
throw new _handlerGraphql.NotFoundError(`There is no group "${data.group}".`);
|
|
464
|
-
}
|
|
465
|
-
group = {
|
|
466
|
-
id: groupData.id,
|
|
467
|
-
name: groupData.name
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
const model = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, original), data), {}, {
|
|
471
|
-
group,
|
|
472
|
-
description: data.description || original.description,
|
|
473
|
-
tenant: original.tenant || getTenant().id,
|
|
474
|
-
locale: original.locale || getLocale().code,
|
|
475
|
-
webinyVersion: context.WEBINY_VERSION,
|
|
476
|
-
savedOn: new Date().toISOString()
|
|
594
|
+
return context.benchmark.measure("headlessCms.crud.models.updateModel", async () => {
|
|
595
|
+
return updateModel(modelId, input);
|
|
477
596
|
});
|
|
478
|
-
model.tags = ensureTypeTag(model);
|
|
479
|
-
try {
|
|
480
|
-
await onModelBeforeUpdate.publish({
|
|
481
|
-
input: data,
|
|
482
|
-
original,
|
|
483
|
-
model
|
|
484
|
-
});
|
|
485
|
-
const resultModel = await storageOperations.models.update({
|
|
486
|
-
model
|
|
487
|
-
});
|
|
488
|
-
await updateManager(context, resultModel);
|
|
489
|
-
await onModelAfterUpdate.publish({
|
|
490
|
-
input: data,
|
|
491
|
-
original,
|
|
492
|
-
model: resultModel
|
|
493
|
-
});
|
|
494
|
-
return resultModel;
|
|
495
|
-
} catch (ex) {
|
|
496
|
-
await onModelUpdateError.publish({
|
|
497
|
-
input: data,
|
|
498
|
-
model,
|
|
499
|
-
original,
|
|
500
|
-
error: ex
|
|
501
|
-
});
|
|
502
|
-
throw ex;
|
|
503
|
-
}
|
|
504
597
|
},
|
|
505
598
|
async deleteModel(modelId) {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
await onModelBeforeDelete.publish({
|
|
510
|
-
model
|
|
511
|
-
});
|
|
512
|
-
try {
|
|
513
|
-
await storageOperations.models.delete({
|
|
514
|
-
model
|
|
515
|
-
});
|
|
516
|
-
} catch (ex) {
|
|
517
|
-
throw new _error.default(ex.message || "Could not delete the content model", ex.code || "CONTENT_MODEL_DELETE_ERROR", {
|
|
518
|
-
error: ex,
|
|
519
|
-
modelId: model.modelId
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
await onModelAfterDelete.publish({
|
|
523
|
-
model
|
|
524
|
-
});
|
|
525
|
-
managers.delete(model.modelId);
|
|
526
|
-
} catch (ex) {
|
|
527
|
-
await onModelDeleteError.publish({
|
|
528
|
-
model,
|
|
529
|
-
error: ex
|
|
530
|
-
});
|
|
531
|
-
throw ex;
|
|
532
|
-
}
|
|
599
|
+
return context.benchmark.measure("headlessCms.crud.models.deleteModel", async () => {
|
|
600
|
+
return deleteModel(modelId);
|
|
601
|
+
});
|
|
533
602
|
},
|
|
534
603
|
async initializeModel(modelId, data) {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
* Maybe introduce another permission for it?
|
|
538
|
-
*/
|
|
539
|
-
await checkModelPermissions("w");
|
|
540
|
-
const model = await getModel(modelId);
|
|
541
|
-
await onModelInitialize.publish({
|
|
542
|
-
model,
|
|
543
|
-
data
|
|
604
|
+
return context.benchmark.measure("headlessCms.crud.models.initializeModel", async () => {
|
|
605
|
+
return initializeModel(modelId, data);
|
|
544
606
|
});
|
|
545
|
-
return true;
|
|
546
607
|
},
|
|
547
608
|
getModelManager,
|
|
548
609
|
getEntryManager: async model => {
|