@webiny/api-headless-cms 0.0.0-unstable.9f53ea597d → 0.0.0-unstable.a4f3e4ea8b
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/crud/contentEntry.crud.js +12 -39
- package/crud/contentEntry.crud.js.map +1 -1
- package/features/contentEntry/ContentEntriesFeature.js +4 -0
- package/features/contentEntry/ContentEntriesFeature.js.map +1 -1
- package/features/contentEntry/CreateEntry/CreateEntryRepository.d.ts +4 -2
- package/features/contentEntry/CreateEntry/CreateEntryRepository.js +8 -3
- package/features/contentEntry/CreateEntry/CreateEntryRepository.js.map +1 -1
- package/features/contentEntry/CreateEntry/CreateEntryUseCase.js +1 -2
- package/features/contentEntry/CreateEntry/CreateEntryUseCase.js.map +1 -1
- package/features/contentEntry/CreateEntryRevisionFrom/CreateEntryRevisionFromRepository.d.ts +4 -2
- package/features/contentEntry/CreateEntryRevisionFrom/CreateEntryRevisionFromRepository.js +8 -3
- package/features/contentEntry/CreateEntryRevisionFrom/CreateEntryRevisionFromRepository.js.map +1 -1
- package/features/contentEntry/CreateEntryRevisionFrom/CreateEntryRevisionFromUseCase.js.map +1 -1
- package/features/contentEntry/DeleteEntry/DeleteEntryRepository.d.ts +4 -2
- package/features/contentEntry/DeleteEntry/DeleteEntryRepository.js +8 -3
- package/features/contentEntry/DeleteEntry/DeleteEntryRepository.js.map +1 -1
- package/features/contentEntry/DeleteEntry/MoveEntryToBinRepository.d.ts +3 -1
- package/features/contentEntry/DeleteEntry/MoveEntryToBinRepository.js +8 -3
- package/features/contentEntry/DeleteEntry/MoveEntryToBinRepository.js.map +1 -1
- package/features/contentEntry/DeleteEntryRevision/DeleteEntryRevisionRepository.d.ts +3 -1
- package/features/contentEntry/DeleteEntryRevision/DeleteEntryRevisionRepository.js +9 -3
- package/features/contentEntry/DeleteEntryRevision/DeleteEntryRevisionRepository.js.map +1 -1
- package/features/contentEntry/DeleteMultipleEntries/DeleteMultipleEntriesRepository.d.ts +4 -2
- package/features/contentEntry/DeleteMultipleEntries/DeleteMultipleEntriesRepository.js +7 -3
- package/features/contentEntry/DeleteMultipleEntries/DeleteMultipleEntriesRepository.js.map +1 -1
- package/features/contentEntry/GetEntriesByIds/GetEntriesByIdsRepository.d.ts +4 -4
- package/features/contentEntry/GetEntriesByIds/GetEntriesByIdsRepository.js +8 -11
- package/features/contentEntry/GetEntriesByIds/GetEntriesByIdsRepository.js.map +1 -1
- package/features/contentEntry/GetLatestEntriesByIds/GetLatestEntriesByIdsRepository.d.ts +4 -2
- package/features/contentEntry/GetLatestEntriesByIds/GetLatestEntriesByIdsRepository.js +7 -3
- package/features/contentEntry/GetLatestEntriesByIds/GetLatestEntriesByIdsRepository.js.map +1 -1
- package/features/contentEntry/GetLatestRevisionByEntryId/GetLatestRevisionByEntryIdRepository.d.ts +4 -2
- package/features/contentEntry/GetLatestRevisionByEntryId/GetLatestRevisionByEntryIdRepository.js +7 -3
- package/features/contentEntry/GetLatestRevisionByEntryId/GetLatestRevisionByEntryIdRepository.js.map +1 -1
- package/features/contentEntry/GetPreviousRevisionByEntryId/GetPreviousRevisionByEntryIdRepository.d.ts +4 -2
- package/features/contentEntry/GetPreviousRevisionByEntryId/GetPreviousRevisionByEntryIdRepository.js +7 -3
- package/features/contentEntry/GetPreviousRevisionByEntryId/GetPreviousRevisionByEntryIdRepository.js.map +1 -1
- package/features/contentEntry/GetPublishedEntriesByIds/GetPublishedEntriesByIdsRepository.d.ts +4 -2
- package/features/contentEntry/GetPublishedEntriesByIds/GetPublishedEntriesByIdsRepository.js +7 -3
- package/features/contentEntry/GetPublishedEntriesByIds/GetPublishedEntriesByIdsRepository.js.map +1 -1
- package/features/contentEntry/GetPublishedRevisionByEntryId/GetPublishedRevisionByEntryIdRepository.d.ts +4 -2
- package/features/contentEntry/GetPublishedRevisionByEntryId/GetPublishedRevisionByEntryIdRepository.js +7 -3
- package/features/contentEntry/GetPublishedRevisionByEntryId/GetPublishedRevisionByEntryIdRepository.js.map +1 -1
- package/features/contentEntry/GetRevisionById/GetRevisionByIdRepository.d.ts +4 -2
- package/features/contentEntry/GetRevisionById/GetRevisionByIdRepository.js +7 -3
- package/features/contentEntry/GetRevisionById/GetRevisionByIdRepository.js.map +1 -1
- package/features/contentEntry/GetRevisionsByEntryId/GetRevisionsByEntryIdRepository.d.ts +4 -2
- package/features/contentEntry/GetRevisionsByEntryId/GetRevisionsByEntryIdRepository.js +7 -3
- package/features/contentEntry/GetRevisionsByEntryId/GetRevisionsByEntryIdRepository.js.map +1 -1
- package/features/contentEntry/GetUniqueFieldValues/GetUniqueFieldValuesRepository.d.ts +4 -2
- package/features/contentEntry/GetUniqueFieldValues/GetUniqueFieldValuesRepository.js +7 -3
- package/features/contentEntry/GetUniqueFieldValues/GetUniqueFieldValuesRepository.js.map +1 -1
- package/features/contentEntry/ListEntries/ListEntriesRepository.d.ts +4 -2
- package/features/contentEntry/ListEntries/ListEntriesRepository.js +7 -3
- package/features/contentEntry/ListEntries/ListEntriesRepository.js.map +1 -1
- package/features/contentEntry/MoveEntry/MoveEntryRepository.d.ts +4 -2
- package/features/contentEntry/MoveEntry/MoveEntryRepository.js +7 -3
- package/features/contentEntry/MoveEntry/MoveEntryRepository.js.map +1 -1
- package/features/contentEntry/PublishEntry/PublishEntryRepository.d.ts +4 -2
- package/features/contentEntry/PublishEntry/PublishEntryRepository.js +8 -3
- package/features/contentEntry/PublishEntry/PublishEntryRepository.js.map +1 -1
- package/features/contentEntry/PublishEntry/PublishEntryUseCase.js.map +1 -1
- package/features/contentEntry/RepublishEntry/RepublishEntryRepository.d.ts +4 -2
- package/features/contentEntry/RepublishEntry/RepublishEntryRepository.js +8 -3
- package/features/contentEntry/RepublishEntry/RepublishEntryRepository.js.map +1 -1
- package/features/contentEntry/RestoreEntryFromBin/RestoreEntryFromBinRepository.d.ts +4 -2
- package/features/contentEntry/RestoreEntryFromBin/RestoreEntryFromBinRepository.js +8 -3
- package/features/contentEntry/RestoreEntryFromBin/RestoreEntryFromBinRepository.js.map +1 -1
- package/features/contentEntry/UnpublishEntry/UnpublishEntryRepository.d.ts +4 -2
- package/features/contentEntry/UnpublishEntry/UnpublishEntryRepository.js +8 -3
- package/features/contentEntry/UnpublishEntry/UnpublishEntryRepository.js.map +1 -1
- package/features/contentEntry/UpdateEntry/UpdateEntryRepository.d.ts +4 -2
- package/features/contentEntry/UpdateEntry/UpdateEntryRepository.js +8 -3
- package/features/contentEntry/UpdateEntry/UpdateEntryRepository.js.map +1 -1
- package/features/contentEntry/UpdateRevision/UpdateRevisionRepository.d.ts +14 -0
- package/features/contentEntry/UpdateRevision/UpdateRevisionRepository.js +34 -0
- package/features/contentEntry/UpdateRevision/UpdateRevisionRepository.js.map +1 -0
- package/features/contentEntry/UpdateRevision/abstractions.d.ts +10 -0
- package/features/contentEntry/UpdateRevision/abstractions.js +5 -0
- package/features/contentEntry/UpdateRevision/abstractions.js.map +1 -0
- package/features/contentEntry/UpdateRevision/feature.d.ts +4 -0
- package/features/contentEntry/UpdateRevision/feature.js +11 -0
- package/features/contentEntry/UpdateRevision/feature.js.map +1 -0
- package/features/contentEntry/UpdateRevision/index.d.ts +1 -0
- package/features/contentEntry/UpdateRevision/index.js +1 -0
- package/features/contentEntry/UpdateRevisionDescription/UpdateRevisionDescriptionUseCase.d.ts +2 -2
- package/features/contentEntry/UpdateRevisionDescription/UpdateRevisionDescriptionUseCase.js +2 -2
- package/features/contentEntry/UpdateRevisionDescription/UpdateRevisionDescriptionUseCase.js.map +1 -1
- package/features/contentEntry/ensureItemIds.d.ts +13 -0
- package/features/contentEntry/ensureItemIds.js +22 -0
- package/features/contentEntry/ensureItemIds.js.map +1 -0
- package/features/contentEntry/entryDataFactories/CreateEntryDataFactory/CreateEntryDataFactory.d.ts +3 -1
- package/features/contentEntry/entryDataFactories/CreateEntryDataFactory/CreateEntryDataFactory.js +8 -2
- package/features/contentEntry/entryDataFactories/CreateEntryDataFactory/CreateEntryDataFactory.js.map +1 -1
- package/features/contentEntry/entryDataFactories/CreateEntryRevisionFromDataFactory/CreateEntryRevisionFromDataFactory.d.ts +3 -1
- package/features/contentEntry/entryDataFactories/CreateEntryRevisionFromDataFactory/CreateEntryRevisionFromDataFactory.js +8 -2
- package/features/contentEntry/entryDataFactories/CreateEntryRevisionFromDataFactory/CreateEntryRevisionFromDataFactory.js.map +1 -1
- package/features/contentEntry/entryDataFactories/UpdateEntryDataFactory/UpdateEntryDataFactory.d.ts +3 -1
- package/features/contentEntry/entryDataFactories/UpdateEntryDataFactory/UpdateEntryDataFactory.js +8 -2
- package/features/contentEntry/entryDataFactories/UpdateEntryDataFactory/UpdateEntryDataFactory.js.map +1 -1
- package/features/contentModel/CreateModel/CreateModelRepository.d.ts +4 -2
- package/features/contentModel/CreateModel/CreateModelRepository.js +8 -4
- package/features/contentModel/CreateModel/CreateModelRepository.js.map +1 -1
- package/features/contentModel/CreateModel/CreateModelUseCase.js +2 -2
- package/features/contentModel/CreateModel/CreateModelUseCase.js.map +1 -1
- package/features/contentModel/CreateModel/abstractions.d.ts +1 -1
- package/features/contentModel/CreateModel/abstractions.js.map +1 -1
- package/features/contentModel/CreateModelFrom/CreateModelFromRepository.d.ts +4 -2
- package/features/contentModel/CreateModelFrom/CreateModelFromRepository.js +8 -4
- package/features/contentModel/CreateModelFrom/CreateModelFromRepository.js.map +1 -1
- package/features/contentModel/CreateModelFrom/CreateModelFromUseCase.js +2 -2
- package/features/contentModel/CreateModelFrom/CreateModelFromUseCase.js.map +1 -1
- package/features/contentModel/CreateModelFrom/abstractions.d.ts +1 -1
- package/features/contentModel/CreateModelFrom/abstractions.js.map +1 -1
- package/features/contentModel/DeleteModel/DeleteModelRepository.d.ts +4 -2
- package/features/contentModel/DeleteModel/DeleteModelRepository.js +7 -3
- package/features/contentModel/DeleteModel/DeleteModelRepository.js.map +1 -1
- package/features/contentModel/UpdateModel/UpdateModelRepository.d.ts +4 -2
- package/features/contentModel/UpdateModel/UpdateModelRepository.js +8 -4
- package/features/contentModel/UpdateModel/UpdateModelRepository.js.map +1 -1
- package/features/contentModel/UpdateModel/UpdateModelUseCase.js +2 -2
- package/features/contentModel/UpdateModel/UpdateModelUseCase.js.map +1 -1
- package/features/contentModel/UpdateModel/abstractions.d.ts +1 -1
- package/features/contentModel/UpdateModel/abstractions.js.map +1 -1
- package/features/contentModel/ValuesSelectionGenerator/ValuesSelectionGenerator.js +3 -2
- package/features/contentModel/ValuesSelectionGenerator/ValuesSelectionGenerator.js.map +1 -1
- package/features/contentModelGroup/CreateGroup/CreateGroupRepository.d.ts +4 -2
- package/features/contentModelGroup/CreateGroup/CreateGroupRepository.js +8 -4
- package/features/contentModelGroup/CreateGroup/CreateGroupRepository.js.map +1 -1
- package/features/contentModelGroup/CreateGroup/CreateGroupUseCase.d.ts +1 -3
- package/features/contentModelGroup/CreateGroup/CreateGroupUseCase.js +5 -7
- package/features/contentModelGroup/CreateGroup/CreateGroupUseCase.js.map +1 -1
- package/features/contentModelGroup/CreateGroup/abstractions.d.ts +1 -1
- package/features/contentModelGroup/CreateGroup/abstractions.js.map +1 -1
- package/features/contentModelGroup/DeleteGroup/DeleteGroupRepository.d.ts +4 -2
- package/features/contentModelGroup/DeleteGroup/DeleteGroupRepository.js +7 -3
- package/features/contentModelGroup/DeleteGroup/DeleteGroupRepository.js.map +1 -1
- package/features/contentModelGroup/UpdateGroup/UpdateGroupRepository.d.ts +4 -2
- package/features/contentModelGroup/UpdateGroup/UpdateGroupRepository.js +8 -4
- package/features/contentModelGroup/UpdateGroup/UpdateGroupRepository.js.map +1 -1
- package/features/contentModelGroup/UpdateGroup/UpdateGroupUseCase.js +2 -2
- package/features/contentModelGroup/UpdateGroup/UpdateGroupUseCase.js.map +1 -1
- package/features/contentModelGroup/UpdateGroup/abstractions.d.ts +1 -1
- package/features/contentModelGroup/UpdateGroup/abstractions.js.map +1 -1
- package/features/graphql/fields/base/DynamicZoneToGraphQL.js +7 -1
- package/features/graphql/fields/base/DynamicZoneToGraphQL.js.map +1 -1
- package/features/graphql/fields/base/ObjectToGraphQL.js +6 -3
- package/features/graphql/fields/base/ObjectToGraphQL.js.map +1 -1
- package/features/graphql/fields/base/RefToGraphQL.js +17 -7
- package/features/graphql/fields/base/RefToGraphQL.js.map +1 -1
- package/features/modelBuilder/abstractions.d.ts +1 -2
- package/features/modelBuilder/abstractions.js.map +1 -1
- package/features/runtimeTenant/RuntimeTenant.d.ts +13 -0
- package/features/runtimeTenant/RuntimeTenant.js +22 -0
- package/features/runtimeTenant/RuntimeTenant.js.map +1 -0
- package/features/runtimeTenant/abstractions.d.ts +11 -0
- package/features/runtimeTenant/abstractions.js +5 -0
- package/features/runtimeTenant/abstractions.js.map +1 -0
- package/features/runtimeTenant/index.d.ts +2 -0
- package/features/runtimeTenant/index.js +2 -0
- package/features/sortMapper/SortMapper.js +2 -5
- package/features/sortMapper/SortMapper.js.map +1 -1
- package/features/storage/fields/ObjectStorageTransform.js +27 -7
- package/features/storage/fields/ObjectStorageTransform.js.map +1 -1
- package/features/validation/validators/PatternValidator.js +1 -1
- package/features/validation/validators/PatternValidator.js.map +1 -1
- package/features/whereMapper/WhereMapper.js +7 -5
- package/features/whereMapper/WhereMapper.js.map +1 -1
- package/fieldConverters/CmsModelDynamicZoneFieldConverterPlugin.js +15 -5
- package/fieldConverters/CmsModelDynamicZoneFieldConverterPlugin.js.map +1 -1
- package/fieldConverters/CmsModelObjectFieldConverterPlugin.js +8 -2
- package/fieldConverters/CmsModelObjectFieldConverterPlugin.js.map +1 -1
- package/package.json +18 -18
- package/types/types.d.ts +4 -0
- package/types/types.js.map +1 -1
package/features/contentEntry/entryDataFactories/CreateEntryDataFactory/CreateEntryDataFactory.js
CHANGED
|
@@ -14,6 +14,8 @@ import { getIdentity } from "../../../../utils/identity.js";
|
|
|
14
14
|
import { NotAuthorizedError } from "../../../../utils/errors.js";
|
|
15
15
|
import { getSystem } from "../system.js";
|
|
16
16
|
import { getExpiresAt } from "../expiresAt.js";
|
|
17
|
+
import { ModelToAstConverter } from "../../../contentModel/ModelToAstConverter/abstractions.js";
|
|
18
|
+
import { ensureItemIds } from "../../ensureItemIds.js";
|
|
17
19
|
const convertDefaultValue = (field, value)=>{
|
|
18
20
|
switch(field.type){
|
|
19
21
|
case "boolean":
|
|
@@ -64,14 +66,17 @@ const createEntryId = (input)=>{
|
|
|
64
66
|
};
|
|
65
67
|
};
|
|
66
68
|
class CreateEntryDataFactoryImpl {
|
|
67
|
-
constructor(cmsContext, identityContext, tenantContext, accessControl){
|
|
69
|
+
constructor(cmsContext, identityContext, tenantContext, accessControl, modelToAstConverter){
|
|
68
70
|
this.cmsContext = cmsContext;
|
|
69
71
|
this.identityContext = identityContext;
|
|
70
72
|
this.tenantContext = tenantContext;
|
|
71
73
|
this.accessControl = accessControl;
|
|
74
|
+
this.modelToAstConverter = modelToAstConverter;
|
|
72
75
|
}
|
|
73
76
|
async create(model, rawInput, options) {
|
|
74
77
|
const initialValues = cleanInputValues(model, rawInput.values || {});
|
|
78
|
+
const modelAst = this.modelToAstConverter.toAst(model);
|
|
79
|
+
await ensureItemIds(modelAst, initialValues);
|
|
75
80
|
await validateModelEntryDataOrThrow({
|
|
76
81
|
context: this.cmsContext,
|
|
77
82
|
model,
|
|
@@ -208,7 +213,8 @@ const CreateEntryDataFactory_CreateEntryDataFactory = createImplementation({
|
|
|
208
213
|
CmsContext,
|
|
209
214
|
IdentityContext,
|
|
210
215
|
TenantContext,
|
|
211
|
-
AccessControl
|
|
216
|
+
AccessControl,
|
|
217
|
+
ModelToAstConverter
|
|
212
218
|
]
|
|
213
219
|
});
|
|
214
220
|
export { CreateEntryDataFactory_CreateEntryDataFactory as CreateEntryDataFactory };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/contentEntry/entryDataFactories/CreateEntryDataFactory/CreateEntryDataFactory.js","sources":["../../../../../src/features/contentEntry/entryDataFactories/CreateEntryDataFactory/CreateEntryDataFactory.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport {\n CreateEntryDataFactory as FactoryAbstraction,\n type ICreateEntryDataFactory,\n type ICreateEntryDataResponse\n} from \"./abstractions.js\";\nimport { AccessControl, CmsContext } from \"~/features/shared/abstractions.js\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport type {\n CmsEntry,\n CmsEntryValues,\n CmsModel,\n CmsModelField,\n CreateCmsEntryInput,\n CreateCmsEntryOptionsInput\n} from \"~/types/index.js\";\nimport { getDate } from \"~/utils/date.js\";\nimport { ROOT_FOLDER } from \"~/constants.js\";\nimport WebinyError from \"@webiny/error\";\nimport { validateModelEntryDataOrThrow } from \"~/crud/contentEntry/entryDataValidation.js\";\nimport { referenceFieldsMapping } from \"~/crud/contentEntry/referenceFieldsMapping.js\";\nimport { createIdentifier, mdbid } from \"@webiny/utils\";\nimport { STATUS_DRAFT, STATUS_PUBLISHED, STATUS_UNPUBLISHED } from \"../statuses.js\";\nimport { getIdentity } from \"~/utils/identity.js\";\nimport { NotAuthorizedError } from \"~/utils/errors.js\";\nimport { getSystem } from \"../system.js\";\nimport { getExpiresAt } from \"../expiresAt.js\";\n\ntype DefaultValue = boolean | number | string | null;\n\nconst convertDefaultValue = (field: CmsModelField, value: DefaultValue): DefaultValue => {\n switch (field.type) {\n case \"boolean\":\n return Boolean(value);\n case \"number\":\n return Number(value);\n default:\n return value;\n }\n};\n\nconst getDefaultValue = (field: CmsModelField): (DefaultValue | DefaultValue[]) | undefined => {\n const { settings, list } = field;\n if (settings && settings.defaultValue !== undefined) {\n return convertDefaultValue(field, settings.defaultValue);\n }\n const { predefinedValues } = field;\n if (\n !predefinedValues ||\n !predefinedValues.enabled ||\n Array.isArray(predefinedValues.values) === false\n ) {\n return undefined;\n }\n if (!list) {\n const selectedValue = predefinedValues.values.find(value => {\n return !!value.selected;\n });\n if (selectedValue) {\n return convertDefaultValue(field, selectedValue.value);\n }\n return undefined;\n }\n return predefinedValues.values\n .filter(({ selected }) => !!selected)\n .map(({ value }) => {\n return convertDefaultValue(field, value);\n });\n};\n\nconst cleanInputValues = <TValues extends CmsEntryValues = CmsEntryValues>(\n model: CmsModel,\n input: TValues\n) => {\n return model.fields.reduce<TValues>((acc, field) => {\n if (!field.fieldId) {\n throw new WebinyError(\"Field does not have an fieldId.\", \"MISSING_FIELD_ID\", {\n field\n });\n }\n const key = field.fieldId as keyof TValues;\n const value = input[key] as TValues[keyof TValues];\n acc[key] = value === undefined ? (getDefaultValue(field) as TValues[keyof TValues]) : value;\n return acc;\n }, {} as TValues);\n};\n\nconst createEntryId = (input: CreateCmsEntryInput) => {\n let entryId = mdbid();\n if (input.id) {\n if (input.id.match(/^([a-zA-Z0-9])([a-zA-Z0-9-]+)([a-zA-Z0-9])$/) === null) {\n throw new WebinyError(\n \"The provided ID is not valid. It must be a string which can be A-Z, a-z, 0-9, - and it cannot start or end with a -.\",\n \"INVALID_ID\",\n {\n id: input.id\n }\n );\n }\n entryId = input.id;\n }\n const version = 1;\n return {\n entryId,\n version,\n id: createIdentifier({\n id: entryId,\n version\n })\n };\n};\n\nclass CreateEntryDataFactoryImpl implements ICreateEntryDataFactory {\n public constructor(\n private readonly cmsContext: CmsContext.Interface,\n private readonly identityContext: IdentityContext.Interface,\n private readonly tenantContext: TenantContext.Interface,\n private readonly accessControl: AccessControl.Interface\n ) {}\n\n public async create<TValues extends CmsEntryValues = CmsEntryValues>(\n model: CmsModel,\n rawInput: CreateCmsEntryInput<TValues>,\n options?: CreateCmsEntryOptionsInput\n ): Promise<ICreateEntryDataResponse<TValues>> {\n const initialValues = cleanInputValues<TValues>(model, rawInput.values || ({} as TValues));\n\n await validateModelEntryDataOrThrow({\n context: this.cmsContext,\n model,\n values: initialValues,\n skipValidation: options?.skipValidation\n });\n\n const values = await referenceFieldsMapping<TValues>({\n context: this.cmsContext,\n model,\n values: initialValues,\n validateEntries: true\n });\n\n const { id, entryId, version } = createEntryId(rawInput);\n\n const currentIdentity = this.identityContext.getIdentity();\n const currentDateTime = new Date();\n\n const status = rawInput.status || STATUS_DRAFT;\n if (status !== STATUS_DRAFT) {\n if (status === STATUS_PUBLISHED) {\n const canPublish = await this.accessControl.canAccessEntry({ model, pw: \"p\" });\n if (!canPublish) {\n throw new NotAuthorizedError(\n `Not allowed to access \"${model.modelId}\" entries.`\n );\n }\n } else if (status === STATUS_UNPUBLISHED) {\n const canUnpublish = await this.accessControl.canAccessEntry({ model, pw: \"u\" });\n if (!canUnpublish) {\n throw new NotAuthorizedError(\n `Not allowed to access \"${model.modelId}\" entries.`\n );\n }\n }\n }\n\n const locked = status !== STATUS_DRAFT;\n\n let revisionLevelPublishingMetaFields: Pick<\n CmsEntry,\n | \"revisionFirstPublishedOn\"\n | \"revisionLastPublishedOn\"\n | \"revisionFirstPublishedBy\"\n | \"revisionLastPublishedBy\"\n > = {\n revisionFirstPublishedOn: null,\n revisionLastPublishedOn: null,\n revisionFirstPublishedBy: null,\n revisionLastPublishedBy: null\n };\n\n let entryLevelPublishingMetaFields: Pick<\n CmsEntry,\n \"firstPublishedOn\" | \"lastPublishedOn\" | \"firstPublishedBy\" | \"lastPublishedBy\"\n > = {\n firstPublishedOn: null,\n lastPublishedOn: null,\n firstPublishedBy: null,\n lastPublishedBy: null\n };\n\n if (status === STATUS_PUBLISHED) {\n revisionLevelPublishingMetaFields = {\n revisionFirstPublishedOn: getDate(\n rawInput.revisionFirstPublishedOn,\n currentDateTime\n ),\n revisionLastPublishedOn: getDate(rawInput.revisionLastPublishedOn, currentDateTime),\n revisionFirstPublishedBy: getIdentity(\n rawInput.revisionFirstPublishedBy,\n currentIdentity\n ),\n revisionLastPublishedBy: getIdentity(\n rawInput.revisionLastPublishedBy,\n currentIdentity\n )\n };\n\n entryLevelPublishingMetaFields = {\n firstPublishedOn: getDate(rawInput.firstPublishedOn, currentDateTime),\n lastPublishedOn: getDate(rawInput.lastPublishedOn, currentDateTime),\n firstPublishedBy: getIdentity(rawInput.firstPublishedBy, currentIdentity),\n lastPublishedBy: getIdentity(rawInput.lastPublishedBy, currentIdentity)\n };\n }\n\n const entry: CmsEntry<TValues> = {\n tenant: this.tenantContext.getTenant().id,\n entryId,\n id,\n modelId: model.modelId,\n createdOn: getDate(rawInput.createdOn, currentDateTime),\n modifiedOn: getDate(rawInput.modifiedOn, null),\n savedOn: getDate(rawInput.savedOn, currentDateTime),\n deletedOn: getDate(rawInput.deletedOn, null),\n restoredOn: getDate(rawInput.restoredOn, null),\n createdBy: getIdentity(rawInput.createdBy, currentIdentity)!,\n modifiedBy: getIdentity(rawInput.modifiedBy, null),\n savedBy: getIdentity(rawInput.savedBy, currentIdentity)!,\n deletedBy: getIdentity(rawInput.deletedBy, null),\n restoredBy: getIdentity(rawInput.restoredBy, null),\n ...entryLevelPublishingMetaFields,\n revisionCreatedOn: getDate(rawInput.revisionCreatedOn, currentDateTime),\n revisionModifiedOn: getDate(rawInput.revisionModifiedOn, null),\n revisionSavedOn: getDate(rawInput.revisionSavedOn, currentDateTime),\n revisionDeletedOn: getDate(rawInput.revisionDeletedOn, null),\n revisionRestoredOn: getDate(rawInput.revisionRestoredOn, null),\n revisionCreatedBy: getIdentity(rawInput.revisionCreatedBy, currentIdentity)!,\n revisionModifiedBy: getIdentity(rawInput.revisionModifiedBy, null),\n revisionSavedBy: getIdentity(rawInput.revisionSavedBy, currentIdentity)!,\n revisionDeletedBy: getIdentity(rawInput.revisionDeletedBy, null),\n revisionRestoredBy: getIdentity(rawInput.revisionRestoredBy, null),\n ...revisionLevelPublishingMetaFields,\n version,\n status,\n locked,\n values,\n location: {\n folderId:\n rawInput.location?.folderId || rawInput.wbyAco_location?.folderId || ROOT_FOLDER\n },\n system: getSystem({\n input: rawInput\n }),\n live:\n status === STATUS_PUBLISHED\n ? {\n version\n }\n : null,\n revisionDescription: \"\",\n expiresAt: getExpiresAt({ expiresAt: rawInput.expiresAt })\n };\n\n if (status !== STATUS_DRAFT) {\n if (status === STATUS_PUBLISHED) {\n const canPublish = await this.accessControl.canAccessEntry({\n model,\n entry,\n pw: \"p\"\n });\n if (!canPublish) {\n throw new NotAuthorizedError(`Not allowed to access entry \"${entry.entryId}\".`);\n }\n } else if (status === STATUS_UNPUBLISHED) {\n const canUnpublish = await this.accessControl.canAccessEntry({\n model,\n entry,\n pw: \"u\"\n });\n if (!canUnpublish) {\n throw new NotAuthorizedError(`Not allowed to access entry \"${entry.entryId}\".`);\n }\n }\n }\n\n return {\n entry,\n input: {\n ...rawInput,\n values: structuredClone(values)\n }\n };\n }\n}\n\nexport const CreateEntryDataFactory = createImplementation({\n abstraction: FactoryAbstraction,\n implementation: CreateEntryDataFactoryImpl,\n dependencies: [CmsContext, IdentityContext, TenantContext, AccessControl]\n});\n"],"names":["convertDefaultValue","field","value","Boolean","Number","getDefaultValue","settings","list","undefined","predefinedValues","Array","selectedValue","selected","cleanInputValues","model","input","acc","WebinyError","key","createEntryId","entryId","mdbid","version","createIdentifier","CreateEntryDataFactoryImpl","cmsContext","identityContext","tenantContext","accessControl","rawInput","options","initialValues","validateModelEntryDataOrThrow","values","referenceFieldsMapping","id","currentIdentity","currentDateTime","Date","status","STATUS_DRAFT","STATUS_PUBLISHED","canPublish","NotAuthorizedError","STATUS_UNPUBLISHED","canUnpublish","locked","revisionLevelPublishingMetaFields","entryLevelPublishingMetaFields","getDate","getIdentity","entry","ROOT_FOLDER","getSystem","getExpiresAt","structuredClone","CreateEntryDataFactory","createImplementation","FactoryAbstraction","CmsContext","IdentityContext","TenantContext","AccessControl"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"features/contentEntry/entryDataFactories/CreateEntryDataFactory/CreateEntryDataFactory.js","sources":["../../../../../src/features/contentEntry/entryDataFactories/CreateEntryDataFactory/CreateEntryDataFactory.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport {\n CreateEntryDataFactory as FactoryAbstraction,\n type ICreateEntryDataFactory,\n type ICreateEntryDataResponse\n} from \"./abstractions.js\";\nimport { AccessControl, CmsContext } from \"~/features/shared/abstractions.js\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport type {\n CmsEntry,\n CmsEntryValues,\n CmsModel,\n CmsModelField,\n CreateCmsEntryInput,\n CreateCmsEntryOptionsInput\n} from \"~/types/index.js\";\nimport { getDate } from \"~/utils/date.js\";\nimport { ROOT_FOLDER } from \"~/constants.js\";\nimport WebinyError from \"@webiny/error\";\nimport { validateModelEntryDataOrThrow } from \"~/crud/contentEntry/entryDataValidation.js\";\nimport { referenceFieldsMapping } from \"~/crud/contentEntry/referenceFieldsMapping.js\";\nimport { createIdentifier, mdbid } from \"@webiny/utils\";\nimport { STATUS_DRAFT, STATUS_PUBLISHED, STATUS_UNPUBLISHED } from \"../statuses.js\";\nimport { getIdentity } from \"~/utils/identity.js\";\nimport { NotAuthorizedError } from \"~/utils/errors.js\";\nimport { getSystem } from \"../system.js\";\nimport { getExpiresAt } from \"../expiresAt.js\";\nimport { ModelToAstConverter } from \"~/features/contentModel/ModelToAstConverter/abstractions.js\";\nimport { ensureItemIds } from \"../../ensureItemIds.js\";\n\ntype DefaultValue = boolean | number | string | null;\n\nconst convertDefaultValue = (field: CmsModelField, value: DefaultValue): DefaultValue => {\n switch (field.type) {\n case \"boolean\":\n return Boolean(value);\n case \"number\":\n return Number(value);\n default:\n return value;\n }\n};\n\nconst getDefaultValue = (field: CmsModelField): (DefaultValue | DefaultValue[]) | undefined => {\n const { settings, list } = field;\n if (settings && settings.defaultValue !== undefined) {\n return convertDefaultValue(field, settings.defaultValue);\n }\n const { predefinedValues } = field;\n if (\n !predefinedValues ||\n !predefinedValues.enabled ||\n Array.isArray(predefinedValues.values) === false\n ) {\n return undefined;\n }\n if (!list) {\n const selectedValue = predefinedValues.values.find(value => {\n return !!value.selected;\n });\n if (selectedValue) {\n return convertDefaultValue(field, selectedValue.value);\n }\n return undefined;\n }\n return predefinedValues.values\n .filter(({ selected }) => !!selected)\n .map(({ value }) => {\n return convertDefaultValue(field, value);\n });\n};\n\nconst cleanInputValues = <TValues extends CmsEntryValues = CmsEntryValues>(\n model: CmsModel,\n input: TValues\n) => {\n return model.fields.reduce<TValues>((acc, field) => {\n if (!field.fieldId) {\n throw new WebinyError(\"Field does not have an fieldId.\", \"MISSING_FIELD_ID\", {\n field\n });\n }\n const key = field.fieldId as keyof TValues;\n const value = input[key] as TValues[keyof TValues];\n acc[key] = value === undefined ? (getDefaultValue(field) as TValues[keyof TValues]) : value;\n return acc;\n }, {} as TValues);\n};\n\nconst createEntryId = (input: CreateCmsEntryInput) => {\n let entryId = mdbid();\n if (input.id) {\n if (input.id.match(/^([a-zA-Z0-9])([a-zA-Z0-9-]+)([a-zA-Z0-9])$/) === null) {\n throw new WebinyError(\n \"The provided ID is not valid. It must be a string which can be A-Z, a-z, 0-9, - and it cannot start or end with a -.\",\n \"INVALID_ID\",\n {\n id: input.id\n }\n );\n }\n entryId = input.id;\n }\n const version = 1;\n return {\n entryId,\n version,\n id: createIdentifier({\n id: entryId,\n version\n })\n };\n};\n\nclass CreateEntryDataFactoryImpl implements ICreateEntryDataFactory {\n public constructor(\n private readonly cmsContext: CmsContext.Interface,\n private readonly identityContext: IdentityContext.Interface,\n private readonly tenantContext: TenantContext.Interface,\n private readonly accessControl: AccessControl.Interface,\n private readonly modelToAstConverter: ModelToAstConverter.Interface\n ) {}\n\n public async create<TValues extends CmsEntryValues = CmsEntryValues>(\n model: CmsModel,\n rawInput: CreateCmsEntryInput<TValues>,\n options?: CreateCmsEntryOptionsInput\n ): Promise<ICreateEntryDataResponse<TValues>> {\n const initialValues = cleanInputValues<TValues>(model, rawInput.values || ({} as TValues));\n\n const modelAst = this.modelToAstConverter.toAst(model);\n await ensureItemIds(modelAst, initialValues);\n\n await validateModelEntryDataOrThrow({\n context: this.cmsContext,\n model,\n values: initialValues,\n skipValidation: options?.skipValidation\n });\n\n const values = await referenceFieldsMapping<TValues>({\n context: this.cmsContext,\n model,\n values: initialValues,\n validateEntries: true\n });\n\n const { id, entryId, version } = createEntryId(rawInput);\n\n const currentIdentity = this.identityContext.getIdentity();\n const currentDateTime = new Date();\n\n const status = rawInput.status || STATUS_DRAFT;\n if (status !== STATUS_DRAFT) {\n if (status === STATUS_PUBLISHED) {\n const canPublish = await this.accessControl.canAccessEntry({ model, pw: \"p\" });\n if (!canPublish) {\n throw new NotAuthorizedError(\n `Not allowed to access \"${model.modelId}\" entries.`\n );\n }\n } else if (status === STATUS_UNPUBLISHED) {\n const canUnpublish = await this.accessControl.canAccessEntry({ model, pw: \"u\" });\n if (!canUnpublish) {\n throw new NotAuthorizedError(\n `Not allowed to access \"${model.modelId}\" entries.`\n );\n }\n }\n }\n\n const locked = status !== STATUS_DRAFT;\n\n let revisionLevelPublishingMetaFields: Pick<\n CmsEntry,\n | \"revisionFirstPublishedOn\"\n | \"revisionLastPublishedOn\"\n | \"revisionFirstPublishedBy\"\n | \"revisionLastPublishedBy\"\n > = {\n revisionFirstPublishedOn: null,\n revisionLastPublishedOn: null,\n revisionFirstPublishedBy: null,\n revisionLastPublishedBy: null\n };\n\n let entryLevelPublishingMetaFields: Pick<\n CmsEntry,\n \"firstPublishedOn\" | \"lastPublishedOn\" | \"firstPublishedBy\" | \"lastPublishedBy\"\n > = {\n firstPublishedOn: null,\n lastPublishedOn: null,\n firstPublishedBy: null,\n lastPublishedBy: null\n };\n\n if (status === STATUS_PUBLISHED) {\n revisionLevelPublishingMetaFields = {\n revisionFirstPublishedOn: getDate(\n rawInput.revisionFirstPublishedOn,\n currentDateTime\n ),\n revisionLastPublishedOn: getDate(rawInput.revisionLastPublishedOn, currentDateTime),\n revisionFirstPublishedBy: getIdentity(\n rawInput.revisionFirstPublishedBy,\n currentIdentity\n ),\n revisionLastPublishedBy: getIdentity(\n rawInput.revisionLastPublishedBy,\n currentIdentity\n )\n };\n\n entryLevelPublishingMetaFields = {\n firstPublishedOn: getDate(rawInput.firstPublishedOn, currentDateTime),\n lastPublishedOn: getDate(rawInput.lastPublishedOn, currentDateTime),\n firstPublishedBy: getIdentity(rawInput.firstPublishedBy, currentIdentity),\n lastPublishedBy: getIdentity(rawInput.lastPublishedBy, currentIdentity)\n };\n }\n\n const entry: CmsEntry<TValues> = {\n tenant: this.tenantContext.getTenant().id,\n entryId,\n id,\n modelId: model.modelId,\n createdOn: getDate(rawInput.createdOn, currentDateTime),\n modifiedOn: getDate(rawInput.modifiedOn, null),\n savedOn: getDate(rawInput.savedOn, currentDateTime),\n deletedOn: getDate(rawInput.deletedOn, null),\n restoredOn: getDate(rawInput.restoredOn, null),\n createdBy: getIdentity(rawInput.createdBy, currentIdentity)!,\n modifiedBy: getIdentity(rawInput.modifiedBy, null),\n savedBy: getIdentity(rawInput.savedBy, currentIdentity)!,\n deletedBy: getIdentity(rawInput.deletedBy, null),\n restoredBy: getIdentity(rawInput.restoredBy, null),\n ...entryLevelPublishingMetaFields,\n revisionCreatedOn: getDate(rawInput.revisionCreatedOn, currentDateTime),\n revisionModifiedOn: getDate(rawInput.revisionModifiedOn, null),\n revisionSavedOn: getDate(rawInput.revisionSavedOn, currentDateTime),\n revisionDeletedOn: getDate(rawInput.revisionDeletedOn, null),\n revisionRestoredOn: getDate(rawInput.revisionRestoredOn, null),\n revisionCreatedBy: getIdentity(rawInput.revisionCreatedBy, currentIdentity)!,\n revisionModifiedBy: getIdentity(rawInput.revisionModifiedBy, null),\n revisionSavedBy: getIdentity(rawInput.revisionSavedBy, currentIdentity)!,\n revisionDeletedBy: getIdentity(rawInput.revisionDeletedBy, null),\n revisionRestoredBy: getIdentity(rawInput.revisionRestoredBy, null),\n ...revisionLevelPublishingMetaFields,\n version,\n status,\n locked,\n values,\n location: {\n folderId:\n rawInput.location?.folderId || rawInput.wbyAco_location?.folderId || ROOT_FOLDER\n },\n system: getSystem({\n input: rawInput\n }),\n live:\n status === STATUS_PUBLISHED\n ? {\n version\n }\n : null,\n revisionDescription: \"\",\n expiresAt: getExpiresAt({ expiresAt: rawInput.expiresAt })\n };\n\n if (status !== STATUS_DRAFT) {\n if (status === STATUS_PUBLISHED) {\n const canPublish = await this.accessControl.canAccessEntry({\n model,\n entry,\n pw: \"p\"\n });\n if (!canPublish) {\n throw new NotAuthorizedError(`Not allowed to access entry \"${entry.entryId}\".`);\n }\n } else if (status === STATUS_UNPUBLISHED) {\n const canUnpublish = await this.accessControl.canAccessEntry({\n model,\n entry,\n pw: \"u\"\n });\n if (!canUnpublish) {\n throw new NotAuthorizedError(`Not allowed to access entry \"${entry.entryId}\".`);\n }\n }\n }\n\n return {\n entry,\n input: {\n ...rawInput,\n values: structuredClone(values)\n }\n };\n }\n}\n\nexport const CreateEntryDataFactory = createImplementation({\n abstraction: FactoryAbstraction,\n implementation: CreateEntryDataFactoryImpl,\n dependencies: [CmsContext, IdentityContext, TenantContext, AccessControl, ModelToAstConverter]\n});\n"],"names":["convertDefaultValue","field","value","Boolean","Number","getDefaultValue","settings","list","undefined","predefinedValues","Array","selectedValue","selected","cleanInputValues","model","input","acc","WebinyError","key","createEntryId","entryId","mdbid","version","createIdentifier","CreateEntryDataFactoryImpl","cmsContext","identityContext","tenantContext","accessControl","modelToAstConverter","rawInput","options","initialValues","modelAst","ensureItemIds","validateModelEntryDataOrThrow","values","referenceFieldsMapping","id","currentIdentity","currentDateTime","Date","status","STATUS_DRAFT","STATUS_PUBLISHED","canPublish","NotAuthorizedError","STATUS_UNPUBLISHED","canUnpublish","locked","revisionLevelPublishingMetaFields","entryLevelPublishingMetaFields","getDate","getIdentity","entry","ROOT_FOLDER","getSystem","getExpiresAt","structuredClone","CreateEntryDataFactory","createImplementation","FactoryAbstraction","CmsContext","IdentityContext","TenantContext","AccessControl","ModelToAstConverter"],"mappings":"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"}
|
|
@@ -2,11 +2,13 @@ import { type ICreateEntryRevisionFromDataFactory, type ICreateEntryRevisionFrom
|
|
|
2
2
|
import { AccessControl, CmsContext } from "../../../../features/shared/abstractions.js";
|
|
3
3
|
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
4
4
|
import type { CmsEntry, CmsEntryValues, CmsModel, CreateCmsEntryInput, CreateCmsEntryOptionsInput } from "../../../../types/index.js";
|
|
5
|
+
import { ModelToAstConverter } from "../../../../features/contentModel/ModelToAstConverter/abstractions.js";
|
|
5
6
|
declare class CreateEntryRevisionFromDataFactoryImpl implements ICreateEntryRevisionFromDataFactory {
|
|
6
7
|
private readonly cmsContext;
|
|
7
8
|
private readonly identityContext;
|
|
8
9
|
private readonly accessControl;
|
|
9
|
-
|
|
10
|
+
private readonly modelToAstConverter;
|
|
11
|
+
constructor(cmsContext: CmsContext.Interface, identityContext: IdentityContext.Interface, accessControl: AccessControl.Interface, modelToAstConverter: ModelToAstConverter.Interface);
|
|
10
12
|
create<TValues extends CmsEntryValues = CmsEntryValues>(sourceId: string, model: CmsModel, rawInput: CreateCmsEntryInput<TValues>, originalEntry: CmsEntry<TValues>, latestStorageEntry: CmsEntry<TValues>, options?: CreateCmsEntryOptionsInput): Promise<ICreateEntryRevisionFromDataResponse<TValues>>;
|
|
11
13
|
}
|
|
12
14
|
export declare const CreateEntryRevisionFromDataFactory: import("@webiny/di").Implementation<typeof CreateEntryRevisionFromDataFactoryImpl>;
|
|
@@ -12,6 +12,8 @@ import error from "@webiny/error";
|
|
|
12
12
|
import { STATUS_DRAFT, STATUS_PUBLISHED, STATUS_UNPUBLISHED } from "../statuses.js";
|
|
13
13
|
import { NotAuthorizedError } from "../../../../utils/errors.js";
|
|
14
14
|
import { getSystem } from "../system.js";
|
|
15
|
+
import { ModelToAstConverter } from "../../../contentModel/ModelToAstConverter/abstractions.js";
|
|
16
|
+
import { ensureItemIds } from "../../ensureItemIds.js";
|
|
15
17
|
const increaseEntryIdVersion = (id)=>{
|
|
16
18
|
const { id: entryId, version } = parseIdentifier(id);
|
|
17
19
|
if (!version) throw new error("Cannot increase version on the ID without the version part.", "WRONG_ID", {
|
|
@@ -27,16 +29,19 @@ const increaseEntryIdVersion = (id)=>{
|
|
|
27
29
|
};
|
|
28
30
|
};
|
|
29
31
|
class CreateEntryRevisionFromDataFactoryImpl {
|
|
30
|
-
constructor(cmsContext, identityContext, accessControl){
|
|
32
|
+
constructor(cmsContext, identityContext, accessControl, modelToAstConverter){
|
|
31
33
|
this.cmsContext = cmsContext;
|
|
32
34
|
this.identityContext = identityContext;
|
|
33
35
|
this.accessControl = accessControl;
|
|
36
|
+
this.modelToAstConverter = modelToAstConverter;
|
|
34
37
|
}
|
|
35
38
|
async create(sourceId, model, rawInput, originalEntry, latestStorageEntry, options) {
|
|
36
39
|
const initialValues = {
|
|
37
40
|
...originalEntry.values,
|
|
38
41
|
...mapAndCleanUpdatedInputData(model, rawInput.values)
|
|
39
42
|
};
|
|
43
|
+
const modelAst = this.modelToAstConverter.toAst(model);
|
|
44
|
+
await ensureItemIds(modelAst, initialValues);
|
|
40
45
|
await validateModelEntryDataOrThrow({
|
|
41
46
|
context: this.cmsContext,
|
|
42
47
|
model,
|
|
@@ -141,7 +146,8 @@ const CreateEntryRevisionFromDataFactory_CreateEntryRevisionFromDataFactory = cr
|
|
|
141
146
|
dependencies: [
|
|
142
147
|
CmsContext,
|
|
143
148
|
IdentityContext,
|
|
144
|
-
AccessControl
|
|
149
|
+
AccessControl,
|
|
150
|
+
ModelToAstConverter
|
|
145
151
|
]
|
|
146
152
|
});
|
|
147
153
|
export { CreateEntryRevisionFromDataFactory_CreateEntryRevisionFromDataFactory as CreateEntryRevisionFromDataFactory };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/contentEntry/entryDataFactories/CreateEntryRevisionFromDataFactory/CreateEntryRevisionFromDataFactory.js","sources":["../../../../../src/features/contentEntry/entryDataFactories/CreateEntryRevisionFromDataFactory/CreateEntryRevisionFromDataFactory.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport {\n CreateEntryRevisionFromDataFactory as FactoryAbstraction,\n type ICreateEntryRevisionFromDataFactory,\n type ICreateEntryRevisionFromDataResponse\n} from \"./abstractions.js\";\nimport { AccessControl, CmsContext } from \"~/features/shared/abstractions.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport type {\n CmsEntry,\n CmsEntryValues,\n CmsModel,\n CreateCmsEntryInput,\n CreateCmsEntryOptionsInput\n} from \"~/types/index.js\";\nimport { getDate } from \"~/utils/date.js\";\nimport { getIdentity } from \"~/utils/identity.js\";\nimport { mapAndCleanUpdatedInputData } from \"../mapAndCleanUpdatedInputData.js\";\nimport { validateModelEntryDataOrThrow } from \"~/crud/contentEntry/entryDataValidation.js\";\nimport { referenceFieldsMapping } from \"~/crud/contentEntry/referenceFieldsMapping.js\";\nimport { createIdentifier, parseIdentifier } from \"@webiny/utils\";\nimport WebinyError from \"@webiny/error\";\nimport { STATUS_DRAFT, STATUS_PUBLISHED, STATUS_UNPUBLISHED } from \"../statuses.js\";\nimport { NotAuthorizedError } from \"~/utils/errors.js\";\nimport { getSystem } from \"../system.js\";\n\nconst increaseEntryIdVersion = (id: string) => {\n const { id: entryId, version } = parseIdentifier(id);\n if (!version) {\n throw new WebinyError(\n \"Cannot increase version on the ID without the version part.\",\n \"WRONG_ID\",\n {\n id\n }\n );\n }\n return {\n entryId,\n version: version + 1,\n id: createIdentifier({\n id: entryId,\n version: version + 1\n })\n };\n};\n\nclass CreateEntryRevisionFromDataFactoryImpl implements ICreateEntryRevisionFromDataFactory {\n public constructor(\n private readonly cmsContext: CmsContext.Interface,\n private readonly identityContext: IdentityContext.Interface,\n private readonly accessControl: AccessControl.Interface\n ) {}\n\n public async create<TValues extends CmsEntryValues = CmsEntryValues>(\n sourceId: string,\n model: CmsModel,\n rawInput: CreateCmsEntryInput<TValues>,\n originalEntry: CmsEntry<TValues>,\n latestStorageEntry: CmsEntry<TValues>,\n options?: CreateCmsEntryOptionsInput\n ): Promise<ICreateEntryRevisionFromDataResponse<TValues>> {\n const initialValues = {\n ...originalEntry.values,\n ...mapAndCleanUpdatedInputData<TValues>(model, rawInput.values)\n };\n\n await validateModelEntryDataOrThrow({\n context: this.cmsContext,\n model,\n values: initialValues,\n entry: originalEntry,\n skipValidation: options?.skipValidation\n });\n\n const values = await referenceFieldsMapping<TValues>({\n context: this.cmsContext,\n model,\n values: initialValues,\n validateEntries: false\n });\n\n const latestId = latestStorageEntry ? latestStorageEntry.id : sourceId;\n const { id, version: nextVersion } = increaseEntryIdVersion(latestId);\n\n const currentIdentity = this.identityContext.getIdentity();\n const currentDateTime = new Date();\n\n const status = rawInput.status || STATUS_DRAFT;\n if (status !== STATUS_DRAFT) {\n if (status === STATUS_PUBLISHED) {\n const canPublish = await this.accessControl.canAccessEntry({ model, pw: \"p\" });\n if (!canPublish) {\n throw new NotAuthorizedError(\n `Not allowed to access \"${model.modelId}\" entries.`\n );\n }\n } else if (status === STATUS_UNPUBLISHED) {\n const canUnpublish = await this.accessControl.canAccessEntry({ model, pw: \"u\" });\n if (!canUnpublish) {\n throw new NotAuthorizedError(\n `Not allowed to access \"${model.modelId}\" entries.`\n );\n }\n }\n }\n\n const locked = status !== STATUS_DRAFT;\n\n let revisionLevelPublishingMetaFields: Pick<\n CmsEntry,\n | \"revisionFirstPublishedOn\"\n | \"revisionLastPublishedOn\"\n | \"revisionFirstPublishedBy\"\n | \"revisionLastPublishedBy\"\n > = {\n revisionFirstPublishedOn: getDate(rawInput.revisionFirstPublishedOn, null),\n revisionLastPublishedOn: getDate(rawInput.revisionLastPublishedOn, null),\n revisionFirstPublishedBy: getIdentity(rawInput.revisionFirstPublishedBy, null),\n revisionLastPublishedBy: getIdentity(rawInput.revisionLastPublishedBy, null)\n };\n\n let entryLevelPublishingMetaFields: Pick<\n CmsEntry,\n \"firstPublishedOn\" | \"lastPublishedOn\" | \"firstPublishedBy\" | \"lastPublishedBy\"\n > = {\n firstPublishedOn: getDate(\n rawInput.firstPublishedOn,\n latestStorageEntry.firstPublishedOn\n ),\n lastPublishedOn: getDate(rawInput.lastPublishedOn, latestStorageEntry.lastPublishedOn),\n firstPublishedBy: getIdentity(\n rawInput.firstPublishedBy,\n latestStorageEntry.firstPublishedBy\n ),\n lastPublishedBy: getIdentity(\n rawInput.lastPublishedBy,\n latestStorageEntry.lastPublishedBy\n )\n };\n\n if (status === STATUS_PUBLISHED) {\n revisionLevelPublishingMetaFields = {\n revisionFirstPublishedOn: getDate(\n rawInput.revisionFirstPublishedOn,\n currentDateTime\n ),\n revisionLastPublishedOn: getDate(rawInput.revisionLastPublishedOn, currentDateTime),\n revisionFirstPublishedBy: getIdentity(\n rawInput.revisionFirstPublishedBy,\n currentIdentity\n ),\n revisionLastPublishedBy: getIdentity(\n rawInput.revisionLastPublishedBy,\n currentIdentity\n )\n };\n\n entryLevelPublishingMetaFields = {\n firstPublishedOn: getDate(\n rawInput.firstPublishedOn,\n latestStorageEntry.firstPublishedOn\n ),\n lastPublishedOn: getDate(rawInput.lastPublishedOn, currentDateTime),\n firstPublishedBy: getIdentity(\n rawInput.firstPublishedBy,\n latestStorageEntry.firstPublishedBy\n ),\n lastPublishedBy: getIdentity(rawInput.lastPublishedBy, currentIdentity)\n };\n }\n\n const entry: CmsEntry<TValues> = {\n ...originalEntry,\n id,\n version: nextVersion,\n createdOn: getDate(rawInput.createdOn, latestStorageEntry.createdOn),\n savedOn: getDate(rawInput.savedOn, currentDateTime),\n modifiedOn: getDate(rawInput.modifiedOn, currentDateTime),\n createdBy: getIdentity(rawInput.createdBy, latestStorageEntry.createdBy)!,\n savedBy: getIdentity(rawInput.savedBy, currentIdentity)!,\n modifiedBy: getIdentity(rawInput.modifiedBy, currentIdentity),\n ...entryLevelPublishingMetaFields,\n revisionCreatedOn: getDate(rawInput.revisionCreatedOn, currentDateTime),\n revisionSavedOn: getDate(rawInput.revisionSavedOn, currentDateTime),\n revisionModifiedOn: getDate(rawInput.revisionModifiedOn, null),\n revisionCreatedBy: getIdentity(rawInput.revisionCreatedBy, currentIdentity)!,\n revisionSavedBy: getIdentity(rawInput.revisionSavedBy, currentIdentity)!,\n revisionModifiedBy: getIdentity(rawInput.revisionModifiedBy, null),\n revisionDescription: undefined,\n ...revisionLevelPublishingMetaFields,\n locked,\n status,\n values,\n system: getSystem({\n input: rawInput,\n original: originalEntry\n }),\n live: originalEntry.live,\n expiresAt: null\n };\n\n return {\n entry,\n input: {\n ...rawInput,\n values: structuredClone(values)\n }\n };\n }\n}\n\nexport const CreateEntryRevisionFromDataFactory = createImplementation({\n abstraction: FactoryAbstraction,\n implementation: CreateEntryRevisionFromDataFactoryImpl,\n dependencies: [CmsContext, IdentityContext, AccessControl]\n});\n"],"names":["increaseEntryIdVersion","id","entryId","version","parseIdentifier","WebinyError","createIdentifier","CreateEntryRevisionFromDataFactoryImpl","cmsContext","identityContext","accessControl","sourceId","model","rawInput","originalEntry","latestStorageEntry","options","initialValues","mapAndCleanUpdatedInputData","validateModelEntryDataOrThrow","values","referenceFieldsMapping","latestId","nextVersion","currentIdentity","currentDateTime","Date","status","STATUS_DRAFT","STATUS_PUBLISHED","canPublish","NotAuthorizedError","STATUS_UNPUBLISHED","canUnpublish","locked","revisionLevelPublishingMetaFields","getDate","getIdentity","entryLevelPublishingMetaFields","entry","undefined","getSystem","structuredClone","CreateEntryRevisionFromDataFactory","createImplementation","FactoryAbstraction","CmsContext","IdentityContext","AccessControl"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"features/contentEntry/entryDataFactories/CreateEntryRevisionFromDataFactory/CreateEntryRevisionFromDataFactory.js","sources":["../../../../../src/features/contentEntry/entryDataFactories/CreateEntryRevisionFromDataFactory/CreateEntryRevisionFromDataFactory.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport {\n CreateEntryRevisionFromDataFactory as FactoryAbstraction,\n type ICreateEntryRevisionFromDataFactory,\n type ICreateEntryRevisionFromDataResponse\n} from \"./abstractions.js\";\nimport { AccessControl, CmsContext } from \"~/features/shared/abstractions.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport type {\n CmsEntry,\n CmsEntryValues,\n CmsModel,\n CreateCmsEntryInput,\n CreateCmsEntryOptionsInput\n} from \"~/types/index.js\";\nimport { getDate } from \"~/utils/date.js\";\nimport { getIdentity } from \"~/utils/identity.js\";\nimport { mapAndCleanUpdatedInputData } from \"../mapAndCleanUpdatedInputData.js\";\nimport { validateModelEntryDataOrThrow } from \"~/crud/contentEntry/entryDataValidation.js\";\nimport { referenceFieldsMapping } from \"~/crud/contentEntry/referenceFieldsMapping.js\";\nimport { createIdentifier, parseIdentifier } from \"@webiny/utils\";\nimport WebinyError from \"@webiny/error\";\nimport { STATUS_DRAFT, STATUS_PUBLISHED, STATUS_UNPUBLISHED } from \"../statuses.js\";\nimport { NotAuthorizedError } from \"~/utils/errors.js\";\nimport { getSystem } from \"../system.js\";\nimport { ModelToAstConverter } from \"~/features/contentModel/ModelToAstConverter/abstractions.js\";\nimport { ensureItemIds } from \"../../ensureItemIds.js\";\n\nconst increaseEntryIdVersion = (id: string) => {\n const { id: entryId, version } = parseIdentifier(id);\n if (!version) {\n throw new WebinyError(\n \"Cannot increase version on the ID without the version part.\",\n \"WRONG_ID\",\n {\n id\n }\n );\n }\n return {\n entryId,\n version: version + 1,\n id: createIdentifier({\n id: entryId,\n version: version + 1\n })\n };\n};\n\nclass CreateEntryRevisionFromDataFactoryImpl implements ICreateEntryRevisionFromDataFactory {\n public constructor(\n private readonly cmsContext: CmsContext.Interface,\n private readonly identityContext: IdentityContext.Interface,\n private readonly accessControl: AccessControl.Interface,\n private readonly modelToAstConverter: ModelToAstConverter.Interface\n ) {}\n\n public async create<TValues extends CmsEntryValues = CmsEntryValues>(\n sourceId: string,\n model: CmsModel,\n rawInput: CreateCmsEntryInput<TValues>,\n originalEntry: CmsEntry<TValues>,\n latestStorageEntry: CmsEntry<TValues>,\n options?: CreateCmsEntryOptionsInput\n ): Promise<ICreateEntryRevisionFromDataResponse<TValues>> {\n const initialValues = {\n ...originalEntry.values,\n ...mapAndCleanUpdatedInputData<TValues>(model, rawInput.values)\n };\n\n const modelAst = this.modelToAstConverter.toAst(model);\n await ensureItemIds(modelAst, initialValues);\n\n await validateModelEntryDataOrThrow({\n context: this.cmsContext,\n model,\n values: initialValues,\n entry: originalEntry,\n skipValidation: options?.skipValidation\n });\n\n const values = await referenceFieldsMapping<TValues>({\n context: this.cmsContext,\n model,\n values: initialValues,\n validateEntries: false\n });\n\n const latestId = latestStorageEntry ? latestStorageEntry.id : sourceId;\n const { id, version: nextVersion } = increaseEntryIdVersion(latestId);\n\n const currentIdentity = this.identityContext.getIdentity();\n const currentDateTime = new Date();\n\n const status = rawInput.status || STATUS_DRAFT;\n if (status !== STATUS_DRAFT) {\n if (status === STATUS_PUBLISHED) {\n const canPublish = await this.accessControl.canAccessEntry({ model, pw: \"p\" });\n if (!canPublish) {\n throw new NotAuthorizedError(\n `Not allowed to access \"${model.modelId}\" entries.`\n );\n }\n } else if (status === STATUS_UNPUBLISHED) {\n const canUnpublish = await this.accessControl.canAccessEntry({ model, pw: \"u\" });\n if (!canUnpublish) {\n throw new NotAuthorizedError(\n `Not allowed to access \"${model.modelId}\" entries.`\n );\n }\n }\n }\n\n const locked = status !== STATUS_DRAFT;\n\n let revisionLevelPublishingMetaFields: Pick<\n CmsEntry,\n | \"revisionFirstPublishedOn\"\n | \"revisionLastPublishedOn\"\n | \"revisionFirstPublishedBy\"\n | \"revisionLastPublishedBy\"\n > = {\n revisionFirstPublishedOn: getDate(rawInput.revisionFirstPublishedOn, null),\n revisionLastPublishedOn: getDate(rawInput.revisionLastPublishedOn, null),\n revisionFirstPublishedBy: getIdentity(rawInput.revisionFirstPublishedBy, null),\n revisionLastPublishedBy: getIdentity(rawInput.revisionLastPublishedBy, null)\n };\n\n let entryLevelPublishingMetaFields: Pick<\n CmsEntry,\n \"firstPublishedOn\" | \"lastPublishedOn\" | \"firstPublishedBy\" | \"lastPublishedBy\"\n > = {\n firstPublishedOn: getDate(\n rawInput.firstPublishedOn,\n latestStorageEntry.firstPublishedOn\n ),\n lastPublishedOn: getDate(rawInput.lastPublishedOn, latestStorageEntry.lastPublishedOn),\n firstPublishedBy: getIdentity(\n rawInput.firstPublishedBy,\n latestStorageEntry.firstPublishedBy\n ),\n lastPublishedBy: getIdentity(\n rawInput.lastPublishedBy,\n latestStorageEntry.lastPublishedBy\n )\n };\n\n if (status === STATUS_PUBLISHED) {\n revisionLevelPublishingMetaFields = {\n revisionFirstPublishedOn: getDate(\n rawInput.revisionFirstPublishedOn,\n currentDateTime\n ),\n revisionLastPublishedOn: getDate(rawInput.revisionLastPublishedOn, currentDateTime),\n revisionFirstPublishedBy: getIdentity(\n rawInput.revisionFirstPublishedBy,\n currentIdentity\n ),\n revisionLastPublishedBy: getIdentity(\n rawInput.revisionLastPublishedBy,\n currentIdentity\n )\n };\n\n entryLevelPublishingMetaFields = {\n firstPublishedOn: getDate(\n rawInput.firstPublishedOn,\n latestStorageEntry.firstPublishedOn\n ),\n lastPublishedOn: getDate(rawInput.lastPublishedOn, currentDateTime),\n firstPublishedBy: getIdentity(\n rawInput.firstPublishedBy,\n latestStorageEntry.firstPublishedBy\n ),\n lastPublishedBy: getIdentity(rawInput.lastPublishedBy, currentIdentity)\n };\n }\n\n const entry: CmsEntry<TValues> = {\n ...originalEntry,\n id,\n version: nextVersion,\n createdOn: getDate(rawInput.createdOn, latestStorageEntry.createdOn),\n savedOn: getDate(rawInput.savedOn, currentDateTime),\n modifiedOn: getDate(rawInput.modifiedOn, currentDateTime),\n createdBy: getIdentity(rawInput.createdBy, latestStorageEntry.createdBy)!,\n savedBy: getIdentity(rawInput.savedBy, currentIdentity)!,\n modifiedBy: getIdentity(rawInput.modifiedBy, currentIdentity),\n ...entryLevelPublishingMetaFields,\n revisionCreatedOn: getDate(rawInput.revisionCreatedOn, currentDateTime),\n revisionSavedOn: getDate(rawInput.revisionSavedOn, currentDateTime),\n revisionModifiedOn: getDate(rawInput.revisionModifiedOn, null),\n revisionCreatedBy: getIdentity(rawInput.revisionCreatedBy, currentIdentity)!,\n revisionSavedBy: getIdentity(rawInput.revisionSavedBy, currentIdentity)!,\n revisionModifiedBy: getIdentity(rawInput.revisionModifiedBy, null),\n revisionDescription: undefined,\n ...revisionLevelPublishingMetaFields,\n locked,\n status,\n values,\n system: getSystem({\n input: rawInput,\n original: originalEntry\n }),\n live: originalEntry.live,\n expiresAt: null\n };\n\n return {\n entry,\n input: {\n ...rawInput,\n values: structuredClone(values)\n }\n };\n }\n}\n\nexport const CreateEntryRevisionFromDataFactory = createImplementation({\n abstraction: FactoryAbstraction,\n implementation: CreateEntryRevisionFromDataFactoryImpl,\n dependencies: [CmsContext, IdentityContext, AccessControl, ModelToAstConverter]\n});\n"],"names":["increaseEntryIdVersion","id","entryId","version","parseIdentifier","WebinyError","createIdentifier","CreateEntryRevisionFromDataFactoryImpl","cmsContext","identityContext","accessControl","modelToAstConverter","sourceId","model","rawInput","originalEntry","latestStorageEntry","options","initialValues","mapAndCleanUpdatedInputData","modelAst","ensureItemIds","validateModelEntryDataOrThrow","values","referenceFieldsMapping","latestId","nextVersion","currentIdentity","currentDateTime","Date","status","STATUS_DRAFT","STATUS_PUBLISHED","canPublish","NotAuthorizedError","STATUS_UNPUBLISHED","canUnpublish","locked","revisionLevelPublishingMetaFields","getDate","getIdentity","entryLevelPublishingMetaFields","entry","undefined","getSystem","structuredClone","CreateEntryRevisionFromDataFactory","createImplementation","FactoryAbstraction","CmsContext","IdentityContext","AccessControl","ModelToAstConverter"],"mappings":"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"}
|
package/features/contentEntry/entryDataFactories/UpdateEntryDataFactory/UpdateEntryDataFactory.d.ts
CHANGED
|
@@ -2,10 +2,12 @@ import { type IUpdateEntryDataFactory, type IUpdateEntryDataResponse } from "./a
|
|
|
2
2
|
import { CmsContext } from "../../../../features/shared/abstractions.js";
|
|
3
3
|
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
4
4
|
import type { CmsEntry, CmsEntryValues, CmsModel, UpdateCmsEntryInput, UpdateCmsEntryOptionsInput } from "../../../../types/index.js";
|
|
5
|
+
import { ModelToAstConverter } from "../../../../features/contentModel/ModelToAstConverter/abstractions.js";
|
|
5
6
|
declare class UpdateEntryDataFactoryImpl implements IUpdateEntryDataFactory {
|
|
6
7
|
private readonly cmsContext;
|
|
7
8
|
private readonly identityContext;
|
|
8
|
-
|
|
9
|
+
private readonly modelToAstConverter;
|
|
10
|
+
constructor(cmsContext: CmsContext.Interface, identityContext: IdentityContext.Interface, modelToAstConverter: ModelToAstConverter.Interface);
|
|
9
11
|
create<TValues extends CmsEntryValues = CmsEntryValues>(model: CmsModel, rawInput: UpdateCmsEntryInput<TValues>, originalEntry: CmsEntry<TValues>, options?: UpdateCmsEntryOptionsInput): Promise<IUpdateEntryDataResponse<TValues>>;
|
|
10
12
|
}
|
|
11
13
|
export declare const UpdateEntryDataFactory: import("@webiny/di").Implementation<typeof UpdateEntryDataFactoryImpl>;
|
package/features/contentEntry/entryDataFactories/UpdateEntryDataFactory/UpdateEntryDataFactory.js
CHANGED
|
@@ -9,6 +9,8 @@ import { referenceFieldsMapping } from "../../../../crud/contentEntry/referenceF
|
|
|
9
9
|
import { mapAndCleanUpdatedInputData } from "../mapAndCleanUpdatedInputData.js";
|
|
10
10
|
import { getSystem } from "../system.js";
|
|
11
11
|
import { getExpiresAt } from "../expiresAt.js";
|
|
12
|
+
import { ModelToAstConverter } from "../../../contentModel/ModelToAstConverter/abstractions.js";
|
|
13
|
+
import { ensureItemIds } from "../../ensureItemIds.js";
|
|
12
14
|
const allowedEntryStatus = [
|
|
13
15
|
"draft",
|
|
14
16
|
"published",
|
|
@@ -16,9 +18,10 @@ const allowedEntryStatus = [
|
|
|
16
18
|
];
|
|
17
19
|
const transformEntryStatus = (status)=>allowedEntryStatus.includes(status) ? status : "draft";
|
|
18
20
|
class UpdateEntryDataFactoryImpl {
|
|
19
|
-
constructor(cmsContext, identityContext){
|
|
21
|
+
constructor(cmsContext, identityContext, modelToAstConverter){
|
|
20
22
|
this.cmsContext = cmsContext;
|
|
21
23
|
this.identityContext = identityContext;
|
|
24
|
+
this.modelToAstConverter = modelToAstConverter;
|
|
22
25
|
}
|
|
23
26
|
async create(model, rawInput, originalEntry, options) {
|
|
24
27
|
const cleanedValues = mapAndCleanUpdatedInputData(model, rawInput?.values || {});
|
|
@@ -33,6 +36,8 @@ class UpdateEntryDataFactoryImpl {
|
|
|
33
36
|
...originalEntry.values,
|
|
34
37
|
...cleanedValues
|
|
35
38
|
};
|
|
39
|
+
const modelAst = this.modelToAstConverter.toAst(model);
|
|
40
|
+
await ensureItemIds(modelAst, mergedValues);
|
|
36
41
|
const values = await referenceFieldsMapping({
|
|
37
42
|
context: this.cmsContext,
|
|
38
43
|
model,
|
|
@@ -100,7 +105,8 @@ const UpdateEntryDataFactory_UpdateEntryDataFactory = createImplementation({
|
|
|
100
105
|
implementation: UpdateEntryDataFactoryImpl,
|
|
101
106
|
dependencies: [
|
|
102
107
|
CmsContext,
|
|
103
|
-
IdentityContext
|
|
108
|
+
IdentityContext,
|
|
109
|
+
ModelToAstConverter
|
|
104
110
|
]
|
|
105
111
|
});
|
|
106
112
|
export { UpdateEntryDataFactory_UpdateEntryDataFactory as UpdateEntryDataFactory };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/contentEntry/entryDataFactories/UpdateEntryDataFactory/UpdateEntryDataFactory.js","sources":["../../../../../src/features/contentEntry/entryDataFactories/UpdateEntryDataFactory/UpdateEntryDataFactory.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport {\n type IUpdateEntryDataFactory,\n type IUpdateEntryDataResponse,\n UpdateEntryDataFactory as FactoryAbstraction\n} from \"./abstractions.js\";\nimport { CmsContext } from \"~/features/shared/abstractions.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport type {\n CmsEntry,\n CmsEntryStatus,\n CmsEntryValues,\n CmsModel,\n UpdateCmsEntryInput,\n UpdateCmsEntryOptionsInput\n} from \"~/types/index.js\";\nimport { getDate } from \"~/utils/date.js\";\nimport { getIdentity } from \"~/utils/identity.js\";\nimport { validateModelEntryDataOrThrow } from \"~/crud/contentEntry/entryDataValidation.js\";\nimport { referenceFieldsMapping } from \"~/crud/contentEntry/referenceFieldsMapping.js\";\nimport { mapAndCleanUpdatedInputData } from \"../mapAndCleanUpdatedInputData.js\";\nimport { getSystem } from \"../system.js\";\nimport { getExpiresAt } from \"../expiresAt.js\";\n\nconst allowedEntryStatus: string[] = [\"draft\", \"published\", \"unpublished\"];\n\nconst transformEntryStatus = (status: CmsEntryStatus | string): CmsEntryStatus => {\n return allowedEntryStatus.includes(status) ? (status as CmsEntryStatus) : \"draft\";\n};\n\nclass UpdateEntryDataFactoryImpl implements IUpdateEntryDataFactory {\n public constructor(\n private readonly cmsContext: CmsContext.Interface,\n private readonly identityContext: IdentityContext.Interface\n ) {}\n\n public async create<TValues extends CmsEntryValues = CmsEntryValues>(\n model: CmsModel,\n rawInput: UpdateCmsEntryInput<TValues>,\n originalEntry: CmsEntry<TValues>,\n options?: UpdateCmsEntryOptionsInput\n ): Promise<IUpdateEntryDataResponse<TValues>> {\n const cleanedValues = mapAndCleanUpdatedInputData<TValues>(\n model,\n rawInput?.values || ({} as TValues)\n );\n\n await validateModelEntryDataOrThrow({\n context: this.cmsContext,\n model,\n values: cleanedValues,\n entry: originalEntry,\n skipValidation: options?.skipValidation\n });\n\n const mergedValues: TValues = {\n ...originalEntry.values,\n ...cleanedValues\n };\n\n const values = await referenceFieldsMapping<TValues>({\n context: this.cmsContext,\n model,\n values: mergedValues,\n validateEntries: false\n });\n\n const currentIdentity = this.identityContext.getIdentity();\n const currentDateTime = new Date();\n\n const entry: CmsEntry<TValues> = {\n ...originalEntry,\n revisionCreatedOn: getDate(rawInput.revisionCreatedOn, originalEntry.revisionCreatedOn),\n revisionModifiedOn: getDate(rawInput.revisionModifiedOn, currentDateTime),\n revisionSavedOn: getDate(rawInput.revisionSavedOn, currentDateTime),\n revisionDeletedOn: getDate(rawInput.revisionDeletedOn, null),\n revisionRestoredOn: getDate(rawInput.revisionRestoredOn, null),\n revisionFirstPublishedOn: getDate(\n rawInput.revisionFirstPublishedOn,\n originalEntry.revisionFirstPublishedOn\n ),\n revisionLastPublishedOn: getDate(\n rawInput.revisionLastPublishedOn,\n originalEntry.revisionLastPublishedOn\n ),\n revisionCreatedBy: getIdentity(\n rawInput.revisionCreatedBy,\n originalEntry.revisionCreatedBy\n )!,\n revisionModifiedBy: getIdentity(rawInput.revisionModifiedBy, currentIdentity),\n revisionSavedBy: getIdentity(rawInput.revisionSavedBy, currentIdentity)!,\n revisionDeletedBy: getIdentity(rawInput.revisionSavedBy, null),\n revisionRestoredBy: getIdentity(rawInput.revisionRestoredBy, null),\n revisionFirstPublishedBy: getIdentity(\n rawInput.revisionFirstPublishedBy,\n originalEntry.revisionFirstPublishedBy\n ),\n revisionLastPublishedBy: getIdentity(\n rawInput.revisionLastPublishedBy,\n originalEntry.revisionLastPublishedBy\n ),\n createdOn: getDate(rawInput.createdOn, originalEntry.createdOn),\n savedOn: getDate(rawInput.savedOn, currentDateTime),\n modifiedOn: getDate(rawInput.modifiedOn, currentDateTime),\n deletedOn: getDate(rawInput.deletedOn, null),\n restoredOn: getDate(rawInput.restoredOn, null),\n firstPublishedOn: getDate(rawInput.firstPublishedOn, originalEntry.firstPublishedOn),\n lastPublishedOn: getDate(rawInput.lastPublishedOn, originalEntry.lastPublishedOn),\n createdBy: getIdentity(rawInput.createdBy, originalEntry.createdBy)!,\n savedBy: getIdentity(rawInput.savedBy, currentIdentity)!,\n modifiedBy: getIdentity(rawInput.modifiedBy, currentIdentity),\n deletedBy: getIdentity(rawInput.deletedBy, null),\n restoredBy: getIdentity(rawInput.restoredBy, null),\n firstPublishedBy: getIdentity(\n rawInput.firstPublishedBy,\n originalEntry.firstPublishedBy\n ),\n lastPublishedBy: getIdentity(rawInput.lastPublishedBy, originalEntry.lastPublishedBy),\n values,\n status: transformEntryStatus(originalEntry.status),\n system: getSystem({\n input: rawInput,\n original: originalEntry\n }),\n live: originalEntry.live,\n expiresAt: getExpiresAt({ expiresAt: rawInput.expiresAt }, originalEntry)\n };\n\n const folderId = rawInput.wbyAco_location?.folderId;\n if (folderId) {\n entry.location = {\n folderId\n };\n }\n\n return {\n entry,\n input: {\n ...rawInput,\n values: structuredClone(values)\n }\n };\n }\n}\n\nexport const UpdateEntryDataFactory = createImplementation({\n abstraction: FactoryAbstraction,\n implementation: UpdateEntryDataFactoryImpl,\n dependencies: [CmsContext, IdentityContext]\n});\n"],"names":["allowedEntryStatus","transformEntryStatus","status","UpdateEntryDataFactoryImpl","cmsContext","identityContext","model","rawInput","originalEntry","options","cleanedValues","mapAndCleanUpdatedInputData","validateModelEntryDataOrThrow","mergedValues","values","referenceFieldsMapping","currentIdentity","currentDateTime","Date","entry","getDate","getIdentity","getSystem","getExpiresAt","folderId","structuredClone","UpdateEntryDataFactory","createImplementation","FactoryAbstraction","CmsContext","IdentityContext"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"features/contentEntry/entryDataFactories/UpdateEntryDataFactory/UpdateEntryDataFactory.js","sources":["../../../../../src/features/contentEntry/entryDataFactories/UpdateEntryDataFactory/UpdateEntryDataFactory.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport {\n type IUpdateEntryDataFactory,\n type IUpdateEntryDataResponse,\n UpdateEntryDataFactory as FactoryAbstraction\n} from \"./abstractions.js\";\nimport { CmsContext } from \"~/features/shared/abstractions.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport type {\n CmsEntry,\n CmsEntryStatus,\n CmsEntryValues,\n CmsModel,\n UpdateCmsEntryInput,\n UpdateCmsEntryOptionsInput\n} from \"~/types/index.js\";\nimport { getDate } from \"~/utils/date.js\";\nimport { getIdentity } from \"~/utils/identity.js\";\nimport { validateModelEntryDataOrThrow } from \"~/crud/contentEntry/entryDataValidation.js\";\nimport { referenceFieldsMapping } from \"~/crud/contentEntry/referenceFieldsMapping.js\";\nimport { mapAndCleanUpdatedInputData } from \"../mapAndCleanUpdatedInputData.js\";\nimport { getSystem } from \"../system.js\";\nimport { getExpiresAt } from \"../expiresAt.js\";\nimport { ModelToAstConverter } from \"~/features/contentModel/ModelToAstConverter/abstractions.js\";\nimport { ensureItemIds } from \"../../ensureItemIds.js\";\n\nconst allowedEntryStatus: string[] = [\"draft\", \"published\", \"unpublished\"];\n\nconst transformEntryStatus = (status: CmsEntryStatus | string): CmsEntryStatus => {\n return allowedEntryStatus.includes(status) ? (status as CmsEntryStatus) : \"draft\";\n};\n\nclass UpdateEntryDataFactoryImpl implements IUpdateEntryDataFactory {\n public constructor(\n private readonly cmsContext: CmsContext.Interface,\n private readonly identityContext: IdentityContext.Interface,\n private readonly modelToAstConverter: ModelToAstConverter.Interface\n ) {}\n\n public async create<TValues extends CmsEntryValues = CmsEntryValues>(\n model: CmsModel,\n rawInput: UpdateCmsEntryInput<TValues>,\n originalEntry: CmsEntry<TValues>,\n options?: UpdateCmsEntryOptionsInput\n ): Promise<IUpdateEntryDataResponse<TValues>> {\n const cleanedValues = mapAndCleanUpdatedInputData<TValues>(\n model,\n rawInput?.values || ({} as TValues)\n );\n\n await validateModelEntryDataOrThrow({\n context: this.cmsContext,\n model,\n values: cleanedValues,\n entry: originalEntry,\n skipValidation: options?.skipValidation\n });\n\n const mergedValues: TValues = {\n ...originalEntry.values,\n ...cleanedValues\n };\n\n const modelAst = this.modelToAstConverter.toAst(model);\n await ensureItemIds(modelAst, mergedValues);\n\n const values = await referenceFieldsMapping<TValues>({\n context: this.cmsContext,\n model,\n values: mergedValues,\n validateEntries: false\n });\n\n const currentIdentity = this.identityContext.getIdentity();\n const currentDateTime = new Date();\n\n const entry: CmsEntry<TValues> = {\n ...originalEntry,\n revisionCreatedOn: getDate(rawInput.revisionCreatedOn, originalEntry.revisionCreatedOn),\n revisionModifiedOn: getDate(rawInput.revisionModifiedOn, currentDateTime),\n revisionSavedOn: getDate(rawInput.revisionSavedOn, currentDateTime),\n revisionDeletedOn: getDate(rawInput.revisionDeletedOn, null),\n revisionRestoredOn: getDate(rawInput.revisionRestoredOn, null),\n revisionFirstPublishedOn: getDate(\n rawInput.revisionFirstPublishedOn,\n originalEntry.revisionFirstPublishedOn\n ),\n revisionLastPublishedOn: getDate(\n rawInput.revisionLastPublishedOn,\n originalEntry.revisionLastPublishedOn\n ),\n revisionCreatedBy: getIdentity(\n rawInput.revisionCreatedBy,\n originalEntry.revisionCreatedBy\n )!,\n revisionModifiedBy: getIdentity(rawInput.revisionModifiedBy, currentIdentity),\n revisionSavedBy: getIdentity(rawInput.revisionSavedBy, currentIdentity)!,\n revisionDeletedBy: getIdentity(rawInput.revisionSavedBy, null),\n revisionRestoredBy: getIdentity(rawInput.revisionRestoredBy, null),\n revisionFirstPublishedBy: getIdentity(\n rawInput.revisionFirstPublishedBy,\n originalEntry.revisionFirstPublishedBy\n ),\n revisionLastPublishedBy: getIdentity(\n rawInput.revisionLastPublishedBy,\n originalEntry.revisionLastPublishedBy\n ),\n createdOn: getDate(rawInput.createdOn, originalEntry.createdOn),\n savedOn: getDate(rawInput.savedOn, currentDateTime),\n modifiedOn: getDate(rawInput.modifiedOn, currentDateTime),\n deletedOn: getDate(rawInput.deletedOn, null),\n restoredOn: getDate(rawInput.restoredOn, null),\n firstPublishedOn: getDate(rawInput.firstPublishedOn, originalEntry.firstPublishedOn),\n lastPublishedOn: getDate(rawInput.lastPublishedOn, originalEntry.lastPublishedOn),\n createdBy: getIdentity(rawInput.createdBy, originalEntry.createdBy)!,\n savedBy: getIdentity(rawInput.savedBy, currentIdentity)!,\n modifiedBy: getIdentity(rawInput.modifiedBy, currentIdentity),\n deletedBy: getIdentity(rawInput.deletedBy, null),\n restoredBy: getIdentity(rawInput.restoredBy, null),\n firstPublishedBy: getIdentity(\n rawInput.firstPublishedBy,\n originalEntry.firstPublishedBy\n ),\n lastPublishedBy: getIdentity(rawInput.lastPublishedBy, originalEntry.lastPublishedBy),\n values,\n status: transformEntryStatus(originalEntry.status),\n system: getSystem({\n input: rawInput,\n original: originalEntry\n }),\n live: originalEntry.live,\n expiresAt: getExpiresAt({ expiresAt: rawInput.expiresAt }, originalEntry)\n };\n\n const folderId = rawInput.wbyAco_location?.folderId;\n if (folderId) {\n entry.location = {\n folderId\n };\n }\n\n return {\n entry,\n input: {\n ...rawInput,\n values: structuredClone(values)\n }\n };\n }\n}\n\nexport const UpdateEntryDataFactory = createImplementation({\n abstraction: FactoryAbstraction,\n implementation: UpdateEntryDataFactoryImpl,\n dependencies: [CmsContext, IdentityContext, ModelToAstConverter]\n});\n"],"names":["allowedEntryStatus","transformEntryStatus","status","UpdateEntryDataFactoryImpl","cmsContext","identityContext","modelToAstConverter","model","rawInput","originalEntry","options","cleanedValues","mapAndCleanUpdatedInputData","validateModelEntryDataOrThrow","mergedValues","modelAst","ensureItemIds","values","referenceFieldsMapping","currentIdentity","currentDateTime","Date","entry","getDate","getIdentity","getSystem","getExpiresAt","folderId","structuredClone","UpdateEntryDataFactory","createImplementation","FactoryAbstraction","CmsContext","IdentityContext","ModelToAstConverter"],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import { CmsContext, StorageOperations } from "../../../features/shared/abstract
|
|
|
6
6
|
import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
|
|
7
7
|
import type { CmsModel } from "../../../types/index.js";
|
|
8
8
|
import { ModelFieldCompression } from "../../../features/contentModel/ModelFieldCompression/index.js";
|
|
9
|
+
import { RuntimeTenant } from "../../../features/runtimeTenant/abstractions.js";
|
|
9
10
|
/**
|
|
10
11
|
* CreateModelRepository - Validates domain rules and persists a new model.
|
|
11
12
|
*
|
|
@@ -28,8 +29,9 @@ declare class CreateModelRepositoryImpl implements RepositoryAbstraction.Interfa
|
|
|
28
29
|
private readonly tenantContext;
|
|
29
30
|
private readonly cmsContext;
|
|
30
31
|
private readonly modelFieldCompression;
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
private readonly runtimeTenant;
|
|
33
|
+
constructor(modelCache: ModelCache.Interface, pluginModelsProvider: PluginModelsProvider.Interface, listModelsUseCase: ListModelsUseCase.Interface, storageOperations: StorageOperations.Interface, tenantContext: TenantContext.Interface, cmsContext: CmsContext.Interface, modelFieldCompression: ModelFieldCompression.Interface, runtimeTenant: RuntimeTenant.Interface);
|
|
34
|
+
execute(initialModel: CmsModel): Promise<Result<CmsModel, RepositoryAbstraction.Error>>;
|
|
33
35
|
}
|
|
34
36
|
export declare const CreateModelRepository: typeof CreateModelRepositoryImpl & {
|
|
35
37
|
__abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").ICreateModelRepository>;
|
|
@@ -13,6 +13,7 @@ import { validateSingularApiName } from "../../../domain/contentModel/validation
|
|
|
13
13
|
import { validatePluralApiName } from "../../../domain/contentModel/validation/pluralApiName.js";
|
|
14
14
|
import { validateModelFields } from "../../../domain/contentModel/validation/modelFields.js";
|
|
15
15
|
import { ModelFieldCompression } from "../ModelFieldCompression/index.js";
|
|
16
|
+
import { RuntimeTenant } from "../../runtimeTenant/abstractions.js";
|
|
16
17
|
const getModelId = (model)=>{
|
|
17
18
|
const { modelId, name } = model;
|
|
18
19
|
const value = modelId ? modelId.trim() : null;
|
|
@@ -25,7 +26,7 @@ const getModelId = (model)=>{
|
|
|
25
26
|
throw new ModelValidationError('There is no "modelId" or "name" passed into the create model method.');
|
|
26
27
|
};
|
|
27
28
|
class CreateModelRepositoryImpl {
|
|
28
|
-
constructor(modelCache, pluginModelsProvider, listModelsUseCase, storageOperations, tenantContext, cmsContext, modelFieldCompression){
|
|
29
|
+
constructor(modelCache, pluginModelsProvider, listModelsUseCase, storageOperations, tenantContext, cmsContext, modelFieldCompression, runtimeTenant){
|
|
29
30
|
this.modelCache = modelCache;
|
|
30
31
|
this.pluginModelsProvider = pluginModelsProvider;
|
|
31
32
|
this.listModelsUseCase = listModelsUseCase;
|
|
@@ -33,8 +34,10 @@ class CreateModelRepositoryImpl {
|
|
|
33
34
|
this.tenantContext = tenantContext;
|
|
34
35
|
this.cmsContext = cmsContext;
|
|
35
36
|
this.modelFieldCompression = modelFieldCompression;
|
|
37
|
+
this.runtimeTenant = runtimeTenant;
|
|
36
38
|
}
|
|
37
|
-
async execute(
|
|
39
|
+
async execute(initialModel) {
|
|
40
|
+
const model = this.runtimeTenant.assign(initialModel);
|
|
38
41
|
try {
|
|
39
42
|
const tenant = this.tenantContext.getTenant();
|
|
40
43
|
const modelId = getModelId(model);
|
|
@@ -103,7 +106,7 @@ class CreateModelRepositoryImpl {
|
|
|
103
106
|
}
|
|
104
107
|
});
|
|
105
108
|
this.modelCache.clear();
|
|
106
|
-
return Result.ok();
|
|
109
|
+
return Result.ok(model);
|
|
107
110
|
} catch (error) {
|
|
108
111
|
console.error(error, error.stack);
|
|
109
112
|
return Result.fail(new ModelPersistenceError(error));
|
|
@@ -119,7 +122,8 @@ const CreateModelRepository_CreateModelRepository = CreateModelRepository.create
|
|
|
119
122
|
StorageOperations,
|
|
120
123
|
TenantContext,
|
|
121
124
|
CmsContext,
|
|
122
|
-
ModelFieldCompression
|
|
125
|
+
ModelFieldCompression,
|
|
126
|
+
RuntimeTenant
|
|
123
127
|
]
|
|
124
128
|
});
|
|
125
129
|
export { CreateModelRepository_CreateModelRepository as CreateModelRepository };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/contentModel/CreateModel/CreateModelRepository.js","sources":["../../../../src/features/contentModel/CreateModel/CreateModelRepository.ts"],"sourcesContent":["import camelCase from \"lodash/camelCase.js\";\nimport { Result } from \"@webiny/feature/api\";\nimport { CreateModelRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport { ModelCache, PluginModelsProvider } from \"~/features/contentModel/shared/abstractions.js\";\nimport { ListModelsUseCase } from \"~/features/contentModel/ListModels/index.js\";\nimport {\n ModelAlreadyExistsError,\n ModelPersistenceError,\n ModelValidationError\n} from \"~/domain/contentModel/errors.js\";\nimport { CmsContext, StorageOperations } from \"~/features/shared/abstractions.js\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport {\n validateExistingModelId,\n validateModelIdAllowed\n} from \"~/crud/contentModel/validate/modelId.js\";\nimport { validateEndingAllowed } from \"~/crud/contentModel/validate/endingAllowed.js\";\nimport type { CmsModel } from \"~/types/index.js\";\nimport { ensureTypeTag } from \"~/domain/contentModel/ensureTypeTag.js\";\nimport { validateSingularApiName } from \"~/domain/contentModel/validation/singularApiName.js\";\nimport { validatePluralApiName } from \"~/domain/contentModel/validation/pluralApiName.js\";\nimport { validateModelFields } from \"~/domain/contentModel/validation/modelFields.js\";\nimport { ModelFieldCompression } from \"~/features/contentModel/ModelFieldCompression/index.js\";\n\n/**\n * Generate modelId from model following the exact logic from beforeCreate.ts\n */\nconst getModelId = (model: { modelId?: string; name?: string }): string => {\n const { modelId, name } = model;\n const value = modelId ? modelId.trim() : null;\n if (value) {\n const isModelIdValid = camelCase(value).toLowerCase() === value.toLowerCase();\n if (isModelIdValid) {\n return value;\n }\n return camelCase(value);\n } else if (name) {\n return camelCase(name.trim());\n }\n throw new ModelValidationError(\n `There is no \"modelId\" or \"name\" passed into the create model method.`\n );\n};\n\n/**\n * CreateModelRepository - Validates domain rules and persists a new model.\n *\n * Responsibilities:\n * - Generate modelId from input\n * - Validate modelId is allowed (not in disallowed list)\n * - Validate API name endings\n * - Validate modelId uniqueness (database + plugins)\n * - Validate API name uniqueness (database + plugins)\n * - Validate plugin conflicts\n * - Validate model fields\n * - Persist to storage\n * - Clear ModelCache after successful create\n */\nclass CreateModelRepositoryImpl implements RepositoryAbstraction.Interface {\n public constructor(\n private readonly modelCache: ModelCache.Interface,\n private readonly pluginModelsProvider: PluginModelsProvider.Interface,\n private readonly listModelsUseCase: ListModelsUseCase.Interface,\n private readonly storageOperations: StorageOperations.Interface,\n private readonly tenantContext: TenantContext.Interface,\n private readonly cmsContext: CmsContext.Interface,\n private readonly modelFieldCompression: ModelFieldCompression.Interface\n ) {}\n\n async execute(model: CmsModel): Promise<Result<void, RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n\n // TODO: this will eventually become part of the Model domain object.\n const modelId = getModelId(model);\n model.modelId = modelId;\n\n // Validate modelId is allowed (not in disallowed list)\n try {\n validateModelIdAllowed({ model });\n } catch (error) {\n return Result.fail(\n new ModelValidationError({\n message: error.message,\n data: error.data\n })\n );\n }\n\n // Validate API name endings\n try {\n validateEndingAllowed({ model });\n } catch (error) {\n return Result.fail(\n new ModelValidationError({\n message: error.message,\n data: error.data\n })\n );\n }\n\n // Check for plugin model conflicts\n const pluginModels = await this.pluginModelsProvider.list(tenant.id);\n const pluginModelConflict = pluginModels.find(pm => {\n return pm.modelId === model.modelId;\n });\n\n if (pluginModelConflict) {\n return Result.fail(\n new ModelAlreadyExistsError({\n modelId,\n message: `Model \"${modelId}\" is already registered via a plugin.`\n })\n );\n }\n\n // Get all models for further validation\n const modelsResult = await this.listModelsUseCase.execute();\n\n if (modelsResult.isFail()) {\n return Result.fail(new ModelPersistenceError(modelsResult.error));\n }\n\n const models = modelsResult.value;\n\n try {\n /**\n * We need to check for the existence of:\n * - modelId\n * - singularApiName\n * - pluralApiName\n */\n for (const existingModel of models) {\n validateExistingModelId({\n existingModel,\n model\n });\n validateSingularApiName({\n existingModel,\n model\n });\n validatePluralApiName({\n existingModel,\n model\n });\n }\n\n await validateModelFields({\n models,\n model,\n context: this.cmsContext\n });\n } catch (error) {\n return Result.fail(\n new ModelValidationError({ message: error.message, data: error.data })\n );\n }\n\n // TODO: ideally, this will eventually be handled by the Model domain object\n model.tags = ensureTypeTag(model);\n\n const fields = await this.modelFieldCompression.compress(model.fields);\n\n // Persist to storage\n await this.storageOperations.models.create({\n model: {\n ...model,\n fields\n }\n });\n\n // Clear cache\n this.modelCache.clear();\n\n return Result.ok();\n } catch (error) {\n console.error(error, error.stack);\n return Result.fail(new ModelPersistenceError(error as Error));\n }\n }\n}\n\nexport const CreateModelRepository = RepositoryAbstraction.createImplementation({\n implementation: CreateModelRepositoryImpl,\n dependencies: [\n ModelCache,\n PluginModelsProvider,\n ListModelsUseCase,\n StorageOperations,\n TenantContext,\n CmsContext,\n ModelFieldCompression\n ]\n});\n"],"names":["getModelId","model","modelId","name","value","isModelIdValid","camelCase","ModelValidationError","CreateModelRepositoryImpl","modelCache","pluginModelsProvider","listModelsUseCase","storageOperations","tenantContext","cmsContext","modelFieldCompression","tenant","validateModelIdAllowed","error","Result","validateEndingAllowed","pluginModels","pluginModelConflict","pm","ModelAlreadyExistsError","modelsResult","ModelPersistenceError","models","existingModel","validateExistingModelId","validateSingularApiName","validatePluralApiName","validateModelFields","ensureTypeTag","fields","console","CreateModelRepository","RepositoryAbstraction","ModelCache","PluginModelsProvider","ListModelsUseCase","StorageOperations","TenantContext","CmsContext","ModelFieldCompression"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"features/contentModel/CreateModel/CreateModelRepository.js","sources":["../../../../src/features/contentModel/CreateModel/CreateModelRepository.ts"],"sourcesContent":["import camelCase from \"lodash/camelCase.js\";\nimport { Result } from \"@webiny/feature/api\";\nimport { CreateModelRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport { ModelCache, PluginModelsProvider } from \"~/features/contentModel/shared/abstractions.js\";\nimport { ListModelsUseCase } from \"~/features/contentModel/ListModels/index.js\";\nimport {\n ModelAlreadyExistsError,\n ModelPersistenceError,\n ModelValidationError\n} from \"~/domain/contentModel/errors.js\";\nimport { CmsContext, StorageOperations } from \"~/features/shared/abstractions.js\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport {\n validateExistingModelId,\n validateModelIdAllowed\n} from \"~/crud/contentModel/validate/modelId.js\";\nimport { validateEndingAllowed } from \"~/crud/contentModel/validate/endingAllowed.js\";\nimport type { CmsModel } from \"~/types/index.js\";\nimport { ensureTypeTag } from \"~/domain/contentModel/ensureTypeTag.js\";\nimport { validateSingularApiName } from \"~/domain/contentModel/validation/singularApiName.js\";\nimport { validatePluralApiName } from \"~/domain/contentModel/validation/pluralApiName.js\";\nimport { validateModelFields } from \"~/domain/contentModel/validation/modelFields.js\";\nimport { ModelFieldCompression } from \"~/features/contentModel/ModelFieldCompression/index.js\";\nimport { RuntimeTenant } from \"~/features/runtimeTenant/abstractions.js\";\n\n/**\n * Generate modelId from model following the exact logic from beforeCreate.ts\n */\nconst getModelId = (model: { modelId?: string; name?: string }): string => {\n const { modelId, name } = model;\n const value = modelId ? modelId.trim() : null;\n if (value) {\n const isModelIdValid = camelCase(value).toLowerCase() === value.toLowerCase();\n if (isModelIdValid) {\n return value;\n }\n return camelCase(value);\n } else if (name) {\n return camelCase(name.trim());\n }\n throw new ModelValidationError(\n `There is no \"modelId\" or \"name\" passed into the create model method.`\n );\n};\n\n/**\n * CreateModelRepository - Validates domain rules and persists a new model.\n *\n * Responsibilities:\n * - Generate modelId from input\n * - Validate modelId is allowed (not in disallowed list)\n * - Validate API name endings\n * - Validate modelId uniqueness (database + plugins)\n * - Validate API name uniqueness (database + plugins)\n * - Validate plugin conflicts\n * - Validate model fields\n * - Persist to storage\n * - Clear ModelCache after successful create\n */\nclass CreateModelRepositoryImpl implements RepositoryAbstraction.Interface {\n public constructor(\n private readonly modelCache: ModelCache.Interface,\n private readonly pluginModelsProvider: PluginModelsProvider.Interface,\n private readonly listModelsUseCase: ListModelsUseCase.Interface,\n private readonly storageOperations: StorageOperations.Interface,\n private readonly tenantContext: TenantContext.Interface,\n private readonly cmsContext: CmsContext.Interface,\n private readonly modelFieldCompression: ModelFieldCompression.Interface,\n private readonly runtimeTenant: RuntimeTenant.Interface\n ) {}\n\n async execute(initialModel: CmsModel): Promise<Result<CmsModel, RepositoryAbstraction.Error>> {\n const model = this.runtimeTenant.assign(initialModel);\n try {\n const tenant = this.tenantContext.getTenant();\n\n // TODO: this will eventually become part of the Model domain object.\n const modelId = getModelId(model);\n model.modelId = modelId;\n\n // Validate modelId is allowed (not in disallowed list)\n try {\n validateModelIdAllowed({ model });\n } catch (error) {\n return Result.fail(\n new ModelValidationError({\n message: error.message,\n data: error.data\n })\n );\n }\n\n // Validate API name endings\n try {\n validateEndingAllowed({ model });\n } catch (error) {\n return Result.fail(\n new ModelValidationError({\n message: error.message,\n data: error.data\n })\n );\n }\n\n // Check for plugin model conflicts\n const pluginModels = await this.pluginModelsProvider.list(tenant.id);\n const pluginModelConflict = pluginModels.find(pm => {\n return pm.modelId === model.modelId;\n });\n\n if (pluginModelConflict) {\n return Result.fail(\n new ModelAlreadyExistsError({\n modelId,\n message: `Model \"${modelId}\" is already registered via a plugin.`\n })\n );\n }\n\n // Get all models for further validation\n const modelsResult = await this.listModelsUseCase.execute();\n\n if (modelsResult.isFail()) {\n return Result.fail(new ModelPersistenceError(modelsResult.error));\n }\n\n const models = modelsResult.value;\n\n try {\n /**\n * We need to check for the existence of:\n * - modelId\n * - singularApiName\n * - pluralApiName\n */\n for (const existingModel of models) {\n validateExistingModelId({\n existingModel,\n model\n });\n validateSingularApiName({\n existingModel,\n model\n });\n validatePluralApiName({\n existingModel,\n model\n });\n }\n\n await validateModelFields({\n models,\n model,\n context: this.cmsContext\n });\n } catch (error) {\n return Result.fail(\n new ModelValidationError({ message: error.message, data: error.data })\n );\n }\n\n // TODO: ideally, this will eventually be handled by the Model domain object\n model.tags = ensureTypeTag(model);\n\n const fields = await this.modelFieldCompression.compress(model.fields);\n\n // Persist to storage\n await this.storageOperations.models.create({\n model: {\n ...model,\n fields\n }\n });\n\n // Clear cache\n this.modelCache.clear();\n\n return Result.ok(model);\n } catch (error) {\n console.error(error, error.stack);\n return Result.fail(new ModelPersistenceError(error as Error));\n }\n }\n}\n\nexport const CreateModelRepository = RepositoryAbstraction.createImplementation({\n implementation: CreateModelRepositoryImpl,\n dependencies: [\n ModelCache,\n PluginModelsProvider,\n ListModelsUseCase,\n StorageOperations,\n TenantContext,\n CmsContext,\n ModelFieldCompression,\n RuntimeTenant\n ]\n});\n"],"names":["getModelId","model","modelId","name","value","isModelIdValid","camelCase","ModelValidationError","CreateModelRepositoryImpl","modelCache","pluginModelsProvider","listModelsUseCase","storageOperations","tenantContext","cmsContext","modelFieldCompression","runtimeTenant","initialModel","tenant","validateModelIdAllowed","error","Result","validateEndingAllowed","pluginModels","pluginModelConflict","pm","ModelAlreadyExistsError","modelsResult","ModelPersistenceError","models","existingModel","validateExistingModelId","validateSingularApiName","validatePluralApiName","validateModelFields","ensureTypeTag","fields","console","CreateModelRepository","RepositoryAbstraction","ModelCache","PluginModelsProvider","ListModelsUseCase","StorageOperations","TenantContext","CmsContext","ModelFieldCompression","RuntimeTenant"],"mappings":"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"}
|
|
@@ -69,9 +69,9 @@ class CreateModelUseCaseImpl {
|
|
|
69
69
|
return Result.fail(result.error);
|
|
70
70
|
}
|
|
71
71
|
await this.eventPublisher.publish(new ModelAfterCreateEvent({
|
|
72
|
-
model
|
|
72
|
+
model: result.value
|
|
73
73
|
}));
|
|
74
|
-
return Result.ok(
|
|
74
|
+
return Result.ok(result.value);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
const CreateModelUseCase_CreateModelUseCase = CreateModelUseCase.createImplementation({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/contentModel/CreateModel/CreateModelUseCase.js","sources":["../../../../src/features/contentModel/CreateModel/CreateModelUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { CreateModelUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { CreateModelRepository } from \"./abstractions.js\";\nimport { EventPublisher } from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport { ModelBeforeCreateEvent } from \"./events.js\";\nimport { ModelAfterCreateEvent } from \"./events.js\";\nimport { ModelCreateErrorEvent } from \"./events.js\";\nimport { AccessControl } from \"~/features/shared/abstractions.js\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { ModelNotAuthorizedError, ModelValidationError } from \"~/domain/contentModel/errors.js\";\nimport { createZodError } from \"@webiny/utils\";\nimport { removeUndefinedValues } from \"@webiny/utils\";\nimport { createModelCreateValidation } from \"~/domain/contentModel/schemas.js\";\nimport { assignModelDefaultFields } from \"~/crud/contentModel/defaultFields.js\";\nimport type { CmsModel } from \"~/types/index.js\";\nimport type { CmsModelCreateInput } from \"~/types/index.js\";\n\n/**\n * CreateModelUseCase - Core model creation orchestration.\n *\n * Responsibilities:\n * - Validate input (Zod)\n * - Create domain model object\n * - Assign default fields if requested\n * - Access control checks\n * - Publish before event\n * - Delegate to repository\n * - Publish after event or error event\n *\n * Note: This use case is decorated by CreateModelValidator which handles:\n * - ModelId generation\n * - ModelId allowed validation\n * - API name ending validation\n * - Field validation and plugin conflict checks\n */\nclass CreateModelUseCaseImpl implements UseCaseAbstraction.Interface {\n public constructor(\n private eventPublisher: EventPublisher.Interface,\n private repository: CreateModelRepository.Interface,\n private accessControl: AccessControl.Interface,\n private tenantContext: TenantContext.Interface,\n private identityContext: IdentityContext.Interface\n ) {}\n\n async execute(input: CmsModelCreateInput): Promise<Result<CmsModel, UseCaseAbstraction.Error>> {\n // Initial access control check\n const canAccess = await this.accessControl.canAccessModel({ rwd: \"w\" });\n if (!canAccess) {\n return Result.fail(new ModelNotAuthorizedError());\n }\n\n // Validate input\n const validationResult = await createModelCreateValidation().safeParseAsync(input);\n if (!validationResult.success) {\n const zodError = createZodError(validationResult.error);\n return Result.fail(new ModelValidationError(zodError.message));\n }\n\n // Extract defaultFields flag and remove it from data\n const { defaultFields, ...data } = removeUndefinedValues(validationResult.data);\n\n // Assign default fields if requested\n if (defaultFields) {\n assignModelDefaultFields(data);\n }\n\n // Create the domain model object\n const identity = this.identityContext.getIdentity();\n const tenant = this.tenantContext.getTenant();\n\n const model: CmsModel = {\n ...data,\n icon: data.icon ?? null,\n modelId: data.modelId ?? \"\", // Will be set by repository\n tenant: tenant.id,\n createdOn: new Date().toISOString(),\n savedOn: new Date().toISOString(),\n createdBy: {\n id: identity.id,\n displayName: identity.displayName,\n type: identity.type\n },\n description: data.description || \"\",\n // Fields and layout from data\n fields: data.fields || [],\n layout: data.layout || [],\n // Title/description/image field IDs\n titleFieldId: data.titleFieldId || \"\",\n descriptionFieldId: data.descriptionFieldId,\n imageFieldId: data.imageFieldId\n };\n\n // Access control check on the created model\n const canAccessModel = await this.accessControl.canAccessModel({ model, rwd: \"w\" });\n if (!canAccessModel) {\n return Result.fail(ModelNotAuthorizedError.fromModel(model));\n }\n\n // Publish before event\n await this.eventPublisher.publish(new ModelBeforeCreateEvent({ model, input: data }));\n\n // Persist via repository (repository will validate and set modelId)\n const result = await this.repository.execute(model);\n if (result.isFail()) {\n // Publish error event\n await this.eventPublisher.publish(\n new ModelCreateErrorEvent({\n input,\n model,\n error: result.error\n })\n );\n return Result.fail(result.error);\n }\n\n // Publish after event\n await this.eventPublisher.publish(new ModelAfterCreateEvent({
|
|
1
|
+
{"version":3,"file":"features/contentModel/CreateModel/CreateModelUseCase.js","sources":["../../../../src/features/contentModel/CreateModel/CreateModelUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { CreateModelUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { CreateModelRepository } from \"./abstractions.js\";\nimport { EventPublisher } from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport { ModelBeforeCreateEvent } from \"./events.js\";\nimport { ModelAfterCreateEvent } from \"./events.js\";\nimport { ModelCreateErrorEvent } from \"./events.js\";\nimport { AccessControl } from \"~/features/shared/abstractions.js\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { ModelNotAuthorizedError, ModelValidationError } from \"~/domain/contentModel/errors.js\";\nimport { createZodError } from \"@webiny/utils\";\nimport { removeUndefinedValues } from \"@webiny/utils\";\nimport { createModelCreateValidation } from \"~/domain/contentModel/schemas.js\";\nimport { assignModelDefaultFields } from \"~/crud/contentModel/defaultFields.js\";\nimport type { CmsModel } from \"~/types/index.js\";\nimport type { CmsModelCreateInput } from \"~/types/index.js\";\n\n/**\n * CreateModelUseCase - Core model creation orchestration.\n *\n * Responsibilities:\n * - Validate input (Zod)\n * - Create domain model object\n * - Assign default fields if requested\n * - Access control checks\n * - Publish before event\n * - Delegate to repository\n * - Publish after event or error event\n *\n * Note: This use case is decorated by CreateModelValidator which handles:\n * - ModelId generation\n * - ModelId allowed validation\n * - API name ending validation\n * - Field validation and plugin conflict checks\n */\nclass CreateModelUseCaseImpl implements UseCaseAbstraction.Interface {\n public constructor(\n private eventPublisher: EventPublisher.Interface,\n private repository: CreateModelRepository.Interface,\n private accessControl: AccessControl.Interface,\n private tenantContext: TenantContext.Interface,\n private identityContext: IdentityContext.Interface\n ) {}\n\n async execute(input: CmsModelCreateInput): Promise<Result<CmsModel, UseCaseAbstraction.Error>> {\n // Initial access control check\n const canAccess = await this.accessControl.canAccessModel({ rwd: \"w\" });\n if (!canAccess) {\n return Result.fail(new ModelNotAuthorizedError());\n }\n\n // Validate input\n const validationResult = await createModelCreateValidation().safeParseAsync(input);\n if (!validationResult.success) {\n const zodError = createZodError(validationResult.error);\n return Result.fail(new ModelValidationError(zodError.message));\n }\n\n // Extract defaultFields flag and remove it from data\n const { defaultFields, ...data } = removeUndefinedValues(validationResult.data);\n\n // Assign default fields if requested\n if (defaultFields) {\n assignModelDefaultFields(data);\n }\n\n // Create the domain model object\n const identity = this.identityContext.getIdentity();\n const tenant = this.tenantContext.getTenant();\n\n const model: CmsModel = {\n ...data,\n icon: data.icon ?? null,\n modelId: data.modelId ?? \"\", // Will be set by repository\n tenant: tenant.id,\n createdOn: new Date().toISOString(),\n savedOn: new Date().toISOString(),\n createdBy: {\n id: identity.id,\n displayName: identity.displayName,\n type: identity.type\n },\n description: data.description || \"\",\n // Fields and layout from data\n fields: data.fields || [],\n layout: data.layout || [],\n // Title/description/image field IDs\n titleFieldId: data.titleFieldId || \"\",\n descriptionFieldId: data.descriptionFieldId,\n imageFieldId: data.imageFieldId\n };\n\n // Access control check on the created model\n const canAccessModel = await this.accessControl.canAccessModel({ model, rwd: \"w\" });\n if (!canAccessModel) {\n return Result.fail(ModelNotAuthorizedError.fromModel(model));\n }\n\n // Publish before event\n await this.eventPublisher.publish(new ModelBeforeCreateEvent({ model, input: data }));\n\n // Persist via repository (repository will validate and set modelId)\n const result = await this.repository.execute(model);\n if (result.isFail()) {\n // Publish error event\n await this.eventPublisher.publish(\n new ModelCreateErrorEvent({\n input,\n model,\n error: result.error\n })\n );\n return Result.fail(result.error);\n }\n\n // Publish after event\n await this.eventPublisher.publish(\n new ModelAfterCreateEvent({\n model: result.value\n })\n );\n\n return Result.ok(result.value);\n }\n}\n\nexport const CreateModelUseCase = UseCaseAbstraction.createImplementation({\n implementation: CreateModelUseCaseImpl,\n dependencies: [\n EventPublisher,\n CreateModelRepository,\n AccessControl,\n TenantContext,\n IdentityContext\n ]\n});\n"],"names":["CreateModelUseCaseImpl","eventPublisher","repository","accessControl","tenantContext","identityContext","input","canAccess","Result","ModelNotAuthorizedError","validationResult","createModelCreateValidation","zodError","createZodError","ModelValidationError","defaultFields","data","removeUndefinedValues","assignModelDefaultFields","identity","tenant","model","Date","canAccessModel","ModelBeforeCreateEvent","result","ModelCreateErrorEvent","ModelAfterCreateEvent","CreateModelUseCase","UseCaseAbstraction","EventPublisher","CreateModelRepository","AccessControl","TenantContext","IdentityContext"],"mappings":";;;;;;;;;;;AAoCA,MAAMA;IACF,YACYC,cAAwC,EACxCC,UAA2C,EAC3CC,aAAsC,EACtCC,aAAsC,EACtCC,eAA0C,CACpD;aALUJ,cAAc,GAAdA;aACAC,UAAU,GAAVA;aACAC,aAAa,GAAbA;aACAC,aAAa,GAAbA;aACAC,eAAe,GAAfA;IACT;IAEH,MAAM,QAAQC,KAA0B,EAAuD;QAE3F,MAAMC,YAAY,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC;YAAE,KAAK;QAAI;QACrE,IAAI,CAACA,WACD,OAAOC,OAAO,IAAI,CAAC,IAAIC;QAI3B,MAAMC,mBAAmB,MAAMC,8BAA8B,cAAc,CAACL;QAC5E,IAAI,CAACI,iBAAiB,OAAO,EAAE;YAC3B,MAAME,WAAWC,eAAeH,iBAAiB,KAAK;YACtD,OAAOF,OAAO,IAAI,CAAC,IAAIM,qBAAqBF,SAAS,OAAO;QAChE;QAGA,MAAM,EAAEG,aAAa,EAAE,GAAGC,MAAM,GAAGC,sBAAsBP,iBAAiB,IAAI;QAG9E,IAAIK,eACAG,yBAAyBF;QAI7B,MAAMG,WAAW,IAAI,CAAC,eAAe,CAAC,WAAW;QACjD,MAAMC,SAAS,IAAI,CAAC,aAAa,CAAC,SAAS;QAE3C,MAAMC,QAAkB;YACpB,GAAGL,IAAI;YACP,MAAMA,KAAK,IAAI,IAAI;YACnB,SAASA,KAAK,OAAO,IAAI;YACzB,QAAQI,OAAO,EAAE;YACjB,WAAW,IAAIE,OAAO,WAAW;YACjC,SAAS,IAAIA,OAAO,WAAW;YAC/B,WAAW;gBACP,IAAIH,SAAS,EAAE;gBACf,aAAaA,SAAS,WAAW;gBACjC,MAAMA,SAAS,IAAI;YACvB;YACA,aAAaH,KAAK,WAAW,IAAI;YAEjC,QAAQA,KAAK,MAAM,IAAI,EAAE;YACzB,QAAQA,KAAK,MAAM,IAAI,EAAE;YAEzB,cAAcA,KAAK,YAAY,IAAI;YACnC,oBAAoBA,KAAK,kBAAkB;YAC3C,cAAcA,KAAK,YAAY;QACnC;QAGA,MAAMO,iBAAiB,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC;YAAEF;YAAO,KAAK;QAAI;QACjF,IAAI,CAACE,gBACD,OAAOf,OAAO,IAAI,CAACC,wBAAwB,SAAS,CAACY;QAIzD,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAIG,uBAAuB;YAAEH;YAAO,OAAOL;QAAK;QAGlF,MAAMS,SAAS,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAACJ;QAC7C,IAAII,OAAO,MAAM,IAAI;YAEjB,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAC7B,IAAIC,sBAAsB;gBACtBpB;gBACAe;gBACA,OAAOI,OAAO,KAAK;YACvB;YAEJ,OAAOjB,OAAO,IAAI,CAACiB,OAAO,KAAK;QACnC;QAGA,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAC7B,IAAIE,sBAAsB;YACtB,OAAOF,OAAO,KAAK;QACvB;QAGJ,OAAOjB,OAAO,EAAE,CAACiB,OAAO,KAAK;IACjC;AACJ;AAEO,MAAMG,wCAAqBC,mBAAAA,oBAAuC,CAAC;IACtE,gBAAgB7B;IAChB,cAAc;QACV8B;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
|
|
@@ -30,7 +30,7 @@ export declare namespace CreateModelUseCase {
|
|
|
30
30
|
* CreateModelRepository - Validates domain rules and persists a new model to storage.
|
|
31
31
|
*/
|
|
32
32
|
export interface ICreateModelRepository {
|
|
33
|
-
execute(model: CmsModel): Promise<Result<
|
|
33
|
+
execute(model: CmsModel): Promise<Result<CmsModel, RepositoryError>>;
|
|
34
34
|
}
|
|
35
35
|
export interface ICreateModelRepositoryErrors {
|
|
36
36
|
alreadyExists: ModelAlreadyExistsError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/contentModel/CreateModel/abstractions.js","sources":["../../../../src/features/contentModel/CreateModel/abstractions.ts"],"sourcesContent":["import { createAbstraction, Result } from \"@webiny/feature/api\";\nimport type { CmsModel, CmsModelCreateInput } from \"~/types/index.js\";\nimport {\n ModelAlreadyExistsError,\n ModelNotAuthorizedError,\n type ModelPersistenceError,\n type ModelSlugTakenError,\n type ModelValidationError\n} from \"~/domain/contentModel/errors.js\";\nimport {\n type GroupNotAuthorizedError,\n type GroupNotFoundError\n} from \"~/domain/contentModelGroup/errors.js\";\n\n/**\n * CreateModel Use Case\n */\nexport interface ICreateModelUseCase {\n execute(input: CmsModelCreateInput): Promise<Result<CmsModel, UseCaseError>>;\n}\n\nexport interface ICreateModelUseCaseErrors {\n notAuthorized: ModelNotAuthorizedError;\n validation: ModelValidationError;\n slugTaken: ModelSlugTakenError;\n alreadyExists: ModelAlreadyExistsError;\n persistence: ModelPersistenceError;\n groupNotFound: GroupNotFoundError; // Reused from Group domain\n groupNotAccessible: GroupNotAuthorizedError; // Reused from Group domain\n}\n\ntype UseCaseError = ICreateModelUseCaseErrors[keyof ICreateModelUseCaseErrors];\n\n/** Create a new content model. */\nexport const CreateModelUseCase = createAbstraction<ICreateModelUseCase>(\"CreateModelUseCase\");\n\nexport namespace CreateModelUseCase {\n export type Interface = ICreateModelUseCase;\n export type Input = CmsModelCreateInput;\n\n export type Error = UseCaseError;\n export type Return = Promise<Result<CmsModel, UseCaseError>>;\n}\n\n/**\n * CreateModelRepository - Validates domain rules and persists a new model to storage.\n */\nexport interface ICreateModelRepository {\n execute(model: CmsModel): Promise<Result<
|
|
1
|
+
{"version":3,"file":"features/contentModel/CreateModel/abstractions.js","sources":["../../../../src/features/contentModel/CreateModel/abstractions.ts"],"sourcesContent":["import { createAbstraction, Result } from \"@webiny/feature/api\";\nimport type { CmsModel, CmsModelCreateInput } from \"~/types/index.js\";\nimport {\n ModelAlreadyExistsError,\n ModelNotAuthorizedError,\n type ModelPersistenceError,\n type ModelSlugTakenError,\n type ModelValidationError\n} from \"~/domain/contentModel/errors.js\";\nimport {\n type GroupNotAuthorizedError,\n type GroupNotFoundError\n} from \"~/domain/contentModelGroup/errors.js\";\n\n/**\n * CreateModel Use Case\n */\nexport interface ICreateModelUseCase {\n execute(input: CmsModelCreateInput): Promise<Result<CmsModel, UseCaseError>>;\n}\n\nexport interface ICreateModelUseCaseErrors {\n notAuthorized: ModelNotAuthorizedError;\n validation: ModelValidationError;\n slugTaken: ModelSlugTakenError;\n alreadyExists: ModelAlreadyExistsError;\n persistence: ModelPersistenceError;\n groupNotFound: GroupNotFoundError; // Reused from Group domain\n groupNotAccessible: GroupNotAuthorizedError; // Reused from Group domain\n}\n\ntype UseCaseError = ICreateModelUseCaseErrors[keyof ICreateModelUseCaseErrors];\n\n/** Create a new content model. */\nexport const CreateModelUseCase = createAbstraction<ICreateModelUseCase>(\"CreateModelUseCase\");\n\nexport namespace CreateModelUseCase {\n export type Interface = ICreateModelUseCase;\n export type Input = CmsModelCreateInput;\n\n export type Error = UseCaseError;\n export type Return = Promise<Result<CmsModel, UseCaseError>>;\n}\n\n/**\n * CreateModelRepository - Validates domain rules and persists a new model to storage.\n */\nexport interface ICreateModelRepository {\n execute(model: CmsModel): Promise<Result<CmsModel, RepositoryError>>;\n}\n\nexport interface ICreateModelRepositoryErrors {\n alreadyExists: ModelAlreadyExistsError;\n validation: ModelValidationError;\n persistence: ModelPersistenceError;\n}\n\ntype RepositoryError = ICreateModelRepositoryErrors[keyof ICreateModelRepositoryErrors];\n\nexport const CreateModelRepository =\n createAbstraction<ICreateModelRepository>(\"CreateModelRepository\");\n\nexport namespace CreateModelRepository {\n export type Interface = ICreateModelRepository;\n export type Error = RepositoryError;\n}\n"],"names":["CreateModelUseCase","createAbstraction","CreateModelRepository"],"mappings":";AAkCO,MAAMA,qBAAqBC,kBAAuC;AAyBlE,MAAMC,wBACTD,kBAA0C"}
|
|
@@ -5,6 +5,7 @@ import { CmsContext, StorageOperations } from "../../../features/shared/abstract
|
|
|
5
5
|
import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
|
|
6
6
|
import type { CmsModel } from "../../../types/index.js";
|
|
7
7
|
import { ModelFieldCompression } from "../../../features/contentModel/ModelFieldCompression/index.js";
|
|
8
|
+
import { RuntimeTenant } from "../../../features/runtimeTenant/abstractions.js";
|
|
8
9
|
/**
|
|
9
10
|
* CreateModelFromRepository - Validates domain rules and persists cloned model.
|
|
10
11
|
*
|
|
@@ -27,8 +28,9 @@ declare class CreateModelFromRepositoryImpl implements RepositoryAbstraction.Int
|
|
|
27
28
|
private readonly tenantContext;
|
|
28
29
|
private readonly cmsContext;
|
|
29
30
|
private readonly modelFieldCompression;
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
private readonly runtimeTenant;
|
|
32
|
+
constructor(modelCache: ModelCache.Interface, pluginModelsProvider: PluginModelsProvider.Interface, modelsFetcher: ModelsFetcher.Interface, storageOperations: StorageOperations.Interface, tenantContext: TenantContext.Interface, cmsContext: CmsContext.Interface, modelFieldCompression: ModelFieldCompression.Interface, runtimeTenant: RuntimeTenant.Interface);
|
|
33
|
+
execute(initialModel: CmsModel): Promise<Result<CmsModel, RepositoryAbstraction.Error>>;
|
|
32
34
|
}
|
|
33
35
|
export declare const CreateModelFromRepository: typeof CreateModelFromRepositoryImpl & {
|
|
34
36
|
__abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").ICreateModelFromRepository>;
|