@strapi/content-type-builder 5.12.1 → 5.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/components/AllowedTypesSelect.js +78 -0
- package/dist/admin/components/AllowedTypesSelect.js.map +1 -0
- package/dist/admin/components/AllowedTypesSelect.mjs +76 -0
- package/dist/admin/components/AllowedTypesSelect.mjs.map +1 -0
- package/dist/admin/components/AttributeIcon.js +72 -0
- package/dist/admin/components/AttributeIcon.js.map +1 -0
- package/dist/admin/components/AttributeIcon.mjs +70 -0
- package/dist/admin/components/AttributeIcon.mjs.map +1 -0
- package/dist/admin/components/AttributeOptions/AttributeList.js +31 -0
- package/dist/admin/components/AttributeOptions/AttributeList.js.map +1 -0
- package/dist/admin/components/AttributeOptions/AttributeList.mjs +29 -0
- package/dist/admin/components/AttributeOptions/AttributeList.mjs.map +1 -0
- package/dist/admin/components/AttributeOptions/AttributeOption.js +92 -0
- package/dist/admin/components/AttributeOptions/AttributeOption.js.map +1 -0
- package/dist/admin/components/AttributeOptions/AttributeOption.mjs +90 -0
- package/dist/admin/components/AttributeOptions/AttributeOption.mjs.map +1 -0
- package/dist/admin/components/AttributeOptions/AttributeOptions.js +71 -0
- package/dist/admin/components/AttributeOptions/AttributeOptions.js.map +1 -0
- package/dist/admin/components/AttributeOptions/AttributeOptions.mjs +69 -0
- package/dist/admin/components/AttributeOptions/AttributeOptions.mjs.map +1 -0
- package/dist/admin/components/AttributeOptions/CustomFieldOption.js +58 -0
- package/dist/admin/components/AttributeOptions/CustomFieldOption.js.map +1 -0
- package/dist/admin/components/AttributeOptions/CustomFieldOption.mjs +56 -0
- package/dist/admin/components/AttributeOptions/CustomFieldOption.mjs.map +1 -0
- package/dist/admin/components/AttributeOptions/CustomFieldsList.js +54 -0
- package/dist/admin/components/AttributeOptions/CustomFieldsList.js.map +1 -0
- package/dist/admin/components/AttributeOptions/CustomFieldsList.mjs +52 -0
- package/dist/admin/components/AttributeOptions/CustomFieldsList.mjs.map +1 -0
- package/dist/admin/components/AttributeOptions/EmptyAttributes.js +123 -0
- package/dist/admin/components/AttributeOptions/EmptyAttributes.js.map +1 -0
- package/dist/admin/components/AttributeOptions/EmptyAttributes.mjs +101 -0
- package/dist/admin/components/AttributeOptions/EmptyAttributes.mjs.map +1 -0
- package/dist/admin/components/AttributeOptions/OptionBoxWrapper.js +19 -0
- package/dist/admin/components/AttributeOptions/OptionBoxWrapper.js.map +1 -0
- package/dist/admin/components/AttributeOptions/OptionBoxWrapper.mjs +17 -0
- package/dist/admin/components/AttributeOptions/OptionBoxWrapper.mjs.map +1 -0
- package/dist/admin/components/AutoReloadOverlayBlocker.js +212 -0
- package/dist/admin/components/AutoReloadOverlayBlocker.js.map +1 -0
- package/dist/admin/components/AutoReloadOverlayBlocker.mjs +190 -0
- package/dist/admin/components/AutoReloadOverlayBlocker.mjs.map +1 -0
- package/dist/admin/components/BooleanDefaultValueSelect.js +54 -0
- package/dist/admin/components/BooleanDefaultValueSelect.js.map +1 -0
- package/dist/admin/components/BooleanDefaultValueSelect.mjs +52 -0
- package/dist/admin/components/BooleanDefaultValueSelect.mjs.map +1 -0
- package/dist/admin/components/BooleanRadioGroup.js +27 -0
- package/dist/admin/components/BooleanRadioGroup.js.map +1 -0
- package/dist/admin/components/BooleanRadioGroup.mjs +25 -0
- package/dist/admin/components/BooleanRadioGroup.mjs.map +1 -0
- package/dist/admin/components/BoxWrapper.js +44 -0
- package/dist/admin/components/BoxWrapper.js.map +1 -0
- package/dist/admin/components/BoxWrapper.mjs +42 -0
- package/dist/admin/components/BoxWrapper.mjs.map +1 -0
- package/dist/admin/components/CheckboxWithNumberField.js +86 -0
- package/dist/admin/components/CheckboxWithNumberField.js.map +1 -0
- package/dist/admin/components/CheckboxWithNumberField.mjs +84 -0
- package/dist/admin/components/CheckboxWithNumberField.mjs.map +1 -0
- package/dist/admin/components/ComponentCard/ComponentCard.js +112 -0
- package/dist/admin/components/ComponentCard/ComponentCard.js.map +1 -0
- package/dist/admin/components/ComponentCard/ComponentCard.mjs +110 -0
- package/dist/admin/components/ComponentCard/ComponentCard.mjs.map +1 -0
- package/dist/admin/components/ComponentCard/ComponentIcon/ComponentIcon.js +24 -0
- package/dist/admin/components/ComponentCard/ComponentIcon/ComponentIcon.js.map +1 -0
- package/dist/admin/components/ComponentCard/ComponentIcon/ComponentIcon.mjs +22 -0
- package/dist/admin/components/ComponentCard/ComponentIcon/ComponentIcon.mjs.map +1 -0
- package/dist/admin/components/ComponentList.js +40 -0
- package/dist/admin/components/ComponentList.js.map +1 -0
- package/dist/admin/components/ComponentList.mjs +38 -0
- package/dist/admin/components/ComponentList.mjs.map +1 -0
- package/dist/admin/components/ContentTypeBuilderNav/ContentTypeBuilderNav.js +108 -0
- package/dist/admin/components/ContentTypeBuilderNav/ContentTypeBuilderNav.js.map +1 -0
- package/dist/admin/components/ContentTypeBuilderNav/ContentTypeBuilderNav.mjs +106 -0
- package/dist/admin/components/ContentTypeBuilderNav/ContentTypeBuilderNav.mjs.map +1 -0
- package/dist/admin/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.js +179 -0
- package/dist/admin/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.js.map +1 -0
- package/dist/admin/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.mjs +177 -0
- package/dist/admin/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.mjs.map +1 -0
- package/dist/admin/components/ContentTypeRadioGroup.js +29 -0
- package/dist/admin/components/ContentTypeRadioGroup.js.map +1 -0
- package/dist/admin/components/ContentTypeRadioGroup.mjs +27 -0
- package/dist/admin/components/ContentTypeRadioGroup.mjs.map +1 -0
- package/dist/admin/components/CustomRadioGroup/CustomRadioGroup.js +79 -0
- package/dist/admin/components/CustomRadioGroup/CustomRadioGroup.js.map +1 -0
- package/dist/admin/components/CustomRadioGroup/CustomRadioGroup.mjs +77 -0
- package/dist/admin/components/CustomRadioGroup/CustomRadioGroup.mjs.map +1 -0
- package/dist/admin/components/CustomRadioGroup/Styles.js +77 -0
- package/dist/admin/components/CustomRadioGroup/Styles.js.map +1 -0
- package/dist/admin/components/CustomRadioGroup/Styles.mjs +75 -0
- package/dist/admin/components/CustomRadioGroup/Styles.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/DataManagerProvider.js +520 -0
- package/dist/admin/components/DataManagerProvider/DataManagerProvider.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/DataManagerProvider.mjs +518 -0
- package/dist/admin/components/DataManagerProvider/DataManagerProvider.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/reducer.js +583 -0
- package/dist/admin/components/DataManagerProvider/reducer.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/reducer.mjs +579 -0
- package/dist/admin/components/DataManagerProvider/reducer.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/selectors.js +20 -0
- package/dist/admin/components/DataManagerProvider/selectors.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/selectors.mjs +17 -0
- package/dist/admin/components/DataManagerProvider/selectors.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/cleanData.js +126 -0
- package/dist/admin/components/DataManagerProvider/utils/cleanData.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/cleanData.mjs +120 -0
- package/dist/admin/components/DataManagerProvider/utils/cleanData.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/createDataObject.js +9 -0
- package/dist/admin/components/DataManagerProvider/utils/createDataObject.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/createDataObject.mjs +7 -0
- package/dist/admin/components/DataManagerProvider/utils/createDataObject.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/createModifiedDataSchema.js +20 -0
- package/dist/admin/components/DataManagerProvider/utils/createModifiedDataSchema.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/createModifiedDataSchema.mjs +18 -0
- package/dist/admin/components/DataManagerProvider/utils/createModifiedDataSchema.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/formatSchemas.js +30 -0
- package/dist/admin/components/DataManagerProvider/utils/formatSchemas.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/formatSchemas.mjs +27 -0
- package/dist/admin/components/DataManagerProvider/utils/formatSchemas.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveComponentsFromSchema.js +46 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveComponentsFromSchema.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveComponentsFromSchema.mjs +44 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveComponentsFromSchema.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveComponentsThatHaveComponents.js +38 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveComponentsThatHaveComponents.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveComponentsThatHaveComponents.mjs +35 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveComponentsThatHaveComponents.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveNestedComponents.js +45 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveNestedComponents.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveNestedComponents.mjs +43 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveNestedComponents.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveSpecificInfoFromComponents.js +17 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveSpecificInfoFromComponents.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveSpecificInfoFromComponents.mjs +15 -0
- package/dist/admin/components/DataManagerProvider/utils/retrieveSpecificInfoFromComponents.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/serverRestartWatcher.js +37 -0
- package/dist/admin/components/DataManagerProvider/utils/serverRestartWatcher.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/serverRestartWatcher.mjs +35 -0
- package/dist/admin/components/DataManagerProvider/utils/serverRestartWatcher.mjs.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/validateSchema.js +9 -0
- package/dist/admin/components/DataManagerProvider/utils/validateSchema.js.map +1 -0
- package/dist/admin/components/DataManagerProvider/utils/validateSchema.mjs +7 -0
- package/dist/admin/components/DataManagerProvider/utils/validateSchema.mjs.map +1 -0
- package/dist/admin/components/DisplayedType.js +48 -0
- package/dist/admin/components/DisplayedType.js.map +1 -0
- package/dist/admin/components/DisplayedType.mjs +46 -0
- package/dist/admin/components/DisplayedType.mjs.map +1 -0
- package/dist/admin/components/DraftAndPublishToggle.js +86 -0
- package/dist/admin/components/DraftAndPublishToggle.js.map +1 -0
- package/dist/admin/components/DraftAndPublishToggle.mjs +84 -0
- package/dist/admin/components/DraftAndPublishToggle.mjs.map +1 -0
- package/dist/admin/components/DynamicZoneList.js +139 -0
- package/dist/admin/components/DynamicZoneList.js.map +1 -0
- package/dist/admin/components/DynamicZoneList.mjs +137 -0
- package/dist/admin/components/DynamicZoneList.mjs.map +1 -0
- package/dist/admin/components/FormModal/FormModal.js +931 -0
- package/dist/admin/components/FormModal/FormModal.js.map +1 -0
- package/dist/admin/components/FormModal/FormModal.mjs +910 -0
- package/dist/admin/components/FormModal/FormModal.mjs.map +1 -0
- package/dist/admin/components/FormModal/attributes/advancedForm.js +471 -0
- package/dist/admin/components/FormModal/attributes/advancedForm.js.map +1 -0
- package/dist/admin/components/FormModal/attributes/advancedForm.mjs +469 -0
- package/dist/admin/components/FormModal/attributes/advancedForm.mjs.map +1 -0
- package/dist/admin/components/FormModal/attributes/attributeOptions.js +97 -0
- package/dist/admin/components/FormModal/attributes/attributeOptions.js.map +1 -0
- package/dist/admin/components/FormModal/attributes/attributeOptions.mjs +95 -0
- package/dist/admin/components/FormModal/attributes/attributeOptions.mjs.map +1 -0
- package/dist/admin/components/FormModal/attributes/baseForm.js +482 -0
- package/dist/admin/components/FormModal/attributes/baseForm.js.map +1 -0
- package/dist/admin/components/FormModal/attributes/baseForm.mjs +480 -0
- package/dist/admin/components/FormModal/attributes/baseForm.mjs.map +1 -0
- package/dist/admin/components/FormModal/attributes/commonBaseForm.js +17 -0
- package/dist/admin/components/FormModal/attributes/commonBaseForm.js.map +1 -0
- package/dist/admin/components/FormModal/attributes/commonBaseForm.mjs +15 -0
- package/dist/admin/components/FormModal/attributes/commonBaseForm.mjs.map +1 -0
- package/dist/admin/components/FormModal/attributes/form.js +12 -0
- package/dist/admin/components/FormModal/attributes/form.js.map +1 -0
- package/dist/admin/components/FormModal/attributes/form.mjs +10 -0
- package/dist/admin/components/FormModal/attributes/form.mjs.map +1 -0
- package/dist/admin/components/FormModal/attributes/nameField.js +19 -0
- package/dist/admin/components/FormModal/attributes/nameField.js.map +1 -0
- package/dist/admin/components/FormModal/attributes/nameField.mjs +17 -0
- package/dist/admin/components/FormModal/attributes/nameField.mjs.map +1 -0
- package/dist/admin/components/FormModal/attributes/types.js +305 -0
- package/dist/admin/components/FormModal/attributes/types.js.map +1 -0
- package/dist/admin/components/FormModal/attributes/types.mjs +284 -0
- package/dist/admin/components/FormModal/attributes/types.mjs.map +1 -0
- package/dist/admin/components/FormModal/attributes/validation/common.js +129 -0
- package/dist/admin/components/FormModal/attributes/validation/common.js.map +1 -0
- package/dist/admin/components/FormModal/attributes/validation/common.mjs +103 -0
- package/dist/admin/components/FormModal/attributes/validation/common.mjs.map +1 -0
- package/dist/admin/components/FormModal/category/createCategorySchema.js +43 -0
- package/dist/admin/components/FormModal/category/createCategorySchema.js.map +1 -0
- package/dist/admin/components/FormModal/category/createCategorySchema.mjs +22 -0
- package/dist/admin/components/FormModal/category/createCategorySchema.mjs.map +1 -0
- package/dist/admin/components/FormModal/category/form.js +34 -0
- package/dist/admin/components/FormModal/category/form.js.map +1 -0
- package/dist/admin/components/FormModal/category/form.mjs +32 -0
- package/dist/admin/components/FormModal/category/form.mjs.map +1 -0
- package/dist/admin/components/FormModal/category/regex.js +6 -0
- package/dist/admin/components/FormModal/category/regex.js.map +1 -0
- package/dist/admin/components/FormModal/category/regex.mjs +4 -0
- package/dist/admin/components/FormModal/category/regex.mjs.map +1 -0
- package/dist/admin/components/FormModal/component/componentField.js +40 -0
- package/dist/admin/components/FormModal/component/componentField.js.map +1 -0
- package/dist/admin/components/FormModal/component/componentField.mjs +38 -0
- package/dist/admin/components/FormModal/component/componentField.mjs.map +1 -0
- package/dist/admin/components/FormModal/component/componentForm.js +53 -0
- package/dist/admin/components/FormModal/component/componentForm.js.map +1 -0
- package/dist/admin/components/FormModal/component/componentForm.mjs +51 -0
- package/dist/admin/components/FormModal/component/componentForm.mjs.map +1 -0
- package/dist/admin/components/FormModal/component/createComponentSchema.js +65 -0
- package/dist/admin/components/FormModal/component/createComponentSchema.js.map +1 -0
- package/dist/admin/components/FormModal/component/createComponentSchema.mjs +44 -0
- package/dist/admin/components/FormModal/component/createComponentSchema.mjs.map +1 -0
- package/dist/admin/components/FormModal/contentType/contentTypeForm.js +169 -0
- package/dist/admin/components/FormModal/contentType/contentTypeForm.js.map +1 -0
- package/dist/admin/components/FormModal/contentType/contentTypeForm.mjs +167 -0
- package/dist/admin/components/FormModal/contentType/contentTypeForm.mjs.map +1 -0
- package/dist/admin/components/FormModal/contentType/createContentTypeSchema.js +170 -0
- package/dist/admin/components/FormModal/contentType/createContentTypeSchema.js.map +1 -0
- package/dist/admin/components/FormModal/contentType/createContentTypeSchema.mjs +149 -0
- package/dist/admin/components/FormModal/contentType/createContentTypeSchema.mjs.map +1 -0
- package/dist/admin/components/FormModal/dynamiczoneForm.js +68 -0
- package/dist/admin/components/FormModal/dynamiczoneForm.js.map +1 -0
- package/dist/admin/components/FormModal/dynamiczoneForm.mjs +66 -0
- package/dist/admin/components/FormModal/dynamiczoneForm.mjs.map +1 -0
- package/dist/admin/components/FormModal/forms/forms.js +275 -0
- package/dist/admin/components/FormModal/forms/forms.js.map +1 -0
- package/dist/admin/components/FormModal/forms/forms.mjs +273 -0
- package/dist/admin/components/FormModal/forms/forms.mjs.map +1 -0
- package/dist/admin/components/FormModal/forms/utils/addItemsToFormSection.js +21 -0
- package/dist/admin/components/FormModal/forms/utils/addItemsToFormSection.js.map +1 -0
- package/dist/admin/components/FormModal/forms/utils/addItemsToFormSection.mjs +19 -0
- package/dist/admin/components/FormModal/forms/utils/addItemsToFormSection.mjs.map +1 -0
- package/dist/admin/components/FormModal/forms/utils/createCollectionName.js +13 -0
- package/dist/admin/components/FormModal/forms/utils/createCollectionName.js.map +1 -0
- package/dist/admin/components/FormModal/forms/utils/createCollectionName.mjs +11 -0
- package/dist/admin/components/FormModal/forms/utils/createCollectionName.mjs.map +1 -0
- package/dist/admin/components/FormModal/forms/utils/getUsedAttributeNames.js +10 -0
- package/dist/admin/components/FormModal/forms/utils/getUsedAttributeNames.js.map +1 -0
- package/dist/admin/components/FormModal/forms/utils/getUsedAttributeNames.mjs +8 -0
- package/dist/admin/components/FormModal/forms/utils/getUsedAttributeNames.mjs.map +1 -0
- package/dist/admin/components/FormModal/reducer.js +327 -0
- package/dist/admin/components/FormModal/reducer.js.map +1 -0
- package/dist/admin/components/FormModal/reducer.mjs +323 -0
- package/dist/admin/components/FormModal/reducer.mjs.map +1 -0
- package/dist/admin/components/FormModal/selectors.js +20 -0
- package/dist/admin/components/FormModal/selectors.js.map +1 -0
- package/dist/admin/components/FormModal/selectors.mjs +17 -0
- package/dist/admin/components/FormModal/selectors.mjs.map +1 -0
- package/dist/admin/components/FormModal/utils/canEditContentType.js +32 -0
- package/dist/admin/components/FormModal/utils/canEditContentType.js.map +1 -0
- package/dist/admin/components/FormModal/utils/canEditContentType.mjs +30 -0
- package/dist/admin/components/FormModal/utils/canEditContentType.mjs.map +1 -0
- package/dist/admin/components/FormModal/utils/createUid.js +16 -0
- package/dist/admin/components/FormModal/utils/createUid.js.map +1 -0
- package/dist/admin/components/FormModal/utils/createUid.mjs +13 -0
- package/dist/admin/components/FormModal/utils/createUid.mjs.map +1 -0
- package/dist/admin/components/FormModal/utils/customFieldDefaultOptionsReducer.js +18 -0
- package/dist/admin/components/FormModal/utils/customFieldDefaultOptionsReducer.js.map +1 -0
- package/dist/admin/components/FormModal/utils/customFieldDefaultOptionsReducer.mjs +16 -0
- package/dist/admin/components/FormModal/utils/customFieldDefaultOptionsReducer.mjs.map +1 -0
- package/dist/admin/components/FormModal/utils/getAttributesToDisplay.js +56 -0
- package/dist/admin/components/FormModal/utils/getAttributesToDisplay.js.map +1 -0
- package/dist/admin/components/FormModal/utils/getAttributesToDisplay.mjs +54 -0
- package/dist/admin/components/FormModal/utils/getAttributesToDisplay.mjs.map +1 -0
- package/dist/admin/components/FormModal/utils/getFormInputNames.js +17 -0
- package/dist/admin/components/FormModal/utils/getFormInputNames.js.map +1 -0
- package/dist/admin/components/FormModal/utils/getFormInputNames.mjs +15 -0
- package/dist/admin/components/FormModal/utils/getFormInputNames.mjs.map +1 -0
- package/dist/admin/components/FormModal/utils/relations.js +15 -0
- package/dist/admin/components/FormModal/utils/relations.js.map +1 -0
- package/dist/admin/components/FormModal/utils/relations.mjs +12 -0
- package/dist/admin/components/FormModal/utils/relations.mjs.map +1 -0
- package/dist/admin/components/FormModalEndActions.js +322 -0
- package/dist/admin/components/FormModalEndActions.js.map +1 -0
- package/dist/admin/components/FormModalEndActions.mjs +320 -0
- package/dist/admin/components/FormModalEndActions.mjs.map +1 -0
- package/dist/admin/components/FormModalHeader.js +150 -0
- package/dist/admin/components/FormModalHeader.js.map +1 -0
- package/dist/admin/components/FormModalHeader.mjs +148 -0
- package/dist/admin/components/FormModalHeader.mjs.map +1 -0
- package/dist/admin/components/FormModalNavigationProvider/FormModalNavigationProvider.js +228 -0
- package/dist/admin/components/FormModalNavigationProvider/FormModalNavigationProvider.js.map +1 -0
- package/dist/admin/components/FormModalNavigationProvider/FormModalNavigationProvider.mjs +207 -0
- package/dist/admin/components/FormModalNavigationProvider/FormModalNavigationProvider.mjs.map +1 -0
- package/dist/admin/components/FormModalNavigationProvider/constants.js +21 -0
- package/dist/admin/components/FormModalNavigationProvider/constants.js.map +1 -0
- package/dist/admin/components/FormModalNavigationProvider/constants.mjs +19 -0
- package/dist/admin/components/FormModalNavigationProvider/constants.mjs.map +1 -0
- package/dist/admin/components/FormModalSubHeader.js +70 -0
- package/dist/admin/components/FormModalSubHeader.js.map +1 -0
- package/dist/admin/components/FormModalSubHeader.mjs +67 -0
- package/dist/admin/components/FormModalSubHeader.mjs.map +1 -0
- package/dist/admin/components/GenericInputs.js +529 -0
- package/dist/admin/components/GenericInputs.js.map +1 -0
- package/dist/admin/components/GenericInputs.mjs +508 -0
- package/dist/admin/components/GenericInputs.mjs.map +1 -0
- package/dist/admin/components/IconPicker/IconPicker.js +196 -0
- package/dist/admin/components/IconPicker/IconPicker.js.map +1 -0
- package/dist/admin/components/IconPicker/IconPicker.mjs +194 -0
- package/dist/admin/components/IconPicker/IconPicker.mjs.map +1 -0
- package/dist/admin/components/IconPicker/constants.js +155 -0
- package/dist/admin/components/IconPicker/constants.js.map +1 -0
- package/dist/admin/components/IconPicker/constants.mjs +133 -0
- package/dist/admin/components/IconPicker/constants.mjs.map +1 -0
- package/dist/admin/components/List.js +243 -0
- package/dist/admin/components/List.js.map +1 -0
- package/dist/admin/components/List.mjs +241 -0
- package/dist/admin/components/List.mjs.map +1 -0
- package/dist/admin/components/ListRow.js +164 -0
- package/dist/admin/components/ListRow.js.map +1 -0
- package/dist/admin/components/ListRow.mjs +161 -0
- package/dist/admin/components/ListRow.mjs.map +1 -0
- package/dist/admin/components/NestedFooter.js +62 -0
- package/dist/admin/components/NestedFooter.js.map +1 -0
- package/dist/admin/components/NestedFooter.mjs +60 -0
- package/dist/admin/components/NestedFooter.mjs.map +1 -0
- package/dist/admin/components/PluralName.js +74 -0
- package/dist/admin/components/PluralName.js.map +1 -0
- package/dist/admin/components/PluralName.mjs +72 -0
- package/dist/admin/components/PluralName.mjs.map +1 -0
- package/dist/admin/components/Relation/Relation.js +47 -0
- package/dist/admin/components/Relation/Relation.js.map +1 -0
- package/dist/admin/components/Relation/Relation.mjs +45 -0
- package/dist/admin/components/Relation/Relation.mjs.map +1 -0
- package/dist/admin/components/Relation/RelationField/RelationField.js +52 -0
- package/dist/admin/components/Relation/RelationField/RelationField.js.map +1 -0
- package/dist/admin/components/Relation/RelationField/RelationField.mjs +50 -0
- package/dist/admin/components/Relation/RelationField/RelationField.mjs.map +1 -0
- package/dist/admin/components/Relation/RelationField/RelationTargetPicker/RelationTargetPicker.js +74 -0
- package/dist/admin/components/Relation/RelationField/RelationTargetPicker/RelationTargetPicker.js.map +1 -0
- package/dist/admin/components/Relation/RelationField/RelationTargetPicker/RelationTargetPicker.mjs +72 -0
- package/dist/admin/components/Relation/RelationField/RelationTargetPicker/RelationTargetPicker.mjs.map +1 -0
- package/dist/admin/components/Relation/RelationNaturePicker/Components.js +49 -0
- package/dist/admin/components/Relation/RelationNaturePicker/Components.js.map +1 -0
- package/dist/admin/components/Relation/RelationNaturePicker/Components.mjs +45 -0
- package/dist/admin/components/Relation/RelationNaturePicker/Components.mjs.map +1 -0
- package/dist/admin/components/Relation/RelationNaturePicker/RelationNaturePicker.js +149 -0
- package/dist/admin/components/Relation/RelationNaturePicker/RelationNaturePicker.js.map +1 -0
- package/dist/admin/components/Relation/RelationNaturePicker/RelationNaturePicker.mjs +147 -0
- package/dist/admin/components/Relation/RelationNaturePicker/RelationNaturePicker.mjs.map +1 -0
- package/dist/admin/components/SelectCategory.js +60 -0
- package/dist/admin/components/SelectCategory.js.map +1 -0
- package/dist/admin/components/SelectCategory.mjs +58 -0
- package/dist/admin/components/SelectCategory.mjs.map +1 -0
- package/dist/admin/components/SelectComponent.js +90 -0
- package/dist/admin/components/SelectComponent.js.map +1 -0
- package/dist/admin/components/SelectComponent.mjs +88 -0
- package/dist/admin/components/SelectComponent.mjs.map +1 -0
- package/dist/admin/components/SelectComponents.js +70 -0
- package/dist/admin/components/SelectComponents.js.map +1 -0
- package/dist/admin/components/SelectComponents.mjs +68 -0
- package/dist/admin/components/SelectComponents.mjs.map +1 -0
- package/dist/admin/components/SelectDateType.js +62 -0
- package/dist/admin/components/SelectDateType.js.map +1 -0
- package/dist/admin/components/SelectDateType.mjs +60 -0
- package/dist/admin/components/SelectDateType.mjs.map +1 -0
- package/dist/admin/components/SelectNumber.js +111 -0
- package/dist/admin/components/SelectNumber.js.map +1 -0
- package/dist/admin/components/SelectNumber.mjs +109 -0
- package/dist/admin/components/SelectNumber.mjs.map +1 -0
- package/dist/admin/components/SingularName.js +63 -0
- package/dist/admin/components/SingularName.js.map +1 -0
- package/dist/admin/components/SingularName.mjs +61 -0
- package/dist/admin/components/SingularName.mjs.map +1 -0
- package/dist/admin/components/TabForm.js +81 -0
- package/dist/admin/components/TabForm.js.map +1 -0
- package/dist/admin/components/TabForm.mjs +79 -0
- package/dist/admin/components/TabForm.mjs.map +1 -0
- package/dist/admin/components/TextareaEnum.js +58 -0
- package/dist/admin/components/TextareaEnum.js.map +1 -0
- package/dist/admin/components/TextareaEnum.mjs +56 -0
- package/dist/admin/components/TextareaEnum.mjs.map +1 -0
- package/dist/admin/components/Tr.js +48 -0
- package/dist/admin/components/Tr.js.map +1 -0
- package/dist/admin/components/Tr.mjs +46 -0
- package/dist/admin/components/Tr.mjs.map +1 -0
- package/dist/admin/components/UpperFirst.js +11 -0
- package/dist/admin/components/UpperFirst.js.map +1 -0
- package/dist/admin/components/UpperFirst.mjs +9 -0
- package/dist/admin/components/UpperFirst.mjs.map +1 -0
- package/dist/admin/constants.js +19 -0
- package/dist/admin/constants.js.map +1 -0
- package/dist/admin/constants.mjs +16 -0
- package/dist/admin/constants.mjs.map +1 -0
- package/dist/admin/contexts/DataManagerContext.js +9 -0
- package/dist/admin/contexts/DataManagerContext.js.map +1 -0
- package/dist/admin/contexts/DataManagerContext.mjs +7 -0
- package/dist/admin/contexts/DataManagerContext.mjs.map +1 -0
- package/dist/admin/contexts/FormModalNavigationContext.js +28 -0
- package/dist/admin/contexts/FormModalNavigationContext.js.map +1 -0
- package/dist/admin/contexts/FormModalNavigationContext.mjs +7 -0
- package/dist/admin/contexts/FormModalNavigationContext.mjs.map +1 -0
- package/dist/admin/hooks/useDataManager.js +9 -0
- package/dist/admin/hooks/useDataManager.js.map +1 -0
- package/dist/admin/hooks/useDataManager.mjs +7 -0
- package/dist/admin/hooks/useDataManager.mjs.map +1 -0
- package/dist/admin/hooks/useFormModalNavigation.js +9 -0
- package/dist/admin/hooks/useFormModalNavigation.js.map +1 -0
- package/dist/admin/hooks/useFormModalNavigation.mjs +7 -0
- package/dist/admin/hooks/useFormModalNavigation.mjs.map +1 -0
- package/dist/admin/icons/Curve.js +46 -0
- package/dist/admin/icons/Curve.js.map +1 -0
- package/dist/admin/icons/Curve.mjs +44 -0
- package/dist/admin/icons/Curve.mjs.map +1 -0
- package/dist/admin/index.js +86 -20
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +85 -17
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/pages/App/index.js +66 -0
- package/dist/admin/pages/App/index.js.map +1 -0
- package/dist/admin/pages/App/index.mjs +62 -0
- package/dist/admin/pages/App/index.mjs.map +1 -0
- package/dist/admin/pages/ListView/LinkToCMSettingsView.js +81 -0
- package/dist/admin/pages/ListView/LinkToCMSettingsView.js.map +1 -0
- package/dist/admin/pages/ListView/LinkToCMSettingsView.mjs +79 -0
- package/dist/admin/pages/ListView/LinkToCMSettingsView.mjs.map +1 -0
- package/dist/admin/pages/ListView/ListView.js +218 -0
- package/dist/admin/pages/ListView/ListView.js.map +1 -0
- package/dist/admin/pages/ListView/ListView.mjs +216 -0
- package/dist/admin/pages/ListView/ListView.mjs.map +1 -0
- package/dist/admin/pluginId.js +6 -0
- package/dist/admin/pluginId.js.map +1 -0
- package/dist/admin/pluginId.mjs +4 -0
- package/dist/admin/pluginId.mjs.map +1 -0
- package/dist/admin/reducers.js +13 -0
- package/dist/admin/reducers.js.map +1 -0
- package/dist/admin/reducers.mjs +11 -0
- package/dist/admin/reducers.mjs.map +1 -0
- package/dist/admin/{chunks/ar-Df0f0-PT.js → translations/ar.json.js} +3 -1
- package/dist/admin/translations/ar.json.js.map +1 -0
- package/dist/admin/{chunks/ar-sRW9VFC-.mjs → translations/ar.json.mjs} +1 -1
- package/dist/admin/translations/ar.json.mjs.map +1 -0
- package/dist/admin/{chunks/cs-DeTwqc7p.js → translations/cs.json.js} +3 -1
- package/dist/admin/translations/cs.json.js.map +1 -0
- package/dist/admin/{chunks/cs-BpQ26jiq.mjs → translations/cs.json.mjs} +1 -1
- package/dist/admin/translations/cs.json.mjs.map +1 -0
- package/dist/admin/{chunks/de-BJkS06jF.js → translations/de.json.js} +3 -1
- package/dist/admin/translations/de.json.js.map +1 -0
- package/dist/admin/{chunks/de-DSxx5_x-.mjs → translations/de.json.mjs} +1 -1
- package/dist/admin/translations/de.json.mjs.map +1 -0
- package/dist/admin/{chunks/dk-CGm-qVH7.js → translations/dk.json.js} +3 -1
- package/dist/admin/translations/dk.json.js.map +1 -0
- package/dist/admin/{chunks/dk-BnjVZ7A_.mjs → translations/dk.json.mjs} +1 -1
- package/dist/admin/translations/dk.json.mjs.map +1 -0
- package/dist/admin/{chunks/en-BJUu34b0.js → translations/en.json.js} +3 -1
- package/dist/admin/translations/en.json.js.map +1 -0
- package/dist/admin/{chunks/en-Bhut8Yay.mjs → translations/en.json.mjs} +1 -1
- package/dist/admin/translations/en.json.mjs.map +1 -0
- package/dist/admin/{chunks/es-J8kvHlNy.js → translations/es.json.js} +3 -1
- package/dist/admin/translations/es.json.js.map +1 -0
- package/dist/admin/{chunks/es-DG8g9igJ.mjs → translations/es.json.mjs} +1 -1
- package/dist/admin/translations/es.json.mjs.map +1 -0
- package/dist/admin/{chunks/fr-C6y35iY7.js → translations/fr.json.js} +3 -1
- package/dist/admin/translations/fr.json.js.map +1 -0
- package/dist/admin/{chunks/fr-UpV34MHY.mjs → translations/fr.json.mjs} +1 -1
- package/dist/admin/translations/fr.json.mjs.map +1 -0
- package/dist/admin/{chunks/id-BvxV6wLP.js → translations/id.json.js} +3 -1
- package/dist/admin/translations/id.json.js.map +1 -0
- package/dist/admin/{chunks/id-BWM18ljw.mjs → translations/id.json.mjs} +1 -1
- package/dist/admin/translations/id.json.mjs.map +1 -0
- package/dist/admin/{chunks/it-C_IgFU-G.js → translations/it.json.js} +3 -1
- package/dist/admin/translations/it.json.js.map +1 -0
- package/dist/admin/{chunks/it-1_vd9gV4.mjs → translations/it.json.mjs} +1 -1
- package/dist/admin/{chunks/ms-C3s4kxq6.mjs.map → translations/it.json.mjs.map} +1 -1
- package/dist/admin/{chunks/ja-CWo4Qqq6.js → translations/ja.json.js} +3 -1
- package/dist/admin/translations/ja.json.js.map +1 -0
- package/dist/admin/{chunks/ja-Cx23a2Ui.mjs → translations/ja.json.mjs} +1 -1
- package/dist/admin/translations/ja.json.mjs.map +1 -0
- package/dist/admin/{chunks/ko-BsByJNEl.js → translations/ko.json.js} +3 -1
- package/dist/admin/translations/ko.json.js.map +1 -0
- package/dist/admin/{chunks/ko-DC7paEx5.mjs → translations/ko.json.mjs} +1 -1
- package/dist/admin/translations/ko.json.mjs.map +1 -0
- package/dist/admin/{chunks/ms-DPTzS7SH.js → translations/ms.json.js} +3 -1
- package/dist/admin/translations/ms.json.js.map +1 -0
- package/dist/admin/{chunks/ms-C3s4kxq6.mjs → translations/ms.json.mjs} +1 -1
- package/dist/admin/translations/ms.json.mjs.map +1 -0
- package/dist/admin/{chunks/nl-db29QMOx.js → translations/nl.json.js} +3 -1
- package/dist/admin/translations/nl.json.js.map +1 -0
- package/dist/admin/{chunks/nl-TzvfktV_.mjs → translations/nl.json.mjs} +1 -1
- package/dist/admin/translations/nl.json.mjs.map +1 -0
- package/dist/admin/{chunks/pl-pYy1djj3.js → translations/pl.json.js} +3 -1
- package/dist/admin/translations/pl.json.js.map +1 -0
- package/dist/admin/{chunks/pl-BdvupIN_.mjs → translations/pl.json.mjs} +1 -1
- package/dist/admin/translations/pl.json.mjs.map +1 -0
- package/dist/admin/{chunks/pt-BR-CTPuXGWF.js → translations/pt-BR.json.js} +3 -1
- package/dist/admin/translations/pt-BR.json.js.map +1 -0
- package/dist/admin/{chunks/pt-BR-DPrVmKeZ.mjs → translations/pt-BR.json.mjs} +1 -1
- package/dist/admin/{chunks/dk-CGm-qVH7.js.map → translations/pt-BR.json.mjs.map} +1 -1
- package/dist/admin/{chunks/pt-BQmWcdeG.js → translations/pt.json.js} +3 -1
- package/dist/admin/translations/pt.json.js.map +1 -0
- package/dist/admin/{chunks/pt-BTLIwmCv.mjs → translations/pt.json.mjs} +1 -1
- package/dist/admin/translations/pt.json.mjs.map +1 -0
- package/dist/admin/{chunks/ru-DQiDXgUV.js → translations/ru.json.js} +3 -1
- package/dist/admin/translations/ru.json.js.map +1 -0
- package/dist/admin/{chunks/ru-D46no502.mjs → translations/ru.json.mjs} +1 -1
- package/dist/admin/translations/ru.json.mjs.map +1 -0
- package/dist/admin/{chunks/sk-DrnebmXb.js → translations/sk.json.js} +3 -1
- package/dist/admin/translations/sk.json.js.map +1 -0
- package/dist/admin/{chunks/sk-Byr_l4Jc.mjs → translations/sk.json.mjs} +1 -1
- package/dist/admin/translations/sk.json.mjs.map +1 -0
- package/dist/admin/{chunks/sv-CrWlNosi.js → translations/sv.json.js} +3 -1
- package/dist/admin/translations/sv.json.js.map +1 -0
- package/dist/admin/{chunks/sv-Bbam7IDm.mjs → translations/sv.json.mjs} +1 -1
- package/dist/admin/translations/sv.json.mjs.map +1 -0
- package/dist/admin/{chunks/th-BbrCkfgX.js → translations/th.json.js} +3 -1
- package/dist/admin/translations/th.json.js.map +1 -0
- package/dist/admin/{chunks/th-hfS0Wmk_.mjs → translations/th.json.mjs} +1 -1
- package/dist/admin/translations/th.json.mjs.map +1 -0
- package/dist/admin/{chunks/tr-CHdMj8m6.js → translations/tr.json.js} +3 -1
- package/dist/admin/translations/tr.json.js.map +1 -0
- package/dist/admin/{chunks/tr-DS7DBOhC.mjs → translations/tr.json.mjs} +1 -1
- package/dist/admin/translations/tr.json.mjs.map +1 -0
- package/dist/admin/{chunks/uk-felSA_eV.js → translations/uk.json.js} +3 -1
- package/dist/admin/translations/uk.json.js.map +1 -0
- package/dist/admin/{chunks/uk-CjzmJyt1.mjs → translations/uk.json.mjs} +1 -1
- package/dist/admin/translations/uk.json.mjs.map +1 -0
- package/dist/admin/{chunks/zh-Hans-lXbNiMp9.js → translations/zh-Hans.json.js} +3 -1
- package/dist/admin/{chunks/cs-BpQ26jiq.mjs.map → translations/zh-Hans.json.js.map} +1 -1
- package/dist/admin/{chunks/zh-Hans-BElOnuRb.mjs → translations/zh-Hans.json.mjs} +1 -1
- package/dist/admin/translations/zh-Hans.json.mjs.map +1 -0
- package/dist/admin/{chunks/zh-CWj4avQA.js → translations/zh.json.js} +3 -1
- package/dist/admin/translations/zh.json.js.map +1 -0
- package/dist/admin/{chunks/zh-BUVXH75-.mjs → translations/zh.json.mjs} +1 -1
- package/dist/admin/translations/zh.json.mjs.map +1 -0
- package/dist/admin/utils/findAttribute.js +8 -0
- package/dist/admin/utils/findAttribute.js.map +1 -0
- package/dist/admin/utils/findAttribute.mjs +6 -0
- package/dist/admin/utils/findAttribute.mjs.map +1 -0
- package/dist/admin/utils/formAPI.js +134 -0
- package/dist/admin/utils/formAPI.js.map +1 -0
- package/dist/admin/utils/formAPI.mjs +113 -0
- package/dist/admin/utils/formAPI.mjs.map +1 -0
- package/dist/admin/utils/getAttributeDisplayedType.js +32 -0
- package/dist/admin/utils/getAttributeDisplayedType.js.map +1 -0
- package/dist/admin/utils/getAttributeDisplayedType.mjs +30 -0
- package/dist/admin/utils/getAttributeDisplayedType.mjs.map +1 -0
- package/dist/admin/utils/getMaxDepth.js +74 -0
- package/dist/admin/utils/getMaxDepth.js.map +1 -0
- package/dist/admin/utils/getMaxDepth.mjs +71 -0
- package/dist/admin/utils/getMaxDepth.mjs.map +1 -0
- package/dist/admin/utils/getRelationType.js +18 -0
- package/dist/admin/utils/getRelationType.js.map +1 -0
- package/dist/admin/utils/getRelationType.mjs +16 -0
- package/dist/admin/utils/getRelationType.mjs.map +1 -0
- package/dist/admin/utils/getTrad.js +8 -0
- package/dist/admin/utils/getTrad.js.map +1 -0
- package/dist/admin/utils/getTrad.mjs +6 -0
- package/dist/admin/utils/getTrad.mjs.map +1 -0
- package/dist/admin/utils/getYupInnerErrors.js +23 -0
- package/dist/admin/utils/getYupInnerErrors.js.map +1 -0
- package/dist/admin/utils/getYupInnerErrors.mjs +21 -0
- package/dist/admin/utils/getYupInnerErrors.mjs.map +1 -0
- package/dist/admin/utils/isAllowedContentTypesForRelations.js +8 -0
- package/dist/admin/utils/isAllowedContentTypesForRelations.js.map +1 -0
- package/dist/admin/utils/isAllowedContentTypesForRelations.mjs +6 -0
- package/dist/admin/utils/isAllowedContentTypesForRelations.mjs.map +1 -0
- package/dist/admin/utils/makeUnique.js +8 -0
- package/dist/admin/utils/makeUnique.js.map +1 -0
- package/dist/admin/utils/makeUnique.mjs +6 -0
- package/dist/admin/utils/makeUnique.mjs.map +1 -0
- package/dist/admin/utils/nameToSlug.js +10 -0
- package/dist/admin/utils/nameToSlug.js.map +1 -0
- package/dist/admin/utils/nameToSlug.mjs +8 -0
- package/dist/admin/utils/nameToSlug.mjs.map +1 -0
- package/dist/admin/utils/parseDateValue.js +17 -0
- package/dist/admin/utils/parseDateValue.js.map +1 -0
- package/dist/admin/utils/parseDateValue.mjs +15 -0
- package/dist/admin/utils/parseDateValue.mjs.map +1 -0
- package/dist/admin/utils/prefixPluginTranslations.js +11 -0
- package/dist/admin/utils/prefixPluginTranslations.js.map +1 -0
- package/dist/admin/utils/prefixPluginTranslations.mjs +9 -0
- package/dist/admin/utils/prefixPluginTranslations.mjs.map +1 -0
- package/dist/admin/utils/timeFormat.js +38 -0
- package/dist/admin/utils/timeFormat.js.map +1 -0
- package/dist/admin/utils/timeFormat.mjs +35 -0
- package/dist/admin/utils/timeFormat.mjs.map +1 -0
- package/dist/admin/utils/toRegressedEnumValue.js +17 -0
- package/dist/admin/utils/toRegressedEnumValue.js.map +1 -0
- package/dist/admin/utils/toRegressedEnumValue.mjs +15 -0
- package/dist/admin/utils/toRegressedEnumValue.mjs.map +1 -0
- package/dist/server/bootstrap.js +16 -0
- package/dist/server/bootstrap.js.map +1 -0
- package/dist/server/bootstrap.mjs +14 -0
- package/dist/server/bootstrap.mjs.map +1 -0
- package/dist/server/config.js +9 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/config.mjs +7 -0
- package/dist/server/config.mjs.map +1 -0
- package/dist/server/controllers/builder.js +12 -0
- package/dist/server/controllers/builder.js.map +1 -0
- package/dist/server/controllers/builder.mjs +10 -0
- package/dist/server/controllers/builder.mjs.map +1 -0
- package/dist/server/controllers/component-categories.js +38 -0
- package/dist/server/controllers/component-categories.js.map +1 -0
- package/dist/server/controllers/component-categories.mjs +36 -0
- package/dist/server/controllers/component-categories.mjs.map +1 -0
- package/dist/server/controllers/components.js +144 -0
- package/dist/server/controllers/components.js.map +1 -0
- package/dist/server/controllers/components.mjs +142 -0
- package/dist/server/controllers/components.mjs.map +1 -0
- package/dist/server/controllers/content-types.js +142 -0
- package/dist/server/controllers/content-types.js.map +1 -0
- package/dist/server/controllers/content-types.mjs +140 -0
- package/dist/server/controllers/content-types.mjs.map +1 -0
- package/dist/server/controllers/index.js +16 -0
- package/dist/server/controllers/index.js.map +1 -0
- package/dist/server/controllers/index.mjs +14 -0
- package/dist/server/controllers/index.mjs.map +1 -0
- package/dist/server/controllers/validation/common.js +102 -0
- package/dist/server/controllers/validation/common.js.map +1 -0
- package/dist/server/controllers/validation/common.mjs +85 -0
- package/dist/server/controllers/validation/common.mjs.map +1 -0
- package/dist/server/controllers/validation/component-category.js +12 -0
- package/dist/server/controllers/validation/component-category.js.map +1 -0
- package/dist/server/controllers/validation/component-category.mjs +10 -0
- package/dist/server/controllers/validation/component-category.mjs.map +1 -0
- package/dist/server/controllers/validation/component.js +68 -0
- package/dist/server/controllers/validation/component.js.map +1 -0
- package/dist/server/controllers/validation/component.mjs +60 -0
- package/dist/server/controllers/validation/component.mjs.map +1 -0
- package/dist/server/controllers/validation/content-type.js +153 -0
- package/dist/server/controllers/validation/content-type.js.map +1 -0
- package/dist/server/controllers/validation/content-type.mjs +149 -0
- package/dist/server/controllers/validation/content-type.mjs.map +1 -0
- package/dist/server/controllers/validation/data-transform.js +27 -0
- package/dist/server/controllers/validation/data-transform.js.map +1 -0
- package/dist/server/controllers/validation/data-transform.mjs +24 -0
- package/dist/server/controllers/validation/data-transform.mjs.map +1 -0
- package/dist/server/controllers/validation/model-schema.js +90 -0
- package/dist/server/controllers/validation/model-schema.js.map +1 -0
- package/dist/server/controllers/validation/model-schema.mjs +88 -0
- package/dist/server/controllers/validation/model-schema.mjs.map +1 -0
- package/dist/server/controllers/validation/relations.js +70 -0
- package/dist/server/controllers/validation/relations.js.map +1 -0
- package/dist/server/controllers/validation/relations.mjs +68 -0
- package/dist/server/controllers/validation/relations.mjs.map +1 -0
- package/dist/server/controllers/validation/types.js +215 -0
- package/dist/server/controllers/validation/types.js.map +1 -0
- package/dist/server/controllers/validation/types.mjs +213 -0
- package/dist/server/controllers/validation/types.mjs.map +1 -0
- package/dist/server/index.js +8 -2654
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +5 -2633
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/routes/admin.js +231 -0
- package/dist/server/routes/admin.js.map +1 -0
- package/dist/server/routes/admin.mjs +229 -0
- package/dist/server/routes/admin.mjs.map +1 -0
- package/dist/server/routes/content-api.js +30 -0
- package/dist/server/routes/content-api.js.map +1 -0
- package/dist/server/routes/content-api.mjs +28 -0
- package/dist/server/routes/content-api.mjs.map +1 -0
- package/dist/server/routes/index.js +12 -0
- package/dist/server/routes/index.js.map +1 -0
- package/dist/server/routes/index.mjs +10 -0
- package/dist/server/routes/index.mjs.map +1 -0
- package/dist/server/services/api-handler.js +109 -0
- package/dist/server/services/api-handler.js.map +1 -0
- package/dist/server/services/api-handler.mjs +85 -0
- package/dist/server/services/api-handler.mjs.map +1 -0
- package/dist/server/services/builder.js +81 -0
- package/dist/server/services/builder.js.map +1 -0
- package/dist/server/services/builder.mjs +75 -0
- package/dist/server/services/builder.mjs.map +1 -0
- package/dist/server/services/component-categories.js +59 -0
- package/dist/server/services/component-categories.js.map +1 -0
- package/dist/server/services/component-categories.mjs +56 -0
- package/dist/server/services/component-categories.mjs.map +1 -0
- package/dist/server/services/components.js +79 -0
- package/dist/server/services/components.js.map +1 -0
- package/dist/server/services/components.mjs +74 -0
- package/dist/server/services/components.mjs.map +1 -0
- package/dist/server/services/constants.js +52 -0
- package/dist/server/services/constants.js.map +1 -0
- package/dist/server/services/constants.mjs +45 -0
- package/dist/server/services/constants.mjs.map +1 -0
- package/dist/server/services/content-types.js +223 -0
- package/dist/server/services/content-types.js.map +1 -0
- package/dist/server/services/content-types.mjs +213 -0
- package/dist/server/services/content-types.mjs.map +1 -0
- package/dist/server/services/index.js +18 -0
- package/dist/server/services/index.js.map +1 -0
- package/dist/server/services/index.mjs +16 -0
- package/dist/server/services/index.mjs.map +1 -0
- package/dist/server/services/schema-builder/component-builder.js +114 -0
- package/dist/server/services/schema-builder/component-builder.js.map +1 -0
- package/dist/server/services/schema-builder/component-builder.mjs +112 -0
- package/dist/server/services/schema-builder/component-builder.mjs.map +1 -0
- package/dist/server/services/schema-builder/content-type-builder.js +276 -0
- package/dist/server/services/schema-builder/content-type-builder.js.map +1 -0
- package/dist/server/services/schema-builder/content-type-builder.mjs +274 -0
- package/dist/server/services/schema-builder/content-type-builder.mjs.map +1 -0
- package/dist/server/services/schema-builder/index.js +145 -0
- package/dist/server/services/schema-builder/index.js.map +1 -0
- package/dist/server/services/schema-builder/index.mjs +143 -0
- package/dist/server/services/schema-builder/index.mjs.map +1 -0
- package/dist/server/services/schema-builder/schema-handler.js +250 -0
- package/dist/server/services/schema-builder/schema-handler.js.map +1 -0
- package/dist/server/services/schema-builder/schema-handler.mjs +248 -0
- package/dist/server/services/schema-builder/schema-handler.mjs.map +1 -0
- package/dist/server/utils/attributes.js +91 -0
- package/dist/server/utils/attributes.js.map +1 -0
- package/dist/server/utils/attributes.mjs +85 -0
- package/dist/server/utils/attributes.mjs.map +1 -0
- package/dist/server/utils/index.js +8 -0
- package/dist/server/utils/index.js.map +1 -0
- package/dist/server/utils/index.mjs +6 -0
- package/dist/server/utils/index.mjs.map +1 -0
- package/dist/server/utils/typeguards.js +8 -0
- package/dist/server/utils/typeguards.js.map +1 -0
- package/dist/server/utils/typeguards.mjs +6 -0
- package/dist/server/utils/typeguards.mjs.map +1 -0
- package/package.json +5 -5
- package/dist/admin/chunks/ListView-Cl-pbcxP.mjs +0 -1184
- package/dist/admin/chunks/ListView-Cl-pbcxP.mjs.map +0 -1
- package/dist/admin/chunks/ListView-DMZvleUI.js +0 -1186
- package/dist/admin/chunks/ListView-DMZvleUI.js.map +0 -1
- package/dist/admin/chunks/ar-Df0f0-PT.js.map +0 -1
- package/dist/admin/chunks/ar-sRW9VFC-.mjs.map +0 -1
- package/dist/admin/chunks/cs-DeTwqc7p.js.map +0 -1
- package/dist/admin/chunks/de-BJkS06jF.js.map +0 -1
- package/dist/admin/chunks/de-DSxx5_x-.mjs.map +0 -1
- package/dist/admin/chunks/dk-BnjVZ7A_.mjs.map +0 -1
- package/dist/admin/chunks/en-BJUu34b0.js.map +0 -1
- package/dist/admin/chunks/en-Bhut8Yay.mjs.map +0 -1
- package/dist/admin/chunks/es-DG8g9igJ.mjs.map +0 -1
- package/dist/admin/chunks/es-J8kvHlNy.js.map +0 -1
- package/dist/admin/chunks/fr-C6y35iY7.js.map +0 -1
- package/dist/admin/chunks/fr-UpV34MHY.mjs.map +0 -1
- package/dist/admin/chunks/id-BWM18ljw.mjs.map +0 -1
- package/dist/admin/chunks/id-BvxV6wLP.js.map +0 -1
- package/dist/admin/chunks/index-BG2mUcnk.js +0 -7788
- package/dist/admin/chunks/index-BG2mUcnk.js.map +0 -1
- package/dist/admin/chunks/index-DAXXa6S8.mjs +0 -1384
- package/dist/admin/chunks/index-DAXXa6S8.mjs.map +0 -1
- package/dist/admin/chunks/index-DWAINlnG.js +0 -1421
- package/dist/admin/chunks/index-DWAINlnG.js.map +0 -1
- package/dist/admin/chunks/index-Knq4Ti8R.mjs +0 -7761
- package/dist/admin/chunks/index-Knq4Ti8R.mjs.map +0 -1
- package/dist/admin/chunks/it-1_vd9gV4.mjs.map +0 -1
- package/dist/admin/chunks/it-C_IgFU-G.js.map +0 -1
- package/dist/admin/chunks/ja-CWo4Qqq6.js.map +0 -1
- package/dist/admin/chunks/ja-Cx23a2Ui.mjs.map +0 -1
- package/dist/admin/chunks/ko-BsByJNEl.js.map +0 -1
- package/dist/admin/chunks/ko-DC7paEx5.mjs.map +0 -1
- package/dist/admin/chunks/ms-DPTzS7SH.js.map +0 -1
- package/dist/admin/chunks/nl-TzvfktV_.mjs.map +0 -1
- package/dist/admin/chunks/nl-db29QMOx.js.map +0 -1
- package/dist/admin/chunks/pl-BdvupIN_.mjs.map +0 -1
- package/dist/admin/chunks/pl-pYy1djj3.js.map +0 -1
- package/dist/admin/chunks/pt-BQmWcdeG.js.map +0 -1
- package/dist/admin/chunks/pt-BR-CTPuXGWF.js.map +0 -1
- package/dist/admin/chunks/pt-BR-DPrVmKeZ.mjs.map +0 -1
- package/dist/admin/chunks/pt-BTLIwmCv.mjs.map +0 -1
- package/dist/admin/chunks/ru-D46no502.mjs.map +0 -1
- package/dist/admin/chunks/ru-DQiDXgUV.js.map +0 -1
- package/dist/admin/chunks/sk-Byr_l4Jc.mjs.map +0 -1
- package/dist/admin/chunks/sk-DrnebmXb.js.map +0 -1
- package/dist/admin/chunks/sv-Bbam7IDm.mjs.map +0 -1
- package/dist/admin/chunks/sv-CrWlNosi.js.map +0 -1
- package/dist/admin/chunks/th-BbrCkfgX.js.map +0 -1
- package/dist/admin/chunks/th-hfS0Wmk_.mjs.map +0 -1
- package/dist/admin/chunks/tr-CHdMj8m6.js.map +0 -1
- package/dist/admin/chunks/tr-DS7DBOhC.mjs.map +0 -1
- package/dist/admin/chunks/uk-CjzmJyt1.mjs.map +0 -1
- package/dist/admin/chunks/uk-felSA_eV.js.map +0 -1
- package/dist/admin/chunks/zh-BUVXH75-.mjs.map +0 -1
- package/dist/admin/chunks/zh-CWj4avQA.js.map +0 -1
- package/dist/admin/chunks/zh-Hans-BElOnuRb.mjs.map +0 -1
- package/dist/admin/chunks/zh-Hans-lXbNiMp9.js.map +0 -1
package/dist/server/index.js
CHANGED
|
@@ -1,2665 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
require('@strapi/types');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var pluralize = require('pluralize');
|
|
10
|
-
|
|
11
|
-
function _interopNamespaceDefault(e) {
|
|
12
|
-
var n = Object.create(null);
|
|
13
|
-
if (e) {
|
|
14
|
-
Object.keys(e).forEach(function (k) {
|
|
15
|
-
if (k !== 'default') {
|
|
16
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
-
enumerable: true,
|
|
19
|
-
get: function () { return e[k]; }
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
n.default = e;
|
|
25
|
-
return Object.freeze(n);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
29
|
-
var fse__namespace = /*#__PURE__*/_interopNamespaceDefault(fse);
|
|
30
|
-
|
|
31
|
-
var config = {
|
|
32
|
-
default: {},
|
|
33
|
-
validator () {}
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
var bootstrap = (async ({ strapi })=>{
|
|
37
|
-
const actions = [
|
|
38
|
-
{
|
|
39
|
-
section: 'plugins',
|
|
40
|
-
displayName: 'Read',
|
|
41
|
-
uid: 'read',
|
|
42
|
-
pluginName: 'content-type-builder'
|
|
43
|
-
}
|
|
44
|
-
];
|
|
45
|
-
await strapi.service('admin::permission').actionProvider.registerMany(actions);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const { ApplicationError: ApplicationError$3 } = utils.errors;
|
|
49
|
-
const isConfigurable = (attribute)=>_.get(attribute, 'configurable', true);
|
|
50
|
-
const isRelation = (attribute)=>attribute.type === 'relation';
|
|
51
|
-
/**
|
|
52
|
-
* Formats a component's attributes
|
|
53
|
-
*/ const formatAttributes = (model)=>{
|
|
54
|
-
const { getVisibleAttributes } = utils.contentTypes;
|
|
55
|
-
// only get attributes that can be seen in the CTB
|
|
56
|
-
return getVisibleAttributes(model).reduce((acc, key)=>{
|
|
57
|
-
acc[key] = formatAttribute(model.attributes[key]);
|
|
58
|
-
return acc;
|
|
59
|
-
}, {});
|
|
60
|
-
};
|
|
61
|
-
/**
|
|
62
|
-
* Formats a component attribute
|
|
63
|
-
*/ const formatAttribute = (attribute)=>{
|
|
64
|
-
const { configurable, required, autoPopulate, pluginOptions } = attribute;
|
|
65
|
-
if (attribute.type === 'media') {
|
|
66
|
-
return {
|
|
67
|
-
type: 'media',
|
|
68
|
-
multiple: !!attribute.multiple,
|
|
69
|
-
required: !!required,
|
|
70
|
-
configurable: configurable === false ? false : undefined,
|
|
71
|
-
private: !!attribute.private,
|
|
72
|
-
allowedTypes: attribute.allowedTypes,
|
|
73
|
-
pluginOptions
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
if (attribute.type === 'relation') {
|
|
77
|
-
return {
|
|
78
|
-
...attribute,
|
|
79
|
-
type: 'relation',
|
|
80
|
-
target: attribute.target,
|
|
81
|
-
targetAttribute: attribute.inversedBy || attribute.mappedBy || null,
|
|
82
|
-
configurable: configurable === false ? false : undefined,
|
|
83
|
-
private: !!attribute.private,
|
|
84
|
-
pluginOptions,
|
|
85
|
-
// TODO: remove
|
|
86
|
-
autoPopulate
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
return attribute;
|
|
90
|
-
};
|
|
91
|
-
// TODO: move to schema builder
|
|
92
|
-
const replaceTemporaryUIDs = (uidMap)=>(schema)=>{
|
|
93
|
-
return {
|
|
94
|
-
...schema,
|
|
95
|
-
attributes: Object.keys(schema.attributes).reduce((acc, key)=>{
|
|
96
|
-
const attr = schema.attributes[key];
|
|
97
|
-
if (attr.type === 'component') {
|
|
98
|
-
if (_.has(uidMap, attr.component)) {
|
|
99
|
-
acc[key] = {
|
|
100
|
-
...attr,
|
|
101
|
-
component: uidMap[attr.component]
|
|
102
|
-
};
|
|
103
|
-
return acc;
|
|
104
|
-
}
|
|
105
|
-
if (!_.has(strapi.components, attr.component)) {
|
|
106
|
-
throw new ApplicationError$3('component.notFound');
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (attr.type === 'dynamiczone' && _.intersection(attr.components, Object.keys(uidMap)).length > 0) {
|
|
110
|
-
acc[key] = {
|
|
111
|
-
...attr,
|
|
112
|
-
components: attr.components.map((value)=>{
|
|
113
|
-
if (_.has(uidMap, value)) return uidMap[value];
|
|
114
|
-
if (!_.has(strapi.components, value)) {
|
|
115
|
-
throw new ApplicationError$3('component.notFound');
|
|
116
|
-
}
|
|
117
|
-
return value;
|
|
118
|
-
})
|
|
119
|
-
};
|
|
120
|
-
return acc;
|
|
121
|
-
}
|
|
122
|
-
acc[key] = attr;
|
|
123
|
-
return acc;
|
|
124
|
-
}, {})
|
|
125
|
-
};
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
function createSchemaHandler(infos) {
|
|
129
|
-
const { category, modelName, plugin, uid, dir, filename, schema } = infos;
|
|
130
|
-
const initialState = {
|
|
131
|
-
modelName,
|
|
132
|
-
plugin,
|
|
133
|
-
category,
|
|
134
|
-
uid,
|
|
135
|
-
dir,
|
|
136
|
-
filename,
|
|
137
|
-
schema: schema || {
|
|
138
|
-
info: {},
|
|
139
|
-
options: {},
|
|
140
|
-
attributes: {}
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
const state = _.cloneDeep(initialState);
|
|
144
|
-
// always keep it the same to rollback
|
|
145
|
-
Object.freeze(initialState.schema);
|
|
146
|
-
let modified = false;
|
|
147
|
-
let deleted = false;
|
|
148
|
-
return {
|
|
149
|
-
get modelName () {
|
|
150
|
-
return initialState.modelName;
|
|
151
|
-
},
|
|
152
|
-
get plugin () {
|
|
153
|
-
return initialState.plugin;
|
|
154
|
-
},
|
|
155
|
-
get category () {
|
|
156
|
-
return initialState.category;
|
|
157
|
-
},
|
|
158
|
-
get kind () {
|
|
159
|
-
return _.get(state.schema, 'kind', 'collectionType');
|
|
160
|
-
},
|
|
161
|
-
get uid () {
|
|
162
|
-
return state.uid;
|
|
163
|
-
},
|
|
164
|
-
get writable () {
|
|
165
|
-
return _.get(state, 'plugin') !== 'admin';
|
|
166
|
-
},
|
|
167
|
-
setUID (val) {
|
|
168
|
-
modified = true;
|
|
169
|
-
state.uid = val;
|
|
170
|
-
return this;
|
|
171
|
-
},
|
|
172
|
-
setDir (val) {
|
|
173
|
-
modified = true;
|
|
174
|
-
state.dir = val;
|
|
175
|
-
return this;
|
|
176
|
-
},
|
|
177
|
-
get schema () {
|
|
178
|
-
return _.cloneDeep(state.schema);
|
|
179
|
-
},
|
|
180
|
-
setSchema (val) {
|
|
181
|
-
modified = true;
|
|
182
|
-
state.schema = _.cloneDeep(val);
|
|
183
|
-
return this;
|
|
184
|
-
},
|
|
185
|
-
// get a particular path inside the schema
|
|
186
|
-
get (path) {
|
|
187
|
-
return _.get(state.schema, path);
|
|
188
|
-
},
|
|
189
|
-
// set a particular path inside the schema
|
|
190
|
-
set (path, val) {
|
|
191
|
-
if (!state.schema) return this;
|
|
192
|
-
modified = true;
|
|
193
|
-
const value = _.defaultTo(val, _.get(state.schema, path));
|
|
194
|
-
_.set(state.schema, path, value);
|
|
195
|
-
return this;
|
|
196
|
-
},
|
|
197
|
-
// delete a particular path inside the schema
|
|
198
|
-
unset (path) {
|
|
199
|
-
modified = true;
|
|
200
|
-
_.unset(state.schema, path);
|
|
201
|
-
return this;
|
|
202
|
-
},
|
|
203
|
-
delete () {
|
|
204
|
-
deleted = true;
|
|
205
|
-
return this;
|
|
206
|
-
},
|
|
207
|
-
getAttribute (key) {
|
|
208
|
-
return this.get([
|
|
209
|
-
'attributes',
|
|
210
|
-
key
|
|
211
|
-
]);
|
|
212
|
-
},
|
|
213
|
-
setAttribute (key, attribute) {
|
|
214
|
-
return this.set([
|
|
215
|
-
'attributes',
|
|
216
|
-
key
|
|
217
|
-
], attribute);
|
|
218
|
-
},
|
|
219
|
-
deleteAttribute (key) {
|
|
220
|
-
return this.unset([
|
|
221
|
-
'attributes',
|
|
222
|
-
key
|
|
223
|
-
]);
|
|
224
|
-
},
|
|
225
|
-
setAttributes (newAttributes) {
|
|
226
|
-
if (!this.schema) return this;
|
|
227
|
-
// delete old configurable attributes
|
|
228
|
-
for(const key in this.schema.attributes){
|
|
229
|
-
if (isConfigurable(this.schema.attributes[key])) {
|
|
230
|
-
this.deleteAttribute(key);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
// set new Attributes
|
|
234
|
-
for (const key of Object.keys(newAttributes)){
|
|
235
|
-
this.setAttribute(key, newAttributes[key]);
|
|
236
|
-
}
|
|
237
|
-
return this;
|
|
238
|
-
},
|
|
239
|
-
removeContentType (uid) {
|
|
240
|
-
if (!state.schema) return this;
|
|
241
|
-
const attributes = state.schema.attributes;
|
|
242
|
-
Object.keys(attributes).forEach((key)=>{
|
|
243
|
-
const attribute = attributes[key];
|
|
244
|
-
if (attribute.target === uid) {
|
|
245
|
-
this.deleteAttribute(key);
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
return this;
|
|
249
|
-
},
|
|
250
|
-
// utils
|
|
251
|
-
removeComponent (uid) {
|
|
252
|
-
if (!state.schema) return this;
|
|
253
|
-
const attributes = state.schema.attributes;
|
|
254
|
-
Object.keys(attributes).forEach((key)=>{
|
|
255
|
-
const attr = attributes[key];
|
|
256
|
-
if (attr.type === 'component' && attr.component === uid) {
|
|
257
|
-
this.deleteAttribute(key);
|
|
258
|
-
}
|
|
259
|
-
if (attr.type === 'dynamiczone' && Array.isArray(attr.components) && attr.components.includes(uid)) {
|
|
260
|
-
const updatedComponentList = attributes[key].components.filter((val)=>val !== uid);
|
|
261
|
-
this.set([
|
|
262
|
-
'attributes',
|
|
263
|
-
key,
|
|
264
|
-
'components'
|
|
265
|
-
], updatedComponentList);
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
return this;
|
|
269
|
-
},
|
|
270
|
-
updateComponent (uid, newUID) {
|
|
271
|
-
if (!state.schema) return this;
|
|
272
|
-
const attributes = state.schema.attributes;
|
|
273
|
-
Object.keys(attributes).forEach((key)=>{
|
|
274
|
-
const attr = attributes[key];
|
|
275
|
-
if (attr.type === 'component' && attr.component === uid) {
|
|
276
|
-
this.set([
|
|
277
|
-
'attributes',
|
|
278
|
-
key,
|
|
279
|
-
'component'
|
|
280
|
-
], newUID);
|
|
281
|
-
}
|
|
282
|
-
if (attr.type === 'dynamiczone' && Array.isArray(attr.components) && attr.components.includes(uid)) {
|
|
283
|
-
const updatedComponentList = attr.components.map((val)=>val === uid ? newUID : val);
|
|
284
|
-
this.set([
|
|
285
|
-
'attributes',
|
|
286
|
-
key,
|
|
287
|
-
'components'
|
|
288
|
-
], updatedComponentList);
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
return this;
|
|
292
|
-
},
|
|
293
|
-
// save the schema to disk
|
|
294
|
-
async flush () {
|
|
295
|
-
if (!this.writable) {
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
const initialPath = path.join(initialState.dir, initialState.filename);
|
|
299
|
-
const filePath = path.join(state.dir, state.filename);
|
|
300
|
-
if (deleted) {
|
|
301
|
-
await fse.remove(initialPath);
|
|
302
|
-
const list = await fse.readdir(initialState.dir);
|
|
303
|
-
if (list.length === 0) {
|
|
304
|
-
await fse.remove(initialState.dir);
|
|
305
|
-
}
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
if (modified) {
|
|
309
|
-
if (!state.schema) return Promise.resolve();
|
|
310
|
-
await fse.ensureFile(filePath);
|
|
311
|
-
await fse.writeJSON(filePath, {
|
|
312
|
-
kind: state.schema.kind,
|
|
313
|
-
collectionName: state.schema.collectionName,
|
|
314
|
-
info: state.schema.info,
|
|
315
|
-
options: state.schema.options,
|
|
316
|
-
pluginOptions: state.schema.pluginOptions,
|
|
317
|
-
attributes: state.schema.attributes,
|
|
318
|
-
config: state.schema.config
|
|
319
|
-
}, {
|
|
320
|
-
spaces: 2
|
|
321
|
-
});
|
|
322
|
-
// remove from oldPath
|
|
323
|
-
if (initialPath !== filePath) {
|
|
324
|
-
await fse.remove(initialPath);
|
|
325
|
-
const list = await fse.readdir(initialState.dir);
|
|
326
|
-
if (list.length === 0) {
|
|
327
|
-
await fse.remove(initialState.dir);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
return Promise.resolve();
|
|
333
|
-
},
|
|
334
|
-
// reset the schema to its initial value
|
|
335
|
-
async rollback () {
|
|
336
|
-
if (!this.writable) {
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
|
-
const initialPath = path.join(initialState.dir, initialState.filename);
|
|
340
|
-
const filePath = path.join(state.dir, state.filename);
|
|
341
|
-
// it was a creation so it needs to be deleted
|
|
342
|
-
if (!initialState.uid) {
|
|
343
|
-
await fse.remove(filePath);
|
|
344
|
-
const list = await fse.readdir(state.dir);
|
|
345
|
-
if (list.length === 0) {
|
|
346
|
-
await fse.remove(state.dir);
|
|
347
|
-
}
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
if (modified || deleted) {
|
|
351
|
-
await fse.ensureFile(initialPath);
|
|
352
|
-
await fse.writeJSON(initialPath, initialState.schema, {
|
|
353
|
-
spaces: 2
|
|
354
|
-
});
|
|
355
|
-
// remove
|
|
356
|
-
if (initialPath !== filePath) {
|
|
357
|
-
await fse.remove(filePath);
|
|
358
|
-
const list = await fse.readdir(state.dir);
|
|
359
|
-
if (list.length === 0) {
|
|
360
|
-
await fse.remove(state.dir);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
return Promise.resolve();
|
|
365
|
-
}
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
const { ApplicationError: ApplicationError$2 } = utils.errors;
|
|
370
|
-
function createComponentBuilder$1() {
|
|
371
|
-
return {
|
|
372
|
-
createComponentUID ({ category, displayName }) {
|
|
373
|
-
return `${utils.strings.nameToSlug(category)}.${utils.strings.nameToSlug(displayName)}`;
|
|
374
|
-
},
|
|
375
|
-
createNewComponentUIDMap (components) {
|
|
376
|
-
return components.reduce((uidMap, component)=>{
|
|
377
|
-
uidMap[component.tmpUID] = this.createComponentUID(component);
|
|
378
|
-
return uidMap;
|
|
379
|
-
}, {});
|
|
380
|
-
},
|
|
381
|
-
/**
|
|
382
|
-
* create a component in the tmpComponent map
|
|
383
|
-
*/ createComponent (infos) {
|
|
384
|
-
const uid = this.createComponentUID(infos);
|
|
385
|
-
if (this.components.has(uid)) {
|
|
386
|
-
throw new ApplicationError$2('component.alreadyExists');
|
|
387
|
-
}
|
|
388
|
-
const handler = createSchemaHandler({
|
|
389
|
-
dir: path.join(strapi.dirs.app.components, utils.strings.nameToSlug(infos.category)),
|
|
390
|
-
filename: `${utils.strings.nameToSlug(infos.displayName)}.json`
|
|
391
|
-
});
|
|
392
|
-
// TODO: create a utility for this
|
|
393
|
-
// Duplicate in admin/src/components/FormModal/forms/utils/createCollectionName.ts
|
|
394
|
-
const collectionName = `components_${utils.strings.nameToCollectionName(infos.category)}_${utils.strings.nameToCollectionName(pluralize(infos.displayName))}`;
|
|
395
|
-
this.components.forEach((compo)=>{
|
|
396
|
-
if (compo.schema.collectionName === collectionName) {
|
|
397
|
-
throw new ApplicationError$2('component.alreadyExists');
|
|
398
|
-
}
|
|
399
|
-
});
|
|
400
|
-
handler.setUID(uid).set('collectionName', collectionName).set([
|
|
401
|
-
'info',
|
|
402
|
-
'displayName'
|
|
403
|
-
], infos.displayName).set([
|
|
404
|
-
'info',
|
|
405
|
-
'icon'
|
|
406
|
-
], infos.icon).set([
|
|
407
|
-
'info',
|
|
408
|
-
'description'
|
|
409
|
-
], infos.description).set('pluginOptions', infos.pluginOptions).set('config', infos.config).setAttributes(this.convertAttributes(infos.attributes));
|
|
410
|
-
if (this.components.size === 0) {
|
|
411
|
-
strapi.telemetry.send('didCreateFirstComponent');
|
|
412
|
-
} else {
|
|
413
|
-
strapi.telemetry.send('didCreateComponent');
|
|
414
|
-
}
|
|
415
|
-
this.components.set(uid, handler);
|
|
416
|
-
return handler;
|
|
417
|
-
},
|
|
418
|
-
/**
|
|
419
|
-
* create a component in the tmpComponent map
|
|
420
|
-
*/ editComponent (infos) {
|
|
421
|
-
const { uid } = infos;
|
|
422
|
-
if (!this.components.has(uid)) {
|
|
423
|
-
throw new utils.errors.ApplicationError('component.notFound');
|
|
424
|
-
}
|
|
425
|
-
const component = this.components.get(uid);
|
|
426
|
-
const [, nameUID] = uid.split('.');
|
|
427
|
-
const newCategory = utils.strings.nameToSlug(infos.category);
|
|
428
|
-
const newUID = `${newCategory}.${nameUID}`;
|
|
429
|
-
if (newUID !== uid && this.components.has(newUID)) {
|
|
430
|
-
throw new utils.errors.ApplicationError('component.edit.alreadyExists');
|
|
431
|
-
}
|
|
432
|
-
const newDir = path.join(strapi.dirs.app.components, newCategory);
|
|
433
|
-
const oldAttributes = component.schema.attributes;
|
|
434
|
-
const newAttributes = _.omitBy(infos.attributes, (attr, key)=>{
|
|
435
|
-
return _.has(oldAttributes, key) && !isConfigurable(oldAttributes[key]);
|
|
436
|
-
});
|
|
437
|
-
component.setUID(newUID).setDir(newDir).set([
|
|
438
|
-
'info',
|
|
439
|
-
'displayName'
|
|
440
|
-
], infos.displayName).set([
|
|
441
|
-
'info',
|
|
442
|
-
'icon'
|
|
443
|
-
], infos.icon).set([
|
|
444
|
-
'info',
|
|
445
|
-
'description'
|
|
446
|
-
], infos.description).set('pluginOptions', infos.pluginOptions).setAttributes(this.convertAttributes(newAttributes));
|
|
447
|
-
if (newUID !== uid) {
|
|
448
|
-
this.components.forEach((compo)=>{
|
|
449
|
-
compo.updateComponent(uid, newUID);
|
|
450
|
-
});
|
|
451
|
-
this.contentTypes.forEach((ct)=>{
|
|
452
|
-
ct.updateComponent(uid, newUID);
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
return component;
|
|
456
|
-
},
|
|
457
|
-
deleteComponent (uid) {
|
|
458
|
-
if (!this.components.has(uid)) {
|
|
459
|
-
throw new utils.errors.ApplicationError('component.notFound');
|
|
460
|
-
}
|
|
461
|
-
this.components.forEach((compo)=>{
|
|
462
|
-
compo.removeComponent(uid);
|
|
463
|
-
});
|
|
464
|
-
this.contentTypes.forEach((ct)=>{
|
|
465
|
-
ct.removeComponent(uid);
|
|
466
|
-
});
|
|
467
|
-
return this.components.get(uid).delete();
|
|
468
|
-
}
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
const modelTypes = {
|
|
473
|
-
CONTENT_TYPE: 'CONTENT_TYPE',
|
|
474
|
-
COMPONENT: 'COMPONENT'
|
|
475
|
-
};
|
|
476
|
-
const typeKinds = {
|
|
477
|
-
SINGLE_TYPE: 'singleType',
|
|
478
|
-
COLLECTION_TYPE: 'collectionType'
|
|
479
|
-
};
|
|
480
|
-
const DEFAULT_TYPES = [
|
|
481
|
-
// advanced types
|
|
482
|
-
'media',
|
|
483
|
-
// scalar types
|
|
484
|
-
'string',
|
|
485
|
-
'text',
|
|
486
|
-
'richtext',
|
|
487
|
-
'blocks',
|
|
488
|
-
'json',
|
|
489
|
-
'enumeration',
|
|
490
|
-
'password',
|
|
491
|
-
'email',
|
|
492
|
-
'integer',
|
|
493
|
-
'biginteger',
|
|
494
|
-
'float',
|
|
495
|
-
'decimal',
|
|
496
|
-
'date',
|
|
497
|
-
'time',
|
|
498
|
-
'datetime',
|
|
499
|
-
'timestamp',
|
|
500
|
-
'boolean',
|
|
501
|
-
'relation'
|
|
502
|
-
];
|
|
503
|
-
const VALID_UID_TARGETS = [
|
|
504
|
-
'string',
|
|
505
|
-
'text'
|
|
506
|
-
];
|
|
507
|
-
const coreUids = {
|
|
508
|
-
STRAPI_USER: 'admin::user',
|
|
509
|
-
PREFIX: 'strapi::'
|
|
510
|
-
};
|
|
511
|
-
const pluginsUids = {
|
|
512
|
-
UPLOAD_FILE: 'plugin::upload.file'
|
|
513
|
-
};
|
|
514
|
-
|
|
515
|
-
const { ApplicationError: ApplicationError$1 } = utils.errors;
|
|
516
|
-
const reuseUnsetPreviousProperties = (newAttribute, oldAttribute)=>{
|
|
517
|
-
_.defaults(newAttribute, _.omit(oldAttribute, [
|
|
518
|
-
'configurable',
|
|
519
|
-
'required',
|
|
520
|
-
'private',
|
|
521
|
-
'unique',
|
|
522
|
-
'pluginOptions',
|
|
523
|
-
'inversedBy',
|
|
524
|
-
'mappedBy'
|
|
525
|
-
]));
|
|
526
|
-
};
|
|
527
|
-
function createComponentBuilder() {
|
|
528
|
-
return {
|
|
529
|
-
setRelation ({ key, uid, attribute }) {
|
|
530
|
-
if (!_.has(attribute, 'target')) {
|
|
531
|
-
return;
|
|
532
|
-
}
|
|
533
|
-
const targetCT = this.contentTypes.get(attribute.target);
|
|
534
|
-
const targetAttribute = targetCT.getAttribute(attribute.targetAttribute);
|
|
535
|
-
if (!attribute.targetAttribute) {
|
|
536
|
-
return;
|
|
537
|
-
}
|
|
538
|
-
targetCT.setAttribute(attribute.targetAttribute, generateRelation({
|
|
539
|
-
key,
|
|
540
|
-
attribute,
|
|
541
|
-
uid,
|
|
542
|
-
targetAttribute
|
|
543
|
-
}));
|
|
544
|
-
},
|
|
545
|
-
unsetRelation (attribute) {
|
|
546
|
-
if (!_.has(attribute, 'target')) {
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
549
|
-
const targetCT = this.contentTypes.get(attribute.target);
|
|
550
|
-
const targetAttributeName = attribute.inversedBy || attribute.mappedBy;
|
|
551
|
-
const targetAttribute = targetCT.getAttribute(targetAttributeName);
|
|
552
|
-
if (!targetAttribute) return;
|
|
553
|
-
return targetCT.deleteAttribute(targetAttributeName);
|
|
554
|
-
},
|
|
555
|
-
/**
|
|
556
|
-
* Creates a content type in memory to be written to files later on
|
|
557
|
-
*/ createContentType (infos) {
|
|
558
|
-
const uid = createContentTypeUID(infos);
|
|
559
|
-
if (this.contentTypes.has(uid)) {
|
|
560
|
-
throw new ApplicationError$1('contentType.alreadyExists');
|
|
561
|
-
}
|
|
562
|
-
const contentType = createSchemaHandler({
|
|
563
|
-
modelName: infos.singularName,
|
|
564
|
-
dir: path.join(strapi.dirs.app.api, infos.singularName, 'content-types', infos.singularName),
|
|
565
|
-
filename: `schema.json`
|
|
566
|
-
});
|
|
567
|
-
this.contentTypes.set(uid, contentType);
|
|
568
|
-
// support self referencing content type relation
|
|
569
|
-
Object.keys(infos.attributes).forEach((key)=>{
|
|
570
|
-
const { target } = infos.attributes[key];
|
|
571
|
-
if (target === '__self__') {
|
|
572
|
-
infos.attributes[key].target = uid;
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
|
-
contentType.setUID(uid).set('kind', infos.kind || typeKinds.COLLECTION_TYPE).set('collectionName', infos.collectionName || utils.strings.nameToCollectionName(infos.pluralName)).set('info', {
|
|
576
|
-
singularName: infos.singularName,
|
|
577
|
-
pluralName: infos.pluralName,
|
|
578
|
-
displayName: infos.displayName,
|
|
579
|
-
description: infos.description
|
|
580
|
-
}).set('options', {
|
|
581
|
-
...infos.options ?? {},
|
|
582
|
-
draftAndPublish: infos.draftAndPublish
|
|
583
|
-
}).set('pluginOptions', infos.pluginOptions).set('config', infos.config).setAttributes(this.convertAttributes(infos.attributes));
|
|
584
|
-
Object.keys(infos.attributes).forEach((key)=>{
|
|
585
|
-
const attribute = infos.attributes[key];
|
|
586
|
-
if (isRelation(attribute)) {
|
|
587
|
-
if ([
|
|
588
|
-
'manyToMany',
|
|
589
|
-
'oneToOne'
|
|
590
|
-
].includes(attribute.relation)) {
|
|
591
|
-
if (attribute.target === uid && attribute.targetAttribute !== undefined) {
|
|
592
|
-
// self referencing relation
|
|
593
|
-
const targetAttribute = infos.attributes[attribute.targetAttribute];
|
|
594
|
-
if (targetAttribute.dominant === undefined) {
|
|
595
|
-
attribute.dominant = true;
|
|
596
|
-
} else {
|
|
597
|
-
attribute.dominant = false;
|
|
598
|
-
}
|
|
599
|
-
} else {
|
|
600
|
-
attribute.dominant = true;
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
this.setRelation({
|
|
604
|
-
key,
|
|
605
|
-
uid,
|
|
606
|
-
attribute
|
|
607
|
-
});
|
|
608
|
-
}
|
|
609
|
-
});
|
|
610
|
-
return contentType;
|
|
611
|
-
},
|
|
612
|
-
editContentType (infos) {
|
|
613
|
-
const { uid } = infos;
|
|
614
|
-
if (!this.contentTypes.has(uid)) {
|
|
615
|
-
throw new ApplicationError$1('contentType.notFound');
|
|
616
|
-
}
|
|
617
|
-
const contentType = this.contentTypes.get(uid);
|
|
618
|
-
const oldAttributes = contentType.schema.attributes;
|
|
619
|
-
const newAttributes = _.omitBy(infos.attributes, (attr, key)=>{
|
|
620
|
-
return _.has(oldAttributes, key) && !isConfigurable(oldAttributes[key]);
|
|
621
|
-
});
|
|
622
|
-
const newKeys = _.difference(Object.keys(newAttributes), Object.keys(oldAttributes));
|
|
623
|
-
const deletedKeys = _.difference(Object.keys(oldAttributes), Object.keys(newAttributes));
|
|
624
|
-
const remainingKeys = _.intersection(Object.keys(oldAttributes), Object.keys(newAttributes));
|
|
625
|
-
// remove old relations
|
|
626
|
-
deletedKeys.forEach((key)=>{
|
|
627
|
-
const attribute = oldAttributes[key];
|
|
628
|
-
const targetAttributeName = attribute.inversedBy || attribute.mappedBy;
|
|
629
|
-
// if the old relation has a target attribute. we need to remove it in the target type
|
|
630
|
-
if (isConfigurable(attribute) && isRelation(attribute) && !_.isNil(targetAttributeName)) {
|
|
631
|
-
this.unsetRelation(attribute);
|
|
632
|
-
}
|
|
633
|
-
});
|
|
634
|
-
remainingKeys.forEach((key)=>{
|
|
635
|
-
const oldAttribute = oldAttributes[key];
|
|
636
|
-
const newAttribute = newAttributes[key];
|
|
637
|
-
if (!isRelation(oldAttribute) && isRelation(newAttribute)) {
|
|
638
|
-
return this.setRelation({
|
|
639
|
-
key,
|
|
640
|
-
uid,
|
|
641
|
-
attribute: newAttributes[key]
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
|
-
if (isRelation(oldAttribute) && !isRelation(newAttribute)) {
|
|
645
|
-
return this.unsetRelation(oldAttribute);
|
|
646
|
-
}
|
|
647
|
-
if (isRelation(oldAttribute) && isRelation(newAttribute)) {
|
|
648
|
-
const oldTargetAttributeName = oldAttribute.inversedBy || oldAttribute.mappedBy;
|
|
649
|
-
const sameRelation = oldAttribute.relation === newAttribute.relation;
|
|
650
|
-
const targetAttributeHasChanged = oldTargetAttributeName !== newAttribute.targetAttribute;
|
|
651
|
-
if (!sameRelation || targetAttributeHasChanged) {
|
|
652
|
-
this.unsetRelation(oldAttribute);
|
|
653
|
-
}
|
|
654
|
-
// keep extra options that were set manually on oldAttribute
|
|
655
|
-
reuseUnsetPreviousProperties(newAttribute, oldAttribute);
|
|
656
|
-
if (oldAttribute.inversedBy) {
|
|
657
|
-
newAttribute.dominant = true;
|
|
658
|
-
} else if (oldAttribute.mappedBy) {
|
|
659
|
-
newAttribute.dominant = false;
|
|
660
|
-
}
|
|
661
|
-
return this.setRelation({
|
|
662
|
-
key,
|
|
663
|
-
uid,
|
|
664
|
-
attribute: newAttribute
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
});
|
|
668
|
-
// add new relations
|
|
669
|
-
newKeys.forEach((key)=>{
|
|
670
|
-
const attribute = newAttributes[key];
|
|
671
|
-
if (isRelation(attribute)) {
|
|
672
|
-
if ([
|
|
673
|
-
'manyToMany',
|
|
674
|
-
'oneToOne'
|
|
675
|
-
].includes(attribute.relation)) {
|
|
676
|
-
if (attribute.target === uid && attribute.targetAttribute !== undefined) {
|
|
677
|
-
// self referencing relation
|
|
678
|
-
const targetAttribute = newAttributes[attribute.targetAttribute];
|
|
679
|
-
if (targetAttribute.dominant === undefined) {
|
|
680
|
-
attribute.dominant = true;
|
|
681
|
-
} else {
|
|
682
|
-
attribute.dominant = false;
|
|
683
|
-
}
|
|
684
|
-
} else {
|
|
685
|
-
attribute.dominant = true;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
this.setRelation({
|
|
689
|
-
key,
|
|
690
|
-
uid,
|
|
691
|
-
attribute
|
|
692
|
-
});
|
|
693
|
-
}
|
|
694
|
-
});
|
|
695
|
-
contentType.set('kind', infos.kind || contentType.schema.kind).set([
|
|
696
|
-
'info',
|
|
697
|
-
'displayName'
|
|
698
|
-
], infos.displayName).set([
|
|
699
|
-
'info',
|
|
700
|
-
'description'
|
|
701
|
-
], infos.description).set('options', {
|
|
702
|
-
...infos.options ?? {},
|
|
703
|
-
draftAndPublish: infos.draftAndPublish
|
|
704
|
-
}).set('pluginOptions', infos.pluginOptions).setAttributes(this.convertAttributes(newAttributes));
|
|
705
|
-
return contentType;
|
|
706
|
-
},
|
|
707
|
-
deleteContentType (uid) {
|
|
708
|
-
if (!this.contentTypes.has(uid)) {
|
|
709
|
-
throw new ApplicationError$1('contentType.notFound');
|
|
710
|
-
}
|
|
711
|
-
this.components.forEach((compo)=>{
|
|
712
|
-
compo.removeContentType(uid);
|
|
713
|
-
});
|
|
714
|
-
this.contentTypes.forEach((ct)=>{
|
|
715
|
-
ct.removeContentType(uid);
|
|
716
|
-
});
|
|
717
|
-
return this.contentTypes.get(uid).delete();
|
|
718
|
-
}
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
/**
|
|
722
|
-
* Returns a uid from a content type infos
|
|
723
|
-
*
|
|
724
|
-
* @param {object} options options
|
|
725
|
-
* @param {string} options.singularName content-type singularName
|
|
726
|
-
* @returns {string} uid
|
|
727
|
-
*/ const createContentTypeUID = ({ singularName })=>`api::${singularName}.${singularName}`;
|
|
728
|
-
const generateRelation = ({ key, attribute, uid, targetAttribute = {} })=>{
|
|
729
|
-
const opts = {
|
|
730
|
-
type: 'relation',
|
|
731
|
-
target: uid,
|
|
732
|
-
autoPopulate: targetAttribute.autoPopulate,
|
|
733
|
-
private: targetAttribute.private || undefined,
|
|
734
|
-
pluginOptions: targetAttribute.pluginOptions || undefined
|
|
735
|
-
};
|
|
736
|
-
switch(attribute.relation){
|
|
737
|
-
case 'oneToOne':
|
|
738
|
-
{
|
|
739
|
-
opts.relation = 'oneToOne';
|
|
740
|
-
if (attribute.dominant) {
|
|
741
|
-
opts.mappedBy = key;
|
|
742
|
-
} else {
|
|
743
|
-
opts.inversedBy = key;
|
|
744
|
-
}
|
|
745
|
-
break;
|
|
746
|
-
}
|
|
747
|
-
case 'oneToMany':
|
|
748
|
-
{
|
|
749
|
-
opts.relation = 'manyToOne';
|
|
750
|
-
opts.inversedBy = key;
|
|
751
|
-
break;
|
|
752
|
-
}
|
|
753
|
-
case 'manyToOne':
|
|
754
|
-
{
|
|
755
|
-
opts.relation = 'oneToMany';
|
|
756
|
-
opts.mappedBy = key;
|
|
757
|
-
break;
|
|
758
|
-
}
|
|
759
|
-
case 'manyToMany':
|
|
760
|
-
{
|
|
761
|
-
opts.relation = 'manyToMany';
|
|
762
|
-
if (attribute.dominant) {
|
|
763
|
-
opts.mappedBy = key;
|
|
764
|
-
} else {
|
|
765
|
-
opts.inversedBy = key;
|
|
766
|
-
}
|
|
767
|
-
break;
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
// we do this just to make sure we have the same key order when writing to files
|
|
771
|
-
const { type, relation, target, ...restOptions } = opts;
|
|
772
|
-
return {
|
|
773
|
-
type,
|
|
774
|
-
relation,
|
|
775
|
-
target,
|
|
776
|
-
...restOptions
|
|
777
|
-
};
|
|
778
|
-
};
|
|
779
|
-
|
|
780
|
-
/**
|
|
781
|
-
* Creates a content type schema builder instance
|
|
782
|
-
*/ function createBuilder() {
|
|
783
|
-
const components = Object.values(strapi.components).map((componentInput)=>({
|
|
784
|
-
category: componentInput.category,
|
|
785
|
-
modelName: componentInput.modelName,
|
|
786
|
-
plugin: componentInput.modelName,
|
|
787
|
-
uid: componentInput.uid,
|
|
788
|
-
filename: componentInput.__filename__,
|
|
789
|
-
dir: path.join(strapi.dirs.app.components, componentInput.category),
|
|
790
|
-
schema: componentInput.__schema__,
|
|
791
|
-
config: componentInput.config
|
|
792
|
-
}));
|
|
793
|
-
const contentTypes = Object.values(strapi.contentTypes).map((contentTypeInput)=>{
|
|
794
|
-
const dir = contentTypeInput.plugin ? path.join(strapi.dirs.app.extensions, contentTypeInput.plugin, 'content-types', contentTypeInput.info.singularName) : path.join(strapi.dirs.app.api, contentTypeInput.apiName, 'content-types', contentTypeInput.info.singularName);
|
|
795
|
-
return {
|
|
796
|
-
modelName: contentTypeInput.modelName,
|
|
797
|
-
plugin: contentTypeInput.plugin,
|
|
798
|
-
uid: contentTypeInput.uid,
|
|
799
|
-
filename: 'schema.json',
|
|
800
|
-
dir,
|
|
801
|
-
schema: contentTypeInput.__schema__,
|
|
802
|
-
config: contentTypeInput.config
|
|
803
|
-
};
|
|
804
|
-
});
|
|
805
|
-
return createSchemaBuilder({
|
|
806
|
-
components,
|
|
807
|
-
contentTypes
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
|
-
function createSchemaBuilder({ components, contentTypes }) {
|
|
811
|
-
const tmpComponents = new Map();
|
|
812
|
-
const tmpContentTypes = new Map();
|
|
813
|
-
// init temporary ContentTypes
|
|
814
|
-
Object.keys(contentTypes).forEach((key)=>{
|
|
815
|
-
tmpContentTypes.set(contentTypes[key].uid, createSchemaHandler(contentTypes[key]));
|
|
816
|
-
});
|
|
817
|
-
// init temporary components
|
|
818
|
-
Object.keys(components).forEach((key)=>{
|
|
819
|
-
tmpComponents.set(components[key].uid, createSchemaHandler(components[key]));
|
|
820
|
-
});
|
|
821
|
-
return {
|
|
822
|
-
get components () {
|
|
823
|
-
return tmpComponents;
|
|
824
|
-
},
|
|
825
|
-
get contentTypes () {
|
|
826
|
-
return tmpContentTypes;
|
|
827
|
-
},
|
|
828
|
-
/**
|
|
829
|
-
* Convert Attributes received from the API to the right syntax
|
|
830
|
-
*/ convertAttributes (attributes) {
|
|
831
|
-
return Object.keys(attributes).reduce((acc, key)=>{
|
|
832
|
-
const attribute = attributes[key];
|
|
833
|
-
const { configurable, private: isPrivate } = attribute;
|
|
834
|
-
const baseProperties = {
|
|
835
|
-
private: isPrivate === true ? true : undefined,
|
|
836
|
-
configurable: configurable === false ? false : undefined
|
|
837
|
-
};
|
|
838
|
-
if (attribute.type === 'relation') {
|
|
839
|
-
const { target, relation, targetAttribute, dominant, ...restOfProperties } = attribute;
|
|
840
|
-
const attr = {
|
|
841
|
-
type: 'relation',
|
|
842
|
-
relation,
|
|
843
|
-
target,
|
|
844
|
-
...restOfProperties,
|
|
845
|
-
...baseProperties
|
|
846
|
-
};
|
|
847
|
-
acc[key] = attr;
|
|
848
|
-
if (target && !this.contentTypes.has(target)) {
|
|
849
|
-
throw new utils.errors.ApplicationError(`target: ${target} does not exist`);
|
|
850
|
-
}
|
|
851
|
-
if (_.isNil(targetAttribute)) {
|
|
852
|
-
return acc;
|
|
853
|
-
}
|
|
854
|
-
if ([
|
|
855
|
-
'oneToOne',
|
|
856
|
-
'manyToMany'
|
|
857
|
-
].includes(relation) && dominant === true) {
|
|
858
|
-
attr.inversedBy = targetAttribute;
|
|
859
|
-
} else if ([
|
|
860
|
-
'oneToOne',
|
|
861
|
-
'manyToMany'
|
|
862
|
-
].includes(relation) && dominant === false) {
|
|
863
|
-
attr.mappedBy = targetAttribute;
|
|
864
|
-
} else if ([
|
|
865
|
-
'oneToOne',
|
|
866
|
-
'manyToOne',
|
|
867
|
-
'manyToMany'
|
|
868
|
-
].includes(relation)) {
|
|
869
|
-
attr.inversedBy = targetAttribute;
|
|
870
|
-
} else if ([
|
|
871
|
-
'oneToMany'
|
|
872
|
-
].includes(relation)) {
|
|
873
|
-
attr.mappedBy = targetAttribute;
|
|
874
|
-
}
|
|
875
|
-
return acc;
|
|
876
|
-
}
|
|
877
|
-
acc[key] = {
|
|
878
|
-
...attribute,
|
|
879
|
-
...baseProperties
|
|
880
|
-
};
|
|
881
|
-
return acc;
|
|
882
|
-
}, {});
|
|
883
|
-
},
|
|
884
|
-
...createComponentBuilder$1(),
|
|
885
|
-
...createComponentBuilder(),
|
|
886
|
-
/**
|
|
887
|
-
* Write all type to files
|
|
888
|
-
*/ writeFiles () {
|
|
889
|
-
const schemas = [
|
|
890
|
-
...Array.from(tmpComponents.values()),
|
|
891
|
-
...Array.from(tmpContentTypes.values())
|
|
892
|
-
];
|
|
893
|
-
return Promise.all(schemas.map((schema)=>schema.flush())).catch((error)=>{
|
|
894
|
-
strapi.log.error('Error writing schema files');
|
|
895
|
-
strapi.log.error(error);
|
|
896
|
-
return this.rollback();
|
|
897
|
-
}).catch((error)=>{
|
|
898
|
-
strapi.log.error('Error rolling back schema files. You might need to fix your files manually');
|
|
899
|
-
strapi.log.error(error);
|
|
900
|
-
throw new utils.errors.ApplicationError('Invalid schema edition');
|
|
901
|
-
});
|
|
902
|
-
},
|
|
903
|
-
/**
|
|
904
|
-
* rollback all files
|
|
905
|
-
*/ rollback () {
|
|
906
|
-
return Promise.all([
|
|
907
|
-
...Array.from(tmpComponents.values()),
|
|
908
|
-
...Array.from(tmpContentTypes.values())
|
|
909
|
-
].map((schema)=>schema.rollback()));
|
|
910
|
-
}
|
|
911
|
-
};
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
const { ApplicationError } = utils.errors;
|
|
915
|
-
const isContentTypeVisible = (model)=>fp.getOr(true, 'pluginOptions.content-type-builder.visible', model) === true;
|
|
916
|
-
const getRestrictRelationsTo = (contentType)=>{
|
|
917
|
-
const { uid } = contentType;
|
|
918
|
-
if (uid === coreUids.STRAPI_USER) {
|
|
919
|
-
// TODO: replace with an obj { relation: 'x', bidirectional: true|false }
|
|
920
|
-
return [
|
|
921
|
-
'oneWay',
|
|
922
|
-
'manyWay'
|
|
923
|
-
];
|
|
924
|
-
}
|
|
925
|
-
if (uid.startsWith(coreUids.PREFIX) || uid === pluginsUids.UPLOAD_FILE || !isContentTypeVisible(contentType)) {
|
|
926
|
-
return [];
|
|
927
|
-
}
|
|
928
|
-
return null;
|
|
929
|
-
};
|
|
930
|
-
/**
|
|
931
|
-
* Format a contentType info to be used by the front-end
|
|
932
|
-
*/ const formatContentType = (contentType)=>{
|
|
933
|
-
const { uid, kind, modelName, plugin, collectionName, info } = contentType;
|
|
934
|
-
return {
|
|
935
|
-
uid,
|
|
936
|
-
plugin,
|
|
937
|
-
apiID: modelName,
|
|
938
|
-
schema: {
|
|
939
|
-
...utils.contentTypes.getOptions(contentType),
|
|
940
|
-
displayName: info.displayName,
|
|
941
|
-
singularName: info.singularName,
|
|
942
|
-
pluralName: info.pluralName,
|
|
943
|
-
description: _.get(info, 'description', ''),
|
|
944
|
-
pluginOptions: contentType.pluginOptions,
|
|
945
|
-
kind: kind || 'collectionType',
|
|
946
|
-
collectionName,
|
|
947
|
-
attributes: formatAttributes(contentType),
|
|
948
|
-
visible: isContentTypeVisible(contentType),
|
|
949
|
-
restrictRelationsTo: getRestrictRelationsTo(contentType)
|
|
950
|
-
}
|
|
951
|
-
};
|
|
952
|
-
};
|
|
953
|
-
const createContentTypes = async (contentTypes)=>{
|
|
954
|
-
const builder = createBuilder();
|
|
955
|
-
const createdContentTypes = [];
|
|
956
|
-
for (const contentType of contentTypes){
|
|
957
|
-
createdContentTypes.push(await createContentType(contentType, {
|
|
958
|
-
defaultBuilder: builder
|
|
959
|
-
}));
|
|
960
|
-
}
|
|
961
|
-
await builder.writeFiles();
|
|
962
|
-
return createdContentTypes;
|
|
963
|
-
};
|
|
964
|
-
/**
|
|
965
|
-
* Creates a content type and handle the nested components sent with it
|
|
966
|
-
*/ const createContentType = async ({ contentType, components }, options = {})=>{
|
|
967
|
-
const builder = options.defaultBuilder || createBuilder();
|
|
968
|
-
const uidMap = builder.createNewComponentUIDMap(components || []);
|
|
969
|
-
const replaceTmpUIDs = replaceTemporaryUIDs(uidMap);
|
|
970
|
-
const newContentType = builder.createContentType(replaceTmpUIDs(contentType));
|
|
971
|
-
// allow components to target the new contentType
|
|
972
|
-
const targetContentType = (infos)=>{
|
|
973
|
-
Object.keys(infos.attributes).forEach((key)=>{
|
|
974
|
-
const { target } = infos.attributes[key];
|
|
975
|
-
if (target === '__contentType__') {
|
|
976
|
-
infos.attributes[key].target = newContentType.uid;
|
|
977
|
-
}
|
|
978
|
-
});
|
|
979
|
-
return infos;
|
|
980
|
-
};
|
|
981
|
-
components?.forEach((component)=>{
|
|
982
|
-
const options = replaceTmpUIDs(targetContentType(component));
|
|
983
|
-
if (!_.has(component, 'uid')) {
|
|
984
|
-
return builder.createComponent(options);
|
|
985
|
-
}
|
|
986
|
-
return builder.editComponent(options);
|
|
987
|
-
});
|
|
988
|
-
// generate api skeleton
|
|
989
|
-
await generateAPI({
|
|
990
|
-
displayName: contentType.displayName || contentType.info.displayName,
|
|
991
|
-
singularName: contentType.singularName,
|
|
992
|
-
pluralName: contentType.pluralName,
|
|
993
|
-
kind: contentType.kind
|
|
994
|
-
});
|
|
995
|
-
if (!options.defaultBuilder) {
|
|
996
|
-
await builder.writeFiles();
|
|
997
|
-
}
|
|
998
|
-
strapi.eventHub.emit('content-type.create', {
|
|
999
|
-
contentType: newContentType
|
|
1000
|
-
});
|
|
1001
|
-
return newContentType;
|
|
1002
|
-
};
|
|
1003
|
-
/**
|
|
1004
|
-
* Generate an API skeleton
|
|
1005
|
-
*/ const generateAPI = ({ singularName, kind = 'collectionType', pluralName, displayName })=>{
|
|
1006
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
1007
|
-
const strapiGenerators = require('@strapi/generators');
|
|
1008
|
-
return strapiGenerators.generate('content-type', {
|
|
1009
|
-
kind,
|
|
1010
|
-
singularName,
|
|
1011
|
-
id: singularName,
|
|
1012
|
-
pluralName,
|
|
1013
|
-
displayName,
|
|
1014
|
-
destination: 'new',
|
|
1015
|
-
bootstrapApi: true,
|
|
1016
|
-
attributes: []
|
|
1017
|
-
}, {
|
|
1018
|
-
dir: strapi.dirs.app.root
|
|
1019
|
-
});
|
|
1020
|
-
};
|
|
1021
|
-
/**
|
|
1022
|
-
* Edits a contentType and handle the nested contentTypes sent with it
|
|
1023
|
-
*/ const editContentType = async (uid, { contentType, components = [] })=>{
|
|
1024
|
-
const builder = createBuilder();
|
|
1025
|
-
const previousSchema = builder.contentTypes.get(uid).schema;
|
|
1026
|
-
const previousKind = previousSchema.kind;
|
|
1027
|
-
const newKind = contentType.kind || previousKind;
|
|
1028
|
-
// Restore non-visible attributes from previous schema
|
|
1029
|
-
const previousAttributes = previousSchema.attributes;
|
|
1030
|
-
const prevNonVisibleAttributes = utils.contentTypes.getNonVisibleAttributes(previousSchema).reduce((acc, key)=>{
|
|
1031
|
-
if (key in previousAttributes) {
|
|
1032
|
-
acc[key] = previousAttributes[key];
|
|
1033
|
-
}
|
|
1034
|
-
return acc;
|
|
1035
|
-
}, {});
|
|
1036
|
-
contentType.attributes = _.merge(prevNonVisibleAttributes, contentType.attributes);
|
|
1037
|
-
if (newKind !== previousKind && newKind === 'singleType') {
|
|
1038
|
-
const entryCount = await strapi.db.query(uid).count();
|
|
1039
|
-
if (entryCount > 1) {
|
|
1040
|
-
throw new ApplicationError('You cannot convert a collectionType to a singleType when having multiple entries in DB');
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
const uidMap = builder.createNewComponentUIDMap(components);
|
|
1044
|
-
const replaceTmpUIDs = replaceTemporaryUIDs(uidMap);
|
|
1045
|
-
const updatedContentType = builder.editContentType({
|
|
1046
|
-
uid,
|
|
1047
|
-
...replaceTmpUIDs(contentType)
|
|
1048
|
-
});
|
|
1049
|
-
components.forEach((component)=>{
|
|
1050
|
-
if (!_.has(component, 'uid')) {
|
|
1051
|
-
return builder.createComponent(replaceTmpUIDs(component));
|
|
1052
|
-
}
|
|
1053
|
-
return builder.editComponent(replaceTmpUIDs(component));
|
|
1054
|
-
});
|
|
1055
|
-
if (newKind !== previousKind) {
|
|
1056
|
-
const apiHandler = strapi.plugin('content-type-builder').service('api-handler');
|
|
1057
|
-
await apiHandler.backup(uid);
|
|
1058
|
-
try {
|
|
1059
|
-
await apiHandler.clear(uid);
|
|
1060
|
-
// generate new api skeleton
|
|
1061
|
-
await generateAPI({
|
|
1062
|
-
displayName: updatedContentType.schema.info.displayName,
|
|
1063
|
-
singularName: updatedContentType.schema.info.singularName,
|
|
1064
|
-
pluralName: updatedContentType.schema.info.pluralName,
|
|
1065
|
-
kind: updatedContentType.schema.kind
|
|
1066
|
-
});
|
|
1067
|
-
await builder.writeFiles();
|
|
1068
|
-
} catch (error) {
|
|
1069
|
-
strapi.log.error(error);
|
|
1070
|
-
await apiHandler.rollback(uid);
|
|
1071
|
-
}
|
|
1072
|
-
return updatedContentType;
|
|
1073
|
-
}
|
|
1074
|
-
await builder.writeFiles();
|
|
1075
|
-
strapi.eventHub.emit('content-type.update', {
|
|
1076
|
-
contentType: updatedContentType
|
|
1077
|
-
});
|
|
1078
|
-
return updatedContentType;
|
|
1079
|
-
};
|
|
1080
|
-
const deleteContentTypes = async (uids)=>{
|
|
1081
|
-
const builder = createBuilder();
|
|
1082
|
-
const apiHandler = strapi.plugin('content-type-builder').service('api-handler');
|
|
1083
|
-
for (const uid of uids){
|
|
1084
|
-
await deleteContentType(uid, builder);
|
|
1085
|
-
}
|
|
1086
|
-
await builder.writeFiles();
|
|
1087
|
-
for (const uid of uids){
|
|
1088
|
-
try {
|
|
1089
|
-
await apiHandler.clear(uid);
|
|
1090
|
-
} catch (error) {
|
|
1091
|
-
strapi.log.error(error);
|
|
1092
|
-
await apiHandler.rollback(uid);
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
};
|
|
1096
|
-
/**
|
|
1097
|
-
* Deletes a content type and the api files related to it
|
|
1098
|
-
*/ const deleteContentType = async (uid, defaultBuilder = undefined)=>{
|
|
1099
|
-
const builder = defaultBuilder || createBuilder();
|
|
1100
|
-
// make a backup
|
|
1101
|
-
const apiHandler = strapi.plugin('content-type-builder').service('api-handler');
|
|
1102
|
-
await apiHandler.backup(uid);
|
|
1103
|
-
const contentType = builder.deleteContentType(uid);
|
|
1104
|
-
if (!defaultBuilder) {
|
|
1105
|
-
try {
|
|
1106
|
-
await builder.writeFiles();
|
|
1107
|
-
await apiHandler.clear(uid);
|
|
1108
|
-
} catch (error) {
|
|
1109
|
-
await apiHandler.rollback(uid);
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
strapi.eventHub.emit('content-type.delete', {
|
|
1113
|
-
contentType
|
|
1114
|
-
});
|
|
1115
|
-
return contentType;
|
|
1116
|
-
};
|
|
1117
|
-
|
|
1118
|
-
var contentTypes$1 = /*#__PURE__*/Object.freeze({
|
|
1119
|
-
__proto__: null,
|
|
1120
|
-
createContentType: createContentType,
|
|
1121
|
-
createContentTypes: createContentTypes,
|
|
1122
|
-
deleteContentType: deleteContentType,
|
|
1123
|
-
deleteContentTypes: deleteContentTypes,
|
|
1124
|
-
editContentType: editContentType,
|
|
1125
|
-
formatContentType: formatContentType,
|
|
1126
|
-
generateAPI: generateAPI,
|
|
1127
|
-
getRestrictRelationsTo: getRestrictRelationsTo,
|
|
1128
|
-
isContentTypeVisible: isContentTypeVisible
|
|
1129
|
-
});
|
|
1130
|
-
|
|
1131
|
-
/**
|
|
1132
|
-
* Formats a component attributes
|
|
1133
|
-
*/ const formatComponent = (component)=>{
|
|
1134
|
-
const { uid, modelName, connection, collectionName, info, category } = component;
|
|
1135
|
-
return {
|
|
1136
|
-
uid,
|
|
1137
|
-
category,
|
|
1138
|
-
apiId: modelName,
|
|
1139
|
-
schema: {
|
|
1140
|
-
displayName: _.get(info, 'displayName'),
|
|
1141
|
-
description: _.get(info, 'description', ''),
|
|
1142
|
-
icon: _.get(info, 'icon'),
|
|
1143
|
-
connection,
|
|
1144
|
-
collectionName,
|
|
1145
|
-
pluginOptions: component.pluginOptions,
|
|
1146
|
-
attributes: formatAttributes(component)
|
|
1147
|
-
}
|
|
1148
|
-
};
|
|
1149
|
-
};
|
|
1150
|
-
/**
|
|
1151
|
-
* Creates a component and handle the nested components sent with it
|
|
1152
|
-
*/ const createComponent = async ({ component, components = [] })=>{
|
|
1153
|
-
const builder = createBuilder();
|
|
1154
|
-
const uidMap = builder.createNewComponentUIDMap(components);
|
|
1155
|
-
const replaceTmpUIDs = replaceTemporaryUIDs(uidMap);
|
|
1156
|
-
const newComponent = builder.createComponent(replaceTmpUIDs(component));
|
|
1157
|
-
components.forEach((component)=>{
|
|
1158
|
-
if (!_.has(component, 'uid')) {
|
|
1159
|
-
return builder.createComponent(replaceTmpUIDs(component));
|
|
1160
|
-
}
|
|
1161
|
-
return builder.editComponent(replaceTmpUIDs(component));
|
|
1162
|
-
});
|
|
1163
|
-
await builder.writeFiles();
|
|
1164
|
-
strapi.eventHub.emit('component.create', {
|
|
1165
|
-
component: newComponent
|
|
1166
|
-
});
|
|
1167
|
-
return newComponent;
|
|
1168
|
-
};
|
|
1169
|
-
const editComponent = async (uid, { component, components = [] })=>{
|
|
1170
|
-
const builder = createBuilder();
|
|
1171
|
-
const uidMap = builder.createNewComponentUIDMap(components);
|
|
1172
|
-
const replaceTmpUIDs = replaceTemporaryUIDs(uidMap);
|
|
1173
|
-
const updatedComponent = builder.editComponent({
|
|
1174
|
-
uid,
|
|
1175
|
-
...replaceTmpUIDs(component)
|
|
1176
|
-
});
|
|
1177
|
-
components.forEach((component)=>{
|
|
1178
|
-
if (!_.has(component, 'uid')) {
|
|
1179
|
-
return builder.createComponent(replaceTmpUIDs(component));
|
|
1180
|
-
}
|
|
1181
|
-
return builder.editComponent(replaceTmpUIDs(component));
|
|
1182
|
-
});
|
|
1183
|
-
await builder.writeFiles();
|
|
1184
|
-
strapi.eventHub.emit('component.update', {
|
|
1185
|
-
component: updatedComponent
|
|
1186
|
-
});
|
|
1187
|
-
return updatedComponent;
|
|
1188
|
-
};
|
|
1189
|
-
const deleteComponent = async (uid)=>{
|
|
1190
|
-
const builder = createBuilder();
|
|
1191
|
-
const deletedComponent = builder.deleteComponent(uid);
|
|
1192
|
-
await builder.writeFiles();
|
|
1193
|
-
strapi.eventHub.emit('component.delete', {
|
|
1194
|
-
component: deletedComponent
|
|
1195
|
-
});
|
|
1196
|
-
return deletedComponent;
|
|
1197
|
-
};
|
|
1198
|
-
|
|
1199
|
-
var components$1 = /*#__PURE__*/Object.freeze({
|
|
1200
|
-
__proto__: null,
|
|
1201
|
-
createComponent: createComponent,
|
|
1202
|
-
deleteComponent: deleteComponent,
|
|
1203
|
-
editComponent: editComponent,
|
|
1204
|
-
formatComponent: formatComponent
|
|
1205
|
-
});
|
|
1206
|
-
|
|
1207
|
-
/**
|
|
1208
|
-
* Edit a category name and move components to the write folder
|
|
1209
|
-
*/ const editCategory = async (name, infos)=>{
|
|
1210
|
-
const newName = utils.strings.nameToSlug(infos.name);
|
|
1211
|
-
// don't do anything the name doesn't change
|
|
1212
|
-
if (name === newName) return;
|
|
1213
|
-
if (!categoryExists(name)) {
|
|
1214
|
-
throw new utils.errors.ApplicationError('category not found');
|
|
1215
|
-
}
|
|
1216
|
-
if (categoryExists(newName)) {
|
|
1217
|
-
throw new utils.errors.ApplicationError('Name already taken');
|
|
1218
|
-
}
|
|
1219
|
-
const builder = createBuilder();
|
|
1220
|
-
builder.components.forEach((component)=>{
|
|
1221
|
-
const oldUID = component.uid;
|
|
1222
|
-
const newUID = `${newName}.${component.modelName}`;
|
|
1223
|
-
// only edit the components in this specific category
|
|
1224
|
-
if (component.category !== name) return;
|
|
1225
|
-
component.setUID(newUID).setDir(path.join(strapi.dirs.app.components, newName));
|
|
1226
|
-
builder.components.forEach((compo)=>{
|
|
1227
|
-
compo.updateComponent(oldUID, newUID);
|
|
1228
|
-
});
|
|
1229
|
-
builder.contentTypes.forEach((ct)=>{
|
|
1230
|
-
ct.updateComponent(oldUID, newUID);
|
|
1231
|
-
});
|
|
1232
|
-
});
|
|
1233
|
-
await builder.writeFiles();
|
|
1234
|
-
return newName;
|
|
1235
|
-
};
|
|
1236
|
-
/**
|
|
1237
|
-
* Deletes a category and its components
|
|
1238
|
-
*/ const deleteCategory = async (name)=>{
|
|
1239
|
-
if (!categoryExists(name)) {
|
|
1240
|
-
throw new utils.errors.ApplicationError('category not found');
|
|
1241
|
-
}
|
|
1242
|
-
const builder = createBuilder();
|
|
1243
|
-
builder.components.forEach((component)=>{
|
|
1244
|
-
if (component.category === name) {
|
|
1245
|
-
builder.deleteComponent(component.uid);
|
|
1246
|
-
}
|
|
1247
|
-
});
|
|
1248
|
-
await builder.writeFiles();
|
|
1249
|
-
};
|
|
1250
|
-
/**
|
|
1251
|
-
* Checks if a category exists
|
|
1252
|
-
*/ const categoryExists = (name)=>{
|
|
1253
|
-
const matchingIndex = Object.values(strapi.components).findIndex((component)=>component.category === name);
|
|
1254
|
-
return matchingIndex > -1;
|
|
1255
|
-
};
|
|
1256
|
-
|
|
1257
|
-
var componentCategories$1 = /*#__PURE__*/Object.freeze({
|
|
1258
|
-
__proto__: null,
|
|
1259
|
-
deleteCategory: deleteCategory,
|
|
1260
|
-
editCategory: editCategory
|
|
1261
|
-
});
|
|
1262
|
-
|
|
1263
|
-
// use snake_case
|
|
1264
|
-
const reservedAttributes = [
|
|
1265
|
-
// TODO: these need to come from a centralized place so we don't break things accidentally in the future and can share them outside the CTB, for example on Strapi bootstrap prior to schema db sync
|
|
1266
|
-
// ID fields
|
|
1267
|
-
'id',
|
|
1268
|
-
'document_id',
|
|
1269
|
-
// Creator fields
|
|
1270
|
-
'created_at',
|
|
1271
|
-
'updated_at',
|
|
1272
|
-
'published_at',
|
|
1273
|
-
'created_by_id',
|
|
1274
|
-
'updated_by_id',
|
|
1275
|
-
// does not actually conflict because the fields are called *_by_id but we'll leave it to avoid confusion
|
|
1276
|
-
'created_by',
|
|
1277
|
-
'updated_by',
|
|
1278
|
-
// Used for Strapi functionality
|
|
1279
|
-
'entry_id',
|
|
1280
|
-
'status',
|
|
1281
|
-
'localizations',
|
|
1282
|
-
'meta',
|
|
1283
|
-
'locale',
|
|
1284
|
-
'__component',
|
|
1285
|
-
'__contentType',
|
|
1286
|
-
// We support ending with * to denote prefixes
|
|
1287
|
-
'strapi*',
|
|
1288
|
-
'_strapi*',
|
|
1289
|
-
'__strapi*'
|
|
1290
|
-
];
|
|
1291
|
-
// use snake_case
|
|
1292
|
-
const reservedModels = [
|
|
1293
|
-
'boolean',
|
|
1294
|
-
'date',
|
|
1295
|
-
'date_time',
|
|
1296
|
-
'time',
|
|
1297
|
-
'upload',
|
|
1298
|
-
'document',
|
|
1299
|
-
'then',
|
|
1300
|
-
// We support ending with * to denote prefixes
|
|
1301
|
-
'strapi*',
|
|
1302
|
-
'_strapi*',
|
|
1303
|
-
'__strapi*'
|
|
1304
|
-
];
|
|
1305
|
-
const getReservedNames = ()=>{
|
|
1306
|
-
return {
|
|
1307
|
-
models: reservedModels,
|
|
1308
|
-
attributes: reservedAttributes
|
|
1309
|
-
};
|
|
1310
|
-
};
|
|
1311
|
-
// compare snake case to check the actual column names that will be used in the database
|
|
1312
|
-
const isReservedModelName = (name)=>{
|
|
1313
|
-
const snakeCaseName = fp.snakeCase(name);
|
|
1314
|
-
if (reservedModels.includes(snakeCaseName)) {
|
|
1315
|
-
return true;
|
|
1316
|
-
}
|
|
1317
|
-
if (reservedModels.filter((key)=>key.endsWith('*')).map((key)=>key.slice(0, -1)).some((prefix)=>snakeCaseName.startsWith(prefix))) {
|
|
1318
|
-
return true;
|
|
1319
|
-
}
|
|
1320
|
-
return false;
|
|
1321
|
-
};
|
|
1322
|
-
// compare snake case to check the actual column names that will be used in the database
|
|
1323
|
-
const isReservedAttributeName = (name)=>{
|
|
1324
|
-
const snakeCaseName = fp.snakeCase(name);
|
|
1325
|
-
if (reservedAttributes.includes(snakeCaseName)) {
|
|
1326
|
-
return true;
|
|
1327
|
-
}
|
|
1328
|
-
if (reservedAttributes.filter((key)=>key.endsWith('*')).map((key)=>key.slice(0, -1)).some((prefix)=>snakeCaseName.startsWith(prefix))) {
|
|
1329
|
-
return true;
|
|
1330
|
-
}
|
|
1331
|
-
return false;
|
|
1332
|
-
};
|
|
1333
|
-
|
|
1334
|
-
var builder$1 = /*#__PURE__*/Object.freeze({
|
|
1335
|
-
__proto__: null,
|
|
1336
|
-
getReservedNames: getReservedNames,
|
|
1337
|
-
isReservedAttributeName: isReservedAttributeName,
|
|
1338
|
-
isReservedModelName: isReservedModelName,
|
|
1339
|
-
reservedAttributes: reservedAttributes,
|
|
1340
|
-
reservedModels: reservedModels
|
|
1341
|
-
});
|
|
1342
|
-
|
|
1343
|
-
/**
|
|
1344
|
-
* Deletes the API folder of a contentType
|
|
1345
|
-
*/ async function clear(uid) {
|
|
1346
|
-
// TODO double check if this is the correct way to get the apiName
|
|
1347
|
-
const { apiName, modelName } = strapi.contentTypes[uid];
|
|
1348
|
-
const apiFolder = path__namespace.join(strapi.dirs.app.api, apiName);
|
|
1349
|
-
await recursiveRemoveFiles(apiFolder, createDeleteApiFunction(modelName));
|
|
1350
|
-
await deleteBackup(uid);
|
|
1351
|
-
}
|
|
1352
|
-
/**
|
|
1353
|
-
* Backups the API folder of a contentType
|
|
1354
|
-
* @param {string} uid content type uid
|
|
1355
|
-
*/ async function backup(uid) {
|
|
1356
|
-
const { apiName } = strapi.contentTypes[uid];
|
|
1357
|
-
const apiFolder = path__namespace.join(strapi.dirs.app.api, apiName);
|
|
1358
|
-
const backupFolder = path__namespace.join(strapi.dirs.app.api, '.backup', apiName);
|
|
1359
|
-
// backup the api folder
|
|
1360
|
-
await fse__namespace.copy(apiFolder, backupFolder);
|
|
1361
|
-
}
|
|
1362
|
-
/**
|
|
1363
|
-
* Deletes an API backup folder
|
|
1364
|
-
*/ async function deleteBackup(uid) {
|
|
1365
|
-
const { apiName } = strapi.contentTypes[uid];
|
|
1366
|
-
const backupFolder = path__namespace.join(strapi.dirs.app.api, '.backup');
|
|
1367
|
-
const apiBackupFolder = path__namespace.join(strapi.dirs.app.api, '.backup', apiName);
|
|
1368
|
-
await fse__namespace.remove(apiBackupFolder);
|
|
1369
|
-
const list = await fse__namespace.readdir(backupFolder);
|
|
1370
|
-
if (list.length === 0) {
|
|
1371
|
-
await fse__namespace.remove(backupFolder);
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
/**
|
|
1375
|
-
* Rollbacks the API folder of a contentType
|
|
1376
|
-
*/ async function rollback(uid) {
|
|
1377
|
-
const { apiName } = strapi.contentTypes[uid];
|
|
1378
|
-
const apiFolder = path__namespace.join(strapi.dirs.app.api, apiName);
|
|
1379
|
-
const backupFolder = path__namespace.join(strapi.dirs.app.api, '.backup', apiName);
|
|
1380
|
-
try {
|
|
1381
|
-
await fse__namespace.access(backupFolder);
|
|
1382
|
-
} catch {
|
|
1383
|
-
throw new Error('Cannot rollback api that was not backed up');
|
|
1384
|
-
}
|
|
1385
|
-
await fse__namespace.remove(apiFolder);
|
|
1386
|
-
await fse__namespace.copy(backupFolder, apiFolder);
|
|
1387
|
-
await deleteBackup(uid);
|
|
1388
|
-
}
|
|
1389
|
-
/**
|
|
1390
|
-
* Creates a delete function to clear an api folder
|
|
1391
|
-
*/ const createDeleteApiFunction = (baseName)=>{
|
|
1392
|
-
/**
|
|
1393
|
-
* Delets a file in an api.
|
|
1394
|
-
* Will only update routes.json instead of deleting it if other routes are present
|
|
1395
|
-
*/ return async (filePath)=>{
|
|
1396
|
-
const fileName = path__namespace.basename(filePath, path__namespace.extname(filePath));
|
|
1397
|
-
const isSchemaFile = filePath.endsWith(`${baseName}/schema.json`);
|
|
1398
|
-
if (fileName === baseName || isSchemaFile) {
|
|
1399
|
-
return fse__namespace.remove(filePath);
|
|
1400
|
-
}
|
|
1401
|
-
};
|
|
1402
|
-
};
|
|
1403
|
-
/**
|
|
1404
|
-
* Deletes a folder recursively using a delete function
|
|
1405
|
-
* @param {string} folder folder to delete
|
|
1406
|
-
*/ const recursiveRemoveFiles = async (folder, deleteFn)=>{
|
|
1407
|
-
const filesName = await fse__namespace.readdir(folder);
|
|
1408
|
-
for (const fileName of filesName){
|
|
1409
|
-
const filePath = path__namespace.join(folder, fileName);
|
|
1410
|
-
const stat = await fse__namespace.stat(filePath);
|
|
1411
|
-
if (stat.isDirectory()) {
|
|
1412
|
-
await recursiveRemoveFiles(filePath, deleteFn);
|
|
1413
|
-
} else {
|
|
1414
|
-
await deleteFn(filePath);
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
const files = await fse__namespace.readdir(folder);
|
|
1418
|
-
if (files.length === 0) {
|
|
1419
|
-
await fse__namespace.remove(folder);
|
|
1420
|
-
}
|
|
1421
|
-
};
|
|
1422
|
-
|
|
1423
|
-
var apiHandler = /*#__PURE__*/Object.freeze({
|
|
1424
|
-
__proto__: null,
|
|
1425
|
-
backup: backup,
|
|
1426
|
-
clear: clear,
|
|
1427
|
-
rollback: rollback
|
|
1428
|
-
});
|
|
1429
|
-
|
|
1430
|
-
var services = {
|
|
1431
|
-
'content-types': contentTypes$1,
|
|
1432
|
-
components: components$1,
|
|
1433
|
-
'component-categories': componentCategories$1,
|
|
1434
|
-
builder: builder$1,
|
|
1435
|
-
'api-handler': apiHandler
|
|
1436
|
-
};
|
|
1437
|
-
|
|
1438
|
-
function getService(name) {
|
|
1439
|
-
return strapi.plugin('content-type-builder').service(name);
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
|
-
var builder = {
|
|
1443
|
-
getReservedNames (ctx) {
|
|
1444
|
-
ctx.body = getService('builder').getReservedNames();
|
|
1445
|
-
}
|
|
1446
|
-
};
|
|
1447
|
-
|
|
1448
|
-
const validators = {
|
|
1449
|
-
required: utils.yup.boolean(),
|
|
1450
|
-
unique: utils.yup.boolean(),
|
|
1451
|
-
minLength: utils.yup.number().integer().positive(),
|
|
1452
|
-
maxLength: utils.yup.number().integer().positive()
|
|
1453
|
-
};
|
|
1454
|
-
const NAME_REGEX = /^[A-Za-z][_0-9A-Za-z]*$/;
|
|
1455
|
-
const COLLECTION_NAME_REGEX = /^[A-Za-z][-_0-9A-Za-z]*$/;
|
|
1456
|
-
const CATEGORY_NAME_REGEX = /^[A-Za-z][-_0-9A-Za-z]*$/;
|
|
1457
|
-
const ICON_REGEX = /^[A-Za-z0-9][-A-Za-z0-9]*$/;
|
|
1458
|
-
const UID_REGEX = /^[A-Za-z0-9-_.~]*$/;
|
|
1459
|
-
const isValidName = {
|
|
1460
|
-
name: 'isValidName',
|
|
1461
|
-
message: `\${path} must match the following regex: ${NAME_REGEX}`,
|
|
1462
|
-
test: (val)=>val === '' || NAME_REGEX.test(val)
|
|
1463
|
-
};
|
|
1464
|
-
const isValidIcon = {
|
|
1465
|
-
name: 'isValidIcon',
|
|
1466
|
-
message: `\${path} is not a valid icon name. Make sure your icon name starts with an alphanumeric character and only includes alphanumeric characters or dashes.`,
|
|
1467
|
-
test: (val)=>val === '' || ICON_REGEX.test(val)
|
|
1468
|
-
};
|
|
1469
|
-
const isValidUID = {
|
|
1470
|
-
name: 'isValidUID',
|
|
1471
|
-
message: `\${path} must match the following regex: ${UID_REGEX}`,
|
|
1472
|
-
test: (val)=>val === '' || UID_REGEX.test(val)
|
|
1473
|
-
};
|
|
1474
|
-
const isValidCategoryName = {
|
|
1475
|
-
name: 'isValidCategoryName',
|
|
1476
|
-
message: `\${path} must match the following regex: ${CATEGORY_NAME_REGEX}`,
|
|
1477
|
-
test: (val)=>val === '' || CATEGORY_NAME_REGEX.test(val)
|
|
1478
|
-
};
|
|
1479
|
-
const isValidCollectionName = {
|
|
1480
|
-
name: 'isValidCollectionName',
|
|
1481
|
-
message: `\${path} must match the following regex: ${COLLECTION_NAME_REGEX}`,
|
|
1482
|
-
test: (val)=>val === '' || COLLECTION_NAME_REGEX.test(val)
|
|
1483
|
-
};
|
|
1484
|
-
const isValidKey = (key)=>({
|
|
1485
|
-
name: 'isValidKey',
|
|
1486
|
-
message: `Attribute name '${key}' must match the following regex: ${NAME_REGEX}`,
|
|
1487
|
-
test: ()=>NAME_REGEX.test(key)
|
|
1488
|
-
});
|
|
1489
|
-
const isValidEnum = {
|
|
1490
|
-
name: 'isValidEnum',
|
|
1491
|
-
message: '${path} should not start with number',
|
|
1492
|
-
test: (val)=>val === '' || !utils.strings.startsWithANumber(val)
|
|
1493
|
-
};
|
|
1494
|
-
const areEnumValuesUnique = {
|
|
1495
|
-
name: 'areEnumValuesUnique',
|
|
1496
|
-
message: '${path} cannot contain duplicate values',
|
|
1497
|
-
test (values) {
|
|
1498
|
-
const filtered = [
|
|
1499
|
-
...new Set(values)
|
|
1500
|
-
];
|
|
1501
|
-
return filtered.length === values.length;
|
|
1502
|
-
}
|
|
1503
|
-
};
|
|
1504
|
-
const isValidRegExpPattern = {
|
|
1505
|
-
name: 'isValidRegExpPattern',
|
|
1506
|
-
message: '${path} must be a valid RexExp pattern string',
|
|
1507
|
-
test: (val)=>val === '' || !!new RegExp(val)
|
|
1508
|
-
};
|
|
1509
|
-
const isValidDefaultJSON = {
|
|
1510
|
-
name: 'isValidDefaultJSON',
|
|
1511
|
-
message: '${path} is not a valid JSON',
|
|
1512
|
-
test (val) {
|
|
1513
|
-
if (val === undefined) {
|
|
1514
|
-
return true;
|
|
1515
|
-
}
|
|
1516
|
-
if (_.isNumber(val) || _.isNull(val) || _.isObject(val) || _.isArray(val)) {
|
|
1517
|
-
return true;
|
|
1518
|
-
}
|
|
1519
|
-
try {
|
|
1520
|
-
JSON.parse(val);
|
|
1521
|
-
return true;
|
|
1522
|
-
} catch (err) {
|
|
1523
|
-
return false;
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
};
|
|
1527
|
-
|
|
1528
|
-
const componentCategorySchema = utils.yup.object({
|
|
1529
|
-
name: utils.yup.string().min(3).test(isValidCategoryName).required('name.required')
|
|
1530
|
-
}).noUnknown();
|
|
1531
|
-
var validateComponentCategory = utils.validateYupSchema(componentCategorySchema);
|
|
1532
|
-
|
|
1533
|
-
var componentCategories = {
|
|
1534
|
-
async editCategory (ctx) {
|
|
1535
|
-
const body = ctx.request.body;
|
|
1536
|
-
try {
|
|
1537
|
-
await validateComponentCategory(body);
|
|
1538
|
-
} catch (error) {
|
|
1539
|
-
return ctx.send({
|
|
1540
|
-
error
|
|
1541
|
-
}, 400);
|
|
1542
|
-
}
|
|
1543
|
-
const { name } = ctx.params;
|
|
1544
|
-
strapi.reload.isWatching = false;
|
|
1545
|
-
const componentCategoryService = getService('component-categories');
|
|
1546
|
-
const newName = await componentCategoryService.editCategory(name, body);
|
|
1547
|
-
setImmediate(()=>strapi.reload());
|
|
1548
|
-
ctx.send({
|
|
1549
|
-
name: newName
|
|
1550
|
-
});
|
|
1551
|
-
},
|
|
1552
|
-
async deleteCategory (ctx) {
|
|
1553
|
-
const { name } = ctx.params;
|
|
1554
|
-
strapi.reload.isWatching = false;
|
|
1555
|
-
const componentCategoryService = getService('component-categories');
|
|
1556
|
-
await componentCategoryService.deleteCategory(name);
|
|
1557
|
-
setImmediate(()=>strapi.reload());
|
|
1558
|
-
ctx.send({
|
|
1559
|
-
name
|
|
1560
|
-
});
|
|
1561
|
-
}
|
|
1562
|
-
};
|
|
1563
|
-
|
|
1564
|
-
const maxLengthIsGreaterThanOrEqualToMinLength = {
|
|
1565
|
-
name: 'isGreaterThanMin',
|
|
1566
|
-
message: 'maxLength must be greater or equal to minLength',
|
|
1567
|
-
test (value) {
|
|
1568
|
-
const { minLength } = this.parent;
|
|
1569
|
-
return !(!_.isUndefined(minLength) && !_.isUndefined(value) && value < minLength);
|
|
1570
|
-
}
|
|
1571
|
-
};
|
|
1572
|
-
const getTypeValidator = (attribute, { types, modelType, attributes })=>{
|
|
1573
|
-
return utils.yup.object({
|
|
1574
|
-
type: utils.yup.string().oneOf([
|
|
1575
|
-
...types
|
|
1576
|
-
]).required(),
|
|
1577
|
-
configurable: utils.yup.boolean().nullable(),
|
|
1578
|
-
private: utils.yup.boolean().nullable(),
|
|
1579
|
-
pluginOptions: utils.yup.object(),
|
|
1580
|
-
...getTypeShape(attribute, {
|
|
1581
|
-
modelType,
|
|
1582
|
-
attributes
|
|
1583
|
-
})
|
|
1584
|
-
});
|
|
1585
|
-
};
|
|
1586
|
-
const getTypeShape = (attribute, { attributes } = {})=>{
|
|
1587
|
-
switch(attribute.type){
|
|
1588
|
-
/**
|
|
1589
|
-
* complex types
|
|
1590
|
-
*/ case 'media':
|
|
1591
|
-
{
|
|
1592
|
-
return {
|
|
1593
|
-
multiple: utils.yup.boolean(),
|
|
1594
|
-
required: validators.required,
|
|
1595
|
-
allowedTypes: utils.yup.array().of(utils.yup.string().oneOf([
|
|
1596
|
-
'images',
|
|
1597
|
-
'videos',
|
|
1598
|
-
'files',
|
|
1599
|
-
'audios'
|
|
1600
|
-
])).min(1)
|
|
1601
|
-
};
|
|
1602
|
-
}
|
|
1603
|
-
case 'uid':
|
|
1604
|
-
{
|
|
1605
|
-
return {
|
|
1606
|
-
required: validators.required,
|
|
1607
|
-
targetField: utils.yup.string().oneOf(Object.keys(attributes).filter((key)=>VALID_UID_TARGETS.includes(_.get(attributes[key], 'type')))).nullable(),
|
|
1608
|
-
default: utils.yup.string().test('isValidDefaultUID', 'cannot define a default UID if the targetField is set', function(value) {
|
|
1609
|
-
const { targetField } = this.parent;
|
|
1610
|
-
return !!(_.isNil(targetField) || _.isNil(value));
|
|
1611
|
-
}).test(isValidUID),
|
|
1612
|
-
minLength: validators.minLength,
|
|
1613
|
-
maxLength: validators.maxLength.max(256).test(maxLengthIsGreaterThanOrEqualToMinLength),
|
|
1614
|
-
options: utils.yup.object().shape({
|
|
1615
|
-
separator: utils.yup.string(),
|
|
1616
|
-
lowercase: utils.yup.boolean(),
|
|
1617
|
-
decamelize: utils.yup.boolean(),
|
|
1618
|
-
customReplacements: utils.yup.array().of(utils.yup.array().of(utils.yup.string()).min(2).max(2)),
|
|
1619
|
-
preserveLeadingUnderscore: utils.yup.boolean()
|
|
1620
|
-
})
|
|
1621
|
-
};
|
|
1622
|
-
}
|
|
1623
|
-
/**
|
|
1624
|
-
* scalar types
|
|
1625
|
-
*/ case 'string':
|
|
1626
|
-
case 'text':
|
|
1627
|
-
{
|
|
1628
|
-
return {
|
|
1629
|
-
default: utils.yup.string(),
|
|
1630
|
-
required: validators.required,
|
|
1631
|
-
unique: validators.unique,
|
|
1632
|
-
minLength: validators.minLength,
|
|
1633
|
-
maxLength: validators.maxLength,
|
|
1634
|
-
regex: utils.yup.string().test(isValidRegExpPattern)
|
|
1635
|
-
};
|
|
1636
|
-
}
|
|
1637
|
-
case 'richtext':
|
|
1638
|
-
{
|
|
1639
|
-
return {
|
|
1640
|
-
default: utils.yup.string(),
|
|
1641
|
-
required: validators.required,
|
|
1642
|
-
minLength: validators.minLength,
|
|
1643
|
-
maxLength: validators.maxLength
|
|
1644
|
-
};
|
|
1645
|
-
}
|
|
1646
|
-
case 'blocks':
|
|
1647
|
-
{
|
|
1648
|
-
return {
|
|
1649
|
-
required: validators.required
|
|
1650
|
-
};
|
|
1651
|
-
}
|
|
1652
|
-
case 'json':
|
|
1653
|
-
{
|
|
1654
|
-
return {
|
|
1655
|
-
default: utils.yup.mixed().test(isValidDefaultJSON),
|
|
1656
|
-
required: validators.required
|
|
1657
|
-
};
|
|
1658
|
-
}
|
|
1659
|
-
case 'enumeration':
|
|
1660
|
-
{
|
|
1661
|
-
return {
|
|
1662
|
-
enum: utils.yup.array().of(utils.yup.string().test(isValidEnum).required()).min(1).test(areEnumValuesUnique).required(),
|
|
1663
|
-
default: utils.yup.string().when('enum', (enumVal)=>utils.yup.string().oneOf(enumVal)),
|
|
1664
|
-
enumName: utils.yup.string().test(isValidName),
|
|
1665
|
-
required: validators.required
|
|
1666
|
-
};
|
|
1667
|
-
}
|
|
1668
|
-
case 'password':
|
|
1669
|
-
{
|
|
1670
|
-
return {
|
|
1671
|
-
required: validators.required,
|
|
1672
|
-
minLength: validators.minLength,
|
|
1673
|
-
maxLength: validators.maxLength
|
|
1674
|
-
};
|
|
1675
|
-
}
|
|
1676
|
-
case 'email':
|
|
1677
|
-
{
|
|
1678
|
-
return {
|
|
1679
|
-
default: utils.yup.string().email(),
|
|
1680
|
-
required: validators.required,
|
|
1681
|
-
unique: validators.unique,
|
|
1682
|
-
minLength: validators.minLength,
|
|
1683
|
-
maxLength: validators.maxLength
|
|
1684
|
-
};
|
|
1685
|
-
}
|
|
1686
|
-
case 'integer':
|
|
1687
|
-
{
|
|
1688
|
-
return {
|
|
1689
|
-
default: utils.yup.number().integer(),
|
|
1690
|
-
required: validators.required,
|
|
1691
|
-
unique: validators.unique,
|
|
1692
|
-
min: utils.yup.number().integer(),
|
|
1693
|
-
max: utils.yup.number().integer()
|
|
1694
|
-
};
|
|
1695
|
-
}
|
|
1696
|
-
case 'biginteger':
|
|
1697
|
-
{
|
|
1698
|
-
return {
|
|
1699
|
-
default: utils.yup.string().nullable().matches(/^\d*$/),
|
|
1700
|
-
required: validators.required,
|
|
1701
|
-
unique: validators.unique,
|
|
1702
|
-
min: utils.yup.string().nullable().matches(/^\d*$/),
|
|
1703
|
-
max: utils.yup.string().nullable().matches(/^\d*$/)
|
|
1704
|
-
};
|
|
1705
|
-
}
|
|
1706
|
-
case 'float':
|
|
1707
|
-
{
|
|
1708
|
-
return {
|
|
1709
|
-
default: utils.yup.number(),
|
|
1710
|
-
required: validators.required,
|
|
1711
|
-
unique: validators.unique,
|
|
1712
|
-
min: utils.yup.number(),
|
|
1713
|
-
max: utils.yup.number()
|
|
1714
|
-
};
|
|
1715
|
-
}
|
|
1716
|
-
case 'decimal':
|
|
1717
|
-
{
|
|
1718
|
-
return {
|
|
1719
|
-
default: utils.yup.number(),
|
|
1720
|
-
required: validators.required,
|
|
1721
|
-
unique: validators.unique,
|
|
1722
|
-
min: utils.yup.number(),
|
|
1723
|
-
max: utils.yup.number()
|
|
1724
|
-
};
|
|
1725
|
-
}
|
|
1726
|
-
case 'time':
|
|
1727
|
-
case 'datetime':
|
|
1728
|
-
case 'date':
|
|
1729
|
-
{
|
|
1730
|
-
return {
|
|
1731
|
-
default: utils.yup.string(),
|
|
1732
|
-
required: validators.required,
|
|
1733
|
-
unique: validators.unique
|
|
1734
|
-
};
|
|
1735
|
-
}
|
|
1736
|
-
case 'boolean':
|
|
1737
|
-
{
|
|
1738
|
-
return {
|
|
1739
|
-
default: utils.yup.boolean(),
|
|
1740
|
-
required: validators.required
|
|
1741
|
-
};
|
|
1742
|
-
}
|
|
1743
|
-
case 'component':
|
|
1744
|
-
{
|
|
1745
|
-
return {
|
|
1746
|
-
required: validators.required,
|
|
1747
|
-
repeatable: utils.yup.boolean(),
|
|
1748
|
-
// TODO: Add correct server validation for nested components
|
|
1749
|
-
component: utils.yup.string().required(),
|
|
1750
|
-
min: utils.yup.number(),
|
|
1751
|
-
max: utils.yup.number()
|
|
1752
|
-
};
|
|
1753
|
-
}
|
|
1754
|
-
case 'dynamiczone':
|
|
1755
|
-
{
|
|
1756
|
-
return {
|
|
1757
|
-
required: validators.required,
|
|
1758
|
-
components: utils.yup.array().of(utils.yup.string().required()).test('isArray', '${path} must be an array', (value)=>Array.isArray(value)).min(1),
|
|
1759
|
-
min: utils.yup.number(),
|
|
1760
|
-
max: utils.yup.number()
|
|
1761
|
-
};
|
|
1762
|
-
}
|
|
1763
|
-
default:
|
|
1764
|
-
{
|
|
1765
|
-
return {};
|
|
1766
|
-
}
|
|
1767
|
-
}
|
|
1768
|
-
};
|
|
1769
|
-
|
|
1770
|
-
const STRAPI_USER_RELATIONS = [
|
|
1771
|
-
'oneToOne',
|
|
1772
|
-
'oneToMany'
|
|
1773
|
-
];
|
|
1774
|
-
const isValidRelation = (validNatures)=>function(value) {
|
|
1775
|
-
// NOTE: In case of an undefined value, delegate the check to .required()
|
|
1776
|
-
if (value === undefined) {
|
|
1777
|
-
return true;
|
|
1778
|
-
}
|
|
1779
|
-
if (this.parent.target === coreUids.STRAPI_USER) {
|
|
1780
|
-
if (!validNatures.includes(value) || !fp.isUndefined(this.parent.targetAttribute)) {
|
|
1781
|
-
return this.createError({
|
|
1782
|
-
path: this.path,
|
|
1783
|
-
message: `must be one of the following values: ${STRAPI_USER_RELATIONS.join(', ')}`
|
|
1784
|
-
});
|
|
1785
|
-
}
|
|
1786
|
-
}
|
|
1787
|
-
return validNatures.includes(value) ? true : this.createError({
|
|
1788
|
-
path: this.path,
|
|
1789
|
-
message: `must be one of the following values: ${validNatures.join(', ')}`
|
|
1790
|
-
});
|
|
1791
|
-
};
|
|
1792
|
-
const getRelationValidator = (attribute, allowedRelations)=>{
|
|
1793
|
-
const contentTypesUIDs = Object.keys(strapi.contentTypes).filter((key)=>strapi.contentTypes[key].kind === typeKinds.COLLECTION_TYPE).filter((key)=>!key.startsWith(coreUids.PREFIX) || key === coreUids.STRAPI_USER).concat([
|
|
1794
|
-
'__self__',
|
|
1795
|
-
'__contentType__'
|
|
1796
|
-
]);
|
|
1797
|
-
const base = {
|
|
1798
|
-
type: utils.yup.string().oneOf([
|
|
1799
|
-
'relation'
|
|
1800
|
-
]).required(),
|
|
1801
|
-
relation: utils.yup.string().test('isValidRelation', isValidRelation(allowedRelations)).required(),
|
|
1802
|
-
configurable: utils.yup.boolean().nullable(),
|
|
1803
|
-
private: utils.yup.boolean().nullable(),
|
|
1804
|
-
pluginOptions: utils.yup.object()
|
|
1805
|
-
};
|
|
1806
|
-
switch(attribute.relation){
|
|
1807
|
-
case 'oneToOne':
|
|
1808
|
-
case 'oneToMany':
|
|
1809
|
-
case 'manyToOne':
|
|
1810
|
-
case 'manyToMany':
|
|
1811
|
-
case 'morphOne':
|
|
1812
|
-
case 'morphMany':
|
|
1813
|
-
{
|
|
1814
|
-
return utils.yup.object({
|
|
1815
|
-
...base,
|
|
1816
|
-
target: utils.yup.string().oneOf(contentTypesUIDs).required(),
|
|
1817
|
-
targetAttribute: utils.yup.string().test(isValidName).nullable()
|
|
1818
|
-
});
|
|
1819
|
-
}
|
|
1820
|
-
case 'morphToOne':
|
|
1821
|
-
case 'morphToMany':
|
|
1822
|
-
default:
|
|
1823
|
-
{
|
|
1824
|
-
return utils.yup.object({
|
|
1825
|
-
...base
|
|
1826
|
-
});
|
|
1827
|
-
}
|
|
1828
|
-
}
|
|
1829
|
-
};
|
|
1830
|
-
|
|
1831
|
-
const createSchema = (types, relations, { modelType } = {})=>{
|
|
1832
|
-
const shape = {
|
|
1833
|
-
description: utils.yup.string(),
|
|
1834
|
-
options: utils.yup.object(),
|
|
1835
|
-
pluginOptions: utils.yup.object(),
|
|
1836
|
-
collectionName: utils.yup.string().nullable().test(isValidCollectionName),
|
|
1837
|
-
attributes: createAttributesValidator({
|
|
1838
|
-
types,
|
|
1839
|
-
relations,
|
|
1840
|
-
modelType
|
|
1841
|
-
}),
|
|
1842
|
-
draftAndPublish: utils.yup.boolean()
|
|
1843
|
-
};
|
|
1844
|
-
if (modelType === modelTypes.CONTENT_TYPE) {
|
|
1845
|
-
shape.kind = utils.yup.string().oneOf([
|
|
1846
|
-
typeKinds.SINGLE_TYPE,
|
|
1847
|
-
typeKinds.COLLECTION_TYPE
|
|
1848
|
-
]).nullable();
|
|
1849
|
-
}
|
|
1850
|
-
return utils.yup.object(shape).noUnknown();
|
|
1851
|
-
};
|
|
1852
|
-
const createAttributesValidator = ({ types, modelType, relations })=>{
|
|
1853
|
-
return utils.yup.lazy((attributes)=>{
|
|
1854
|
-
return utils.yup.object().shape(_.mapValues(attributes, (attribute, key)=>{
|
|
1855
|
-
if (isForbiddenKey(key)) {
|
|
1856
|
-
return forbiddenValidator();
|
|
1857
|
-
}
|
|
1858
|
-
if (isConflictingKey(key, attributes)) {
|
|
1859
|
-
return conflictingKeysValidator(key);
|
|
1860
|
-
}
|
|
1861
|
-
if (attribute.type === 'relation') {
|
|
1862
|
-
return getRelationValidator(attribute, relations).test(isValidKey(key));
|
|
1863
|
-
}
|
|
1864
|
-
if (_.has(attribute, 'type')) {
|
|
1865
|
-
return getTypeValidator(attribute, {
|
|
1866
|
-
types,
|
|
1867
|
-
modelType,
|
|
1868
|
-
attributes
|
|
1869
|
-
}).test(isValidKey(key));
|
|
1870
|
-
}
|
|
1871
|
-
return typeOrRelationValidator;
|
|
1872
|
-
})).required('attributes.required');
|
|
1873
|
-
});
|
|
1874
|
-
};
|
|
1875
|
-
const isConflictingKey = (key, attributes)=>{
|
|
1876
|
-
const snakeCaseKey = fp.snakeCase(key);
|
|
1877
|
-
return Object.keys(attributes).some((existingKey)=>{
|
|
1878
|
-
if (existingKey === key) return false; // don't compare against itself
|
|
1879
|
-
return fp.snakeCase(existingKey) === snakeCaseKey;
|
|
1880
|
-
});
|
|
1881
|
-
};
|
|
1882
|
-
const isForbiddenKey = (key)=>{
|
|
1883
|
-
return getService('builder').isReservedAttributeName(key);
|
|
1884
|
-
};
|
|
1885
|
-
const forbiddenValidator = ()=>{
|
|
1886
|
-
const reservedNames = [
|
|
1887
|
-
...getService('builder').getReservedNames().attributes
|
|
1888
|
-
];
|
|
1889
|
-
return utils.yup.mixed().test({
|
|
1890
|
-
name: 'forbiddenKeys',
|
|
1891
|
-
message: `Attribute keys cannot be one of ${reservedNames.join(', ')}`,
|
|
1892
|
-
test: ()=>false
|
|
1893
|
-
});
|
|
1894
|
-
};
|
|
1895
|
-
const conflictingKeysValidator = (key)=>{
|
|
1896
|
-
return utils.yup.mixed().test({
|
|
1897
|
-
name: 'conflictingKeys',
|
|
1898
|
-
message: `Attribute ${key} conflicts with an existing key`,
|
|
1899
|
-
test: ()=>false
|
|
1900
|
-
});
|
|
1901
|
-
};
|
|
1902
|
-
const typeOrRelationValidator = utils.yup.object().test({
|
|
1903
|
-
name: 'mustHaveTypeOrTarget',
|
|
1904
|
-
message: 'Attribute must have either a type or a target',
|
|
1905
|
-
test: ()=>false
|
|
1906
|
-
});
|
|
1907
|
-
|
|
1908
|
-
const hasDefaultAttribute = (attribute)=>{
|
|
1909
|
-
return 'default' in attribute;
|
|
1910
|
-
};
|
|
1911
|
-
|
|
1912
|
-
const removeEmptyDefaults = (data)=>{
|
|
1913
|
-
const { attributes } = data || {};
|
|
1914
|
-
Object.keys(attributes).forEach((attributeName)=>{
|
|
1915
|
-
const attribute = attributes[attributeName];
|
|
1916
|
-
if (hasDefaultAttribute(attribute) && attribute.default === '') {
|
|
1917
|
-
attribute.default = undefined;
|
|
1918
|
-
}
|
|
1919
|
-
});
|
|
1920
|
-
};
|
|
1921
|
-
const removeDeletedUIDTargetFields = (data)=>{
|
|
1922
|
-
if (_.has(data, 'attributes')) {
|
|
1923
|
-
Object.values(data.attributes).forEach((attribute)=>{
|
|
1924
|
-
if (attribute.type === 'uid' && !_.isUndefined(attribute.targetField) && !_.has(data.attributes, attribute.targetField)) {
|
|
1925
|
-
attribute.targetField = undefined;
|
|
1926
|
-
}
|
|
1927
|
-
});
|
|
1928
|
-
}
|
|
1929
|
-
};
|
|
1930
|
-
|
|
1931
|
-
const VALID_RELATIONS$1 = [
|
|
1932
|
-
'oneToOne',
|
|
1933
|
-
'oneToMany'
|
|
1934
|
-
];
|
|
1935
|
-
const VALID_TYPES$1 = [
|
|
1936
|
-
...DEFAULT_TYPES,
|
|
1937
|
-
'component',
|
|
1938
|
-
'customField'
|
|
1939
|
-
];
|
|
1940
|
-
const componentSchema = createSchema(VALID_TYPES$1, VALID_RELATIONS$1, {
|
|
1941
|
-
modelType: modelTypes.COMPONENT
|
|
1942
|
-
}).shape({
|
|
1943
|
-
displayName: utils.yup.string().min(1).required('displayName.required'),
|
|
1944
|
-
icon: utils.yup.string().nullable().test(isValidIcon),
|
|
1945
|
-
category: utils.yup.string().nullable().test(isValidCategoryName).required('category.required')
|
|
1946
|
-
}).required().noUnknown();
|
|
1947
|
-
const nestedComponentSchema = utils.yup.array().of(componentSchema.shape({
|
|
1948
|
-
uid: utils.yup.string(),
|
|
1949
|
-
tmpUID: utils.yup.string()
|
|
1950
|
-
}).test({
|
|
1951
|
-
name: 'mustHaveUIDOrTmpUID',
|
|
1952
|
-
message: 'Component must have a uid or a tmpUID',
|
|
1953
|
-
test (attr) {
|
|
1954
|
-
if (_.has(attr, 'uid') && _.has(attr, 'tmpUID')) return false;
|
|
1955
|
-
if (!_.has(attr, 'uid') && !_.has(attr, 'tmpUID')) return false;
|
|
1956
|
-
return true;
|
|
1957
|
-
}
|
|
1958
|
-
}).required().noUnknown());
|
|
1959
|
-
const componentInputSchema = utils.yup.object({
|
|
1960
|
-
component: componentSchema,
|
|
1961
|
-
components: nestedComponentSchema
|
|
1962
|
-
}).noUnknown();
|
|
1963
|
-
const validateComponentInput = utils.validateYupSchema(componentInputSchema);
|
|
1964
|
-
const updateComponentInputSchema = utils.yup.object({
|
|
1965
|
-
component: componentSchema,
|
|
1966
|
-
components: nestedComponentSchema
|
|
1967
|
-
}).noUnknown();
|
|
1968
|
-
const validateUpdateComponentInput = (data)=>{
|
|
1969
|
-
if (_.has(data, 'component') && data.component) {
|
|
1970
|
-
removeEmptyDefaults(data.component);
|
|
1971
|
-
}
|
|
1972
|
-
if (_.has(data, 'components') && Array.isArray(data.components)) {
|
|
1973
|
-
data.components.forEach((data)=>{
|
|
1974
|
-
if (_.has(data, 'uid')) {
|
|
1975
|
-
removeEmptyDefaults(data);
|
|
1976
|
-
}
|
|
1977
|
-
});
|
|
1978
|
-
}
|
|
1979
|
-
return utils.validateYupSchema(updateComponentInputSchema)(data);
|
|
1980
|
-
};
|
|
1981
|
-
|
|
1982
|
-
/**
|
|
1983
|
-
* Components controller
|
|
1984
|
-
*/ var components = {
|
|
1985
|
-
/**
|
|
1986
|
-
* GET /components handler
|
|
1987
|
-
* Returns a list of available components
|
|
1988
|
-
* @param {Object} ctx - koa context
|
|
1989
|
-
*/ async getComponents (ctx) {
|
|
1990
|
-
const componentService = getService('components');
|
|
1991
|
-
const componentUIDs = Object.keys(strapi.components);
|
|
1992
|
-
const data = componentUIDs.map((uid)=>{
|
|
1993
|
-
return componentService.formatComponent(strapi.components[uid]);
|
|
1994
|
-
});
|
|
1995
|
-
ctx.send({
|
|
1996
|
-
data
|
|
1997
|
-
});
|
|
1998
|
-
},
|
|
1999
|
-
/**
|
|
2000
|
-
* GET /components/:uid
|
|
2001
|
-
* Returns a specific component
|
|
2002
|
-
* @param {Object} ctx - koa context
|
|
2003
|
-
*/ async getComponent (ctx) {
|
|
2004
|
-
const { uid } = ctx.params;
|
|
2005
|
-
const component = strapi.components[uid];
|
|
2006
|
-
if (!component) {
|
|
2007
|
-
return ctx.send({
|
|
2008
|
-
error: 'component.notFound'
|
|
2009
|
-
}, 404);
|
|
2010
|
-
}
|
|
2011
|
-
const componentService = getService('components');
|
|
2012
|
-
ctx.send({
|
|
2013
|
-
data: componentService.formatComponent(component)
|
|
2014
|
-
});
|
|
2015
|
-
},
|
|
2016
|
-
/**
|
|
2017
|
-
* POST /components
|
|
2018
|
-
* Creates a component and returns its infos
|
|
2019
|
-
* @param {Object} ctx - koa context
|
|
2020
|
-
*/ async createComponent (ctx) {
|
|
2021
|
-
const body = ctx.request.body;
|
|
2022
|
-
try {
|
|
2023
|
-
await validateComponentInput(body);
|
|
2024
|
-
} catch (error) {
|
|
2025
|
-
return ctx.send({
|
|
2026
|
-
error
|
|
2027
|
-
}, 400);
|
|
2028
|
-
}
|
|
2029
|
-
try {
|
|
2030
|
-
strapi.reload.isWatching = false;
|
|
2031
|
-
const componentService = getService('components');
|
|
2032
|
-
const component = await componentService.createComponent({
|
|
2033
|
-
component: body.component,
|
|
2034
|
-
components: body.components
|
|
2035
|
-
});
|
|
2036
|
-
setImmediate(()=>strapi.reload());
|
|
2037
|
-
ctx.send({
|
|
2038
|
-
data: {
|
|
2039
|
-
uid: component.uid
|
|
2040
|
-
}
|
|
2041
|
-
}, 201);
|
|
2042
|
-
} catch (error) {
|
|
2043
|
-
strapi.log.error(error);
|
|
2044
|
-
ctx.send({
|
|
2045
|
-
error: error?.message || 'Unknown error'
|
|
2046
|
-
}, 400);
|
|
2047
|
-
}
|
|
2048
|
-
},
|
|
2049
|
-
/**
|
|
2050
|
-
* PUT /components/:uid
|
|
2051
|
-
* Updates a component and return its infos
|
|
2052
|
-
* @param {Object} ctx - koa context - enhanced koa context
|
|
2053
|
-
*/ async updateComponent (ctx) {
|
|
2054
|
-
const { uid } = ctx.params;
|
|
2055
|
-
const body = ctx.request.body;
|
|
2056
|
-
if (!_.has(strapi.components, uid)) {
|
|
2057
|
-
return ctx.send({
|
|
2058
|
-
error: 'component.notFound'
|
|
2059
|
-
}, 404);
|
|
2060
|
-
}
|
|
2061
|
-
try {
|
|
2062
|
-
await validateUpdateComponentInput(body);
|
|
2063
|
-
} catch (error) {
|
|
2064
|
-
return ctx.send({
|
|
2065
|
-
error
|
|
2066
|
-
}, 400);
|
|
2067
|
-
}
|
|
2068
|
-
try {
|
|
2069
|
-
strapi.reload.isWatching = false;
|
|
2070
|
-
const componentService = getService('components');
|
|
2071
|
-
const component = await componentService.editComponent(uid, {
|
|
2072
|
-
component: body.component,
|
|
2073
|
-
components: body.components
|
|
2074
|
-
});
|
|
2075
|
-
setImmediate(()=>strapi.reload());
|
|
2076
|
-
ctx.send({
|
|
2077
|
-
data: {
|
|
2078
|
-
uid: component.uid
|
|
2079
|
-
}
|
|
2080
|
-
});
|
|
2081
|
-
} catch (error) {
|
|
2082
|
-
strapi.log.error(error);
|
|
2083
|
-
ctx.send({
|
|
2084
|
-
error: error?.message || 'Unknown error'
|
|
2085
|
-
}, 400);
|
|
2086
|
-
}
|
|
2087
|
-
},
|
|
2088
|
-
/**
|
|
2089
|
-
* DELETE /components/:uid
|
|
2090
|
-
* Deletes a components and returns its old infos
|
|
2091
|
-
* @param {Object} ctx - koa context
|
|
2092
|
-
*/ async deleteComponent (ctx) {
|
|
2093
|
-
const { uid } = ctx.params;
|
|
2094
|
-
if (!_.has(strapi.components, uid)) {
|
|
2095
|
-
return ctx.send({
|
|
2096
|
-
error: 'component.notFound'
|
|
2097
|
-
}, 404);
|
|
2098
|
-
}
|
|
2099
|
-
try {
|
|
2100
|
-
strapi.reload.isWatching = false;
|
|
2101
|
-
const componentService = getService('components');
|
|
2102
|
-
const component = await componentService.deleteComponent(uid);
|
|
2103
|
-
setImmediate(()=>strapi.reload());
|
|
2104
|
-
ctx.send({
|
|
2105
|
-
data: {
|
|
2106
|
-
uid: component.uid
|
|
2107
|
-
}
|
|
2108
|
-
});
|
|
2109
|
-
} catch (error) {
|
|
2110
|
-
strapi.log.error(error);
|
|
2111
|
-
ctx.send({
|
|
2112
|
-
error: error?.message || 'Unknown error'
|
|
2113
|
-
}, 400);
|
|
2114
|
-
}
|
|
2115
|
-
}
|
|
2116
|
-
};
|
|
2117
|
-
|
|
2118
|
-
/* eslint-disable no-template-curly-in-string */ // yup templates need to be in this format
|
|
2119
|
-
/**
|
|
2120
|
-
* Allowed relation per type kind
|
|
2121
|
-
*/ const VALID_RELATIONS = {
|
|
2122
|
-
[typeKinds.SINGLE_TYPE]: [
|
|
2123
|
-
'oneToOne',
|
|
2124
|
-
'oneToMany',
|
|
2125
|
-
'morphOne',
|
|
2126
|
-
'morphMany',
|
|
2127
|
-
'morphToOne',
|
|
2128
|
-
'morphToMany'
|
|
2129
|
-
],
|
|
2130
|
-
[typeKinds.COLLECTION_TYPE]: [
|
|
2131
|
-
'oneToOne',
|
|
2132
|
-
'oneToMany',
|
|
2133
|
-
'manyToOne',
|
|
2134
|
-
'manyToMany',
|
|
2135
|
-
'morphOne',
|
|
2136
|
-
'morphMany',
|
|
2137
|
-
'morphToOne',
|
|
2138
|
-
'morphToMany'
|
|
2139
|
-
]
|
|
2140
|
-
};
|
|
2141
|
-
/**
|
|
2142
|
-
* Allowed types
|
|
2143
|
-
*/ const VALID_TYPES = [
|
|
2144
|
-
...DEFAULT_TYPES,
|
|
2145
|
-
'uid',
|
|
2146
|
-
'component',
|
|
2147
|
-
'dynamiczone',
|
|
2148
|
-
'customField'
|
|
2149
|
-
];
|
|
2150
|
-
/**
|
|
2151
|
-
* Returns a yup schema to validate a content type payload
|
|
2152
|
-
*/ const createContentTypeSchema = (data, { isEdition = false } = {})=>{
|
|
2153
|
-
const kind = fp.getOr(typeKinds.COLLECTION_TYPE, 'contentType.kind', data);
|
|
2154
|
-
const contentTypeSchema = createSchema(VALID_TYPES, VALID_RELATIONS[kind] || [], {
|
|
2155
|
-
modelType: modelTypes.CONTENT_TYPE
|
|
2156
|
-
}).shape({
|
|
2157
|
-
displayName: utils.yup.string().min(1).required(),
|
|
2158
|
-
singularName: utils.yup.string().min(1).test(nameIsAvailable(isEdition)).test(forbiddenContentTypeNameValidator()).isKebabCase().required(),
|
|
2159
|
-
pluralName: utils.yup.string().min(1).test(nameIsAvailable(isEdition)).test(nameIsNotExistingCollectionName(isEdition)) // TODO: v5: require singularName to not match a collection name
|
|
2160
|
-
.test(forbiddenContentTypeNameValidator()).isKebabCase().required()
|
|
2161
|
-
}).test('singularName-not-equal-pluralName', '${path}: singularName and pluralName should be different', (value)=>value.singularName !== value.pluralName);
|
|
2162
|
-
return utils.yup.object({
|
|
2163
|
-
// FIXME .noUnknown(false) will strip off the unwanted properties without throwing an error
|
|
2164
|
-
// Why not having .noUnknown() ? Because we want to be able to add options relatable to EE features
|
|
2165
|
-
// without having any reference to them in CE.
|
|
2166
|
-
// Why not handle an "options" object in the content-type ? The admin panel needs lots of rework
|
|
2167
|
-
// to be able to send this options object instead of top-level attributes.
|
|
2168
|
-
// @nathan-pichon 20/02/2023
|
|
2169
|
-
contentType: contentTypeSchema.required().noUnknown(false),
|
|
2170
|
-
components: nestedComponentSchema
|
|
2171
|
-
}).noUnknown();
|
|
2172
|
-
};
|
|
2173
|
-
/**
|
|
2174
|
-
* Validator for content type creation
|
|
2175
|
-
*/ const validateContentTypeInput = (data)=>{
|
|
2176
|
-
return utils.validateYupSchema(createContentTypeSchema(data))(data);
|
|
2177
|
-
};
|
|
2178
|
-
/**
|
|
2179
|
-
* Validator for content type edition
|
|
2180
|
-
*/ const validateUpdateContentTypeInput = (data)=>{
|
|
2181
|
-
if (fp.has('contentType', data)) {
|
|
2182
|
-
removeEmptyDefaults(data.contentType);
|
|
2183
|
-
removeDeletedUIDTargetFields(data.contentType);
|
|
2184
|
-
}
|
|
2185
|
-
if (fp.has('components', data) && Array.isArray(data.components)) {
|
|
2186
|
-
data.components.forEach((comp)=>{
|
|
2187
|
-
if (fp.has('uid', comp)) {
|
|
2188
|
-
removeEmptyDefaults(comp);
|
|
2189
|
-
}
|
|
2190
|
-
});
|
|
2191
|
-
}
|
|
2192
|
-
return utils.validateYupSchema(createContentTypeSchema(data, {
|
|
2193
|
-
isEdition: true
|
|
2194
|
-
}))(data);
|
|
2195
|
-
};
|
|
2196
|
-
const forbiddenContentTypeNameValidator = ()=>{
|
|
2197
|
-
const reservedNames = getService('builder').getReservedNames().models;
|
|
2198
|
-
return {
|
|
2199
|
-
name: 'forbiddenContentTypeName',
|
|
2200
|
-
message: `Content Type name cannot be one of ${reservedNames.join(', ')}`,
|
|
2201
|
-
test (value) {
|
|
2202
|
-
if (typeof value !== 'string') {
|
|
2203
|
-
return true;
|
|
2204
|
-
}
|
|
2205
|
-
return !getService('builder').isReservedModelName(value);
|
|
2206
|
-
}
|
|
2207
|
-
};
|
|
2208
|
-
};
|
|
2209
|
-
const nameIsAvailable = (isEdition)=>{
|
|
2210
|
-
// TODO TS: if strapi.contentTypes (ie, ContentTypes) works as an ArrayLike and is used like this, we may want to ensure it is typed so that it can be without using as
|
|
2211
|
-
const usedNames = fp.flatMap((ct)=>{
|
|
2212
|
-
return [
|
|
2213
|
-
ct.info?.singularName,
|
|
2214
|
-
ct.info?.pluralName
|
|
2215
|
-
];
|
|
2216
|
-
})(strapi.contentTypes);
|
|
2217
|
-
return {
|
|
2218
|
-
name: 'nameAlreadyUsed',
|
|
2219
|
-
message: 'contentType: name `${value}` is already being used by another content type.',
|
|
2220
|
-
test (value) {
|
|
2221
|
-
// don't check on edition
|
|
2222
|
-
if (isEdition) return true;
|
|
2223
|
-
// ignore if not a string (will be caught in another validator)
|
|
2224
|
-
if (typeof value !== 'string') {
|
|
2225
|
-
return true;
|
|
2226
|
-
}
|
|
2227
|
-
// compare snake case to check the actual column names that will be used in the database
|
|
2228
|
-
return usedNames.every((usedName)=>fp.snakeCase(usedName) !== fp.snakeCase(value));
|
|
2229
|
-
}
|
|
2230
|
-
};
|
|
2231
|
-
};
|
|
2232
|
-
const nameIsNotExistingCollectionName = (isEdition)=>{
|
|
2233
|
-
const usedNames = Object.keys(strapi.contentTypes).map((key)=>strapi.contentTypes[key].collectionName);
|
|
2234
|
-
return {
|
|
2235
|
-
name: 'nameAlreadyUsed',
|
|
2236
|
-
message: 'contentType: name `${value}` is already being used by another content type.',
|
|
2237
|
-
test (value) {
|
|
2238
|
-
// don't check on edition
|
|
2239
|
-
if (isEdition) return true;
|
|
2240
|
-
// ignore if not a string (will be caught in another validator)
|
|
2241
|
-
if (typeof value !== 'string') {
|
|
2242
|
-
return true;
|
|
2243
|
-
}
|
|
2244
|
-
// compare snake case to check the actual column names that will be used in the database
|
|
2245
|
-
return usedNames.every((usedName)=>fp.snakeCase(usedName) !== fp.snakeCase(value));
|
|
2246
|
-
}
|
|
2247
|
-
};
|
|
2248
|
-
};
|
|
2249
|
-
/**
|
|
2250
|
-
* Validates type kind
|
|
2251
|
-
*/ const kindSchema = utils.yup.string().oneOf([
|
|
2252
|
-
typeKinds.SINGLE_TYPE,
|
|
2253
|
-
typeKinds.COLLECTION_TYPE
|
|
2254
|
-
]);
|
|
2255
|
-
const validateKind = utils.validateYupSchema(kindSchema);
|
|
2256
|
-
|
|
2257
|
-
var contentTypes = {
|
|
2258
|
-
async getContentTypes (ctx) {
|
|
2259
|
-
const { kind } = ctx.query;
|
|
2260
|
-
try {
|
|
2261
|
-
await validateKind(kind);
|
|
2262
|
-
} catch (error) {
|
|
2263
|
-
return ctx.send({
|
|
2264
|
-
error
|
|
2265
|
-
}, 400);
|
|
2266
|
-
}
|
|
2267
|
-
const contentTypeService = getService('content-types');
|
|
2268
|
-
const contentTypes = Object.keys(strapi.contentTypes).filter((uid)=>!kind || _.get(strapi.contentTypes[uid], 'kind', 'collectionType') === kind).map((uid)=>contentTypeService.formatContentType(strapi.contentTypes[uid]));
|
|
2269
|
-
ctx.send({
|
|
2270
|
-
data: contentTypes
|
|
2271
|
-
});
|
|
2272
|
-
},
|
|
2273
|
-
getContentType (ctx) {
|
|
2274
|
-
const { uid } = ctx.params;
|
|
2275
|
-
const contentType = strapi.contentTypes[uid];
|
|
2276
|
-
if (!contentType) {
|
|
2277
|
-
return ctx.send({
|
|
2278
|
-
error: 'contentType.notFound'
|
|
2279
|
-
}, 404);
|
|
2280
|
-
}
|
|
2281
|
-
const contentTypeService = getService('content-types');
|
|
2282
|
-
ctx.send({
|
|
2283
|
-
data: contentTypeService.formatContentType(contentType)
|
|
2284
|
-
});
|
|
2285
|
-
},
|
|
2286
|
-
async createContentType (ctx) {
|
|
2287
|
-
const body = ctx.request.body;
|
|
2288
|
-
try {
|
|
2289
|
-
await validateContentTypeInput(body);
|
|
2290
|
-
} catch (error) {
|
|
2291
|
-
return ctx.send({
|
|
2292
|
-
error
|
|
2293
|
-
}, 400);
|
|
2294
|
-
}
|
|
2295
|
-
try {
|
|
2296
|
-
strapi.reload.isWatching = false;
|
|
2297
|
-
const contentTypeService = getService('content-types');
|
|
2298
|
-
const contentType = await contentTypeService.createContentType({
|
|
2299
|
-
contentType: body.contentType,
|
|
2300
|
-
components: body.components
|
|
2301
|
-
});
|
|
2302
|
-
const metricsPayload = {
|
|
2303
|
-
eventProperties: {
|
|
2304
|
-
kind: contentType.kind
|
|
2305
|
-
}
|
|
2306
|
-
};
|
|
2307
|
-
if (_.isEmpty(strapi.apis)) {
|
|
2308
|
-
await strapi.telemetry.send('didCreateFirstContentType', metricsPayload);
|
|
2309
|
-
} else {
|
|
2310
|
-
await strapi.telemetry.send('didCreateContentType', metricsPayload);
|
|
2311
|
-
}
|
|
2312
|
-
setImmediate(()=>strapi.reload());
|
|
2313
|
-
ctx.send({
|
|
2314
|
-
data: {
|
|
2315
|
-
uid: contentType.uid
|
|
2316
|
-
}
|
|
2317
|
-
}, 201);
|
|
2318
|
-
} catch (err) {
|
|
2319
|
-
strapi.log.error(err);
|
|
2320
|
-
await strapi.telemetry.send('didNotCreateContentType', {
|
|
2321
|
-
eventProperties: {
|
|
2322
|
-
error: err.message || err
|
|
2323
|
-
}
|
|
2324
|
-
});
|
|
2325
|
-
ctx.send({
|
|
2326
|
-
error: err.message || 'Unknown error'
|
|
2327
|
-
}, 400);
|
|
2328
|
-
}
|
|
2329
|
-
},
|
|
2330
|
-
async updateContentType (ctx) {
|
|
2331
|
-
const { uid } = ctx.params;
|
|
2332
|
-
const body = ctx.request.body;
|
|
2333
|
-
if (!_.has(strapi.contentTypes, uid)) {
|
|
2334
|
-
return ctx.send({
|
|
2335
|
-
error: 'contentType.notFound'
|
|
2336
|
-
}, 404);
|
|
2337
|
-
}
|
|
2338
|
-
try {
|
|
2339
|
-
await validateUpdateContentTypeInput(body);
|
|
2340
|
-
} catch (error) {
|
|
2341
|
-
return ctx.send({
|
|
2342
|
-
error
|
|
2343
|
-
}, 400);
|
|
2344
|
-
}
|
|
2345
|
-
try {
|
|
2346
|
-
strapi.reload.isWatching = false;
|
|
2347
|
-
const contentTypeService = getService('content-types');
|
|
2348
|
-
const component = await contentTypeService.editContentType(uid, {
|
|
2349
|
-
contentType: body.contentType,
|
|
2350
|
-
components: body.components
|
|
2351
|
-
});
|
|
2352
|
-
setImmediate(()=>strapi.reload());
|
|
2353
|
-
ctx.send({
|
|
2354
|
-
data: {
|
|
2355
|
-
uid: component.uid
|
|
2356
|
-
}
|
|
2357
|
-
}, 201);
|
|
2358
|
-
} catch (error) {
|
|
2359
|
-
strapi.log.error(error);
|
|
2360
|
-
ctx.send({
|
|
2361
|
-
error: error?.message || 'Unknown error'
|
|
2362
|
-
}, 400);
|
|
2363
|
-
}
|
|
2364
|
-
},
|
|
2365
|
-
async deleteContentType (ctx) {
|
|
2366
|
-
const { uid } = ctx.params;
|
|
2367
|
-
if (!_.has(strapi.contentTypes, uid)) {
|
|
2368
|
-
return ctx.send({
|
|
2369
|
-
error: 'contentType.notFound'
|
|
2370
|
-
}, 404);
|
|
2371
|
-
}
|
|
2372
|
-
try {
|
|
2373
|
-
strapi.reload.isWatching = false;
|
|
2374
|
-
const contentTypeService = getService('content-types');
|
|
2375
|
-
const component = await contentTypeService.deleteContentType(uid);
|
|
2376
|
-
setImmediate(()=>strapi.reload());
|
|
2377
|
-
ctx.send({
|
|
2378
|
-
data: {
|
|
2379
|
-
uid: component.uid
|
|
2380
|
-
}
|
|
2381
|
-
});
|
|
2382
|
-
} catch (error) {
|
|
2383
|
-
strapi.log.error(error);
|
|
2384
|
-
ctx.send({
|
|
2385
|
-
error: error?.message || 'Unknown error'
|
|
2386
|
-
}, 400);
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
};
|
|
2390
|
-
|
|
2391
|
-
const exportObject = {
|
|
2392
|
-
builder,
|
|
2393
|
-
'component-categories': componentCategories,
|
|
2394
|
-
components,
|
|
2395
|
-
'content-types': contentTypes
|
|
2396
|
-
};
|
|
2397
|
-
|
|
2398
|
-
var admin = {
|
|
2399
|
-
type: 'admin',
|
|
2400
|
-
routes: [
|
|
2401
|
-
{
|
|
2402
|
-
method: 'GET',
|
|
2403
|
-
path: '/reserved-names',
|
|
2404
|
-
handler: 'builder.getReservedNames',
|
|
2405
|
-
config: {
|
|
2406
|
-
policies: [
|
|
2407
|
-
{
|
|
2408
|
-
name: 'admin::hasPermissions',
|
|
2409
|
-
config: {
|
|
2410
|
-
actions: [
|
|
2411
|
-
'plugin::content-type-builder.read'
|
|
2412
|
-
]
|
|
2413
|
-
}
|
|
2414
|
-
}
|
|
2415
|
-
]
|
|
2416
|
-
}
|
|
2417
|
-
},
|
|
2418
|
-
{
|
|
2419
|
-
method: 'GET',
|
|
2420
|
-
path: '/content-types',
|
|
2421
|
-
handler: 'content-types.getContentTypes',
|
|
2422
|
-
config: {
|
|
2423
|
-
policies: [
|
|
2424
|
-
{
|
|
2425
|
-
name: 'admin::hasPermissions',
|
|
2426
|
-
config: {
|
|
2427
|
-
actions: [
|
|
2428
|
-
'plugin::content-type-builder.read'
|
|
2429
|
-
]
|
|
2430
|
-
}
|
|
2431
|
-
}
|
|
2432
|
-
]
|
|
2433
|
-
}
|
|
2434
|
-
},
|
|
2435
|
-
{
|
|
2436
|
-
method: 'GET',
|
|
2437
|
-
path: '/content-types/:uid',
|
|
2438
|
-
handler: 'content-types.getContentType',
|
|
2439
|
-
config: {
|
|
2440
|
-
policies: [
|
|
2441
|
-
{
|
|
2442
|
-
name: 'admin::hasPermissions',
|
|
2443
|
-
config: {
|
|
2444
|
-
actions: [
|
|
2445
|
-
'plugin::content-type-builder.read'
|
|
2446
|
-
]
|
|
2447
|
-
}
|
|
2448
|
-
}
|
|
2449
|
-
]
|
|
2450
|
-
}
|
|
2451
|
-
},
|
|
2452
|
-
{
|
|
2453
|
-
method: 'POST',
|
|
2454
|
-
path: '/content-types',
|
|
2455
|
-
handler: 'content-types.createContentType',
|
|
2456
|
-
config: {
|
|
2457
|
-
policies: [
|
|
2458
|
-
{
|
|
2459
|
-
name: 'admin::hasPermissions',
|
|
2460
|
-
config: {
|
|
2461
|
-
actions: [
|
|
2462
|
-
'plugin::content-type-builder.read'
|
|
2463
|
-
]
|
|
2464
|
-
}
|
|
2465
|
-
}
|
|
2466
|
-
]
|
|
2467
|
-
}
|
|
2468
|
-
},
|
|
2469
|
-
{
|
|
2470
|
-
method: 'PUT',
|
|
2471
|
-
path: '/content-types/:uid',
|
|
2472
|
-
handler: 'content-types.updateContentType',
|
|
2473
|
-
config: {
|
|
2474
|
-
policies: [
|
|
2475
|
-
{
|
|
2476
|
-
name: 'admin::hasPermissions',
|
|
2477
|
-
config: {
|
|
2478
|
-
actions: [
|
|
2479
|
-
'plugin::content-type-builder.read'
|
|
2480
|
-
]
|
|
2481
|
-
}
|
|
2482
|
-
}
|
|
2483
|
-
]
|
|
2484
|
-
}
|
|
2485
|
-
},
|
|
2486
|
-
{
|
|
2487
|
-
method: 'DELETE',
|
|
2488
|
-
path: '/content-types/:uid',
|
|
2489
|
-
handler: 'content-types.deleteContentType',
|
|
2490
|
-
config: {
|
|
2491
|
-
policies: [
|
|
2492
|
-
{
|
|
2493
|
-
name: 'admin::hasPermissions',
|
|
2494
|
-
config: {
|
|
2495
|
-
actions: [
|
|
2496
|
-
'plugin::content-type-builder.read'
|
|
2497
|
-
]
|
|
2498
|
-
}
|
|
2499
|
-
}
|
|
2500
|
-
]
|
|
2501
|
-
}
|
|
2502
|
-
},
|
|
2503
|
-
{
|
|
2504
|
-
method: 'GET',
|
|
2505
|
-
path: '/components',
|
|
2506
|
-
handler: 'components.getComponents',
|
|
2507
|
-
config: {
|
|
2508
|
-
policies: [
|
|
2509
|
-
{
|
|
2510
|
-
name: 'admin::hasPermissions',
|
|
2511
|
-
config: {
|
|
2512
|
-
actions: [
|
|
2513
|
-
'plugin::content-type-builder.read'
|
|
2514
|
-
]
|
|
2515
|
-
}
|
|
2516
|
-
}
|
|
2517
|
-
]
|
|
2518
|
-
}
|
|
2519
|
-
},
|
|
2520
|
-
{
|
|
2521
|
-
method: 'GET',
|
|
2522
|
-
path: '/components/:uid',
|
|
2523
|
-
handler: 'components.getComponent',
|
|
2524
|
-
config: {
|
|
2525
|
-
policies: [
|
|
2526
|
-
{
|
|
2527
|
-
name: 'admin::hasPermissions',
|
|
2528
|
-
config: {
|
|
2529
|
-
actions: [
|
|
2530
|
-
'plugin::content-type-builder.read'
|
|
2531
|
-
]
|
|
2532
|
-
}
|
|
2533
|
-
}
|
|
2534
|
-
]
|
|
2535
|
-
}
|
|
2536
|
-
},
|
|
2537
|
-
{
|
|
2538
|
-
method: 'POST',
|
|
2539
|
-
path: '/components',
|
|
2540
|
-
handler: 'components.createComponent',
|
|
2541
|
-
config: {
|
|
2542
|
-
policies: [
|
|
2543
|
-
{
|
|
2544
|
-
name: 'admin::hasPermissions',
|
|
2545
|
-
config: {
|
|
2546
|
-
actions: [
|
|
2547
|
-
'plugin::content-type-builder.read'
|
|
2548
|
-
]
|
|
2549
|
-
}
|
|
2550
|
-
}
|
|
2551
|
-
]
|
|
2552
|
-
}
|
|
2553
|
-
},
|
|
2554
|
-
{
|
|
2555
|
-
method: 'PUT',
|
|
2556
|
-
path: '/components/:uid',
|
|
2557
|
-
handler: 'components.updateComponent',
|
|
2558
|
-
config: {
|
|
2559
|
-
policies: [
|
|
2560
|
-
{
|
|
2561
|
-
name: 'admin::hasPermissions',
|
|
2562
|
-
config: {
|
|
2563
|
-
actions: [
|
|
2564
|
-
'plugin::content-type-builder.read'
|
|
2565
|
-
]
|
|
2566
|
-
}
|
|
2567
|
-
}
|
|
2568
|
-
]
|
|
2569
|
-
}
|
|
2570
|
-
},
|
|
2571
|
-
{
|
|
2572
|
-
method: 'DELETE',
|
|
2573
|
-
path: '/components/:uid',
|
|
2574
|
-
handler: 'components.deleteComponent',
|
|
2575
|
-
config: {
|
|
2576
|
-
policies: [
|
|
2577
|
-
{
|
|
2578
|
-
name: 'admin::hasPermissions',
|
|
2579
|
-
config: {
|
|
2580
|
-
actions: [
|
|
2581
|
-
'plugin::content-type-builder.read'
|
|
2582
|
-
]
|
|
2583
|
-
}
|
|
2584
|
-
}
|
|
2585
|
-
]
|
|
2586
|
-
}
|
|
2587
|
-
},
|
|
2588
|
-
{
|
|
2589
|
-
method: 'PUT',
|
|
2590
|
-
path: '/component-categories/:name',
|
|
2591
|
-
handler: 'component-categories.editCategory',
|
|
2592
|
-
config: {
|
|
2593
|
-
policies: [
|
|
2594
|
-
{
|
|
2595
|
-
name: 'admin::hasPermissions',
|
|
2596
|
-
config: {
|
|
2597
|
-
actions: [
|
|
2598
|
-
'plugin::content-type-builder.read'
|
|
2599
|
-
]
|
|
2600
|
-
}
|
|
2601
|
-
}
|
|
2602
|
-
]
|
|
2603
|
-
}
|
|
2604
|
-
},
|
|
2605
|
-
{
|
|
2606
|
-
method: 'DELETE',
|
|
2607
|
-
path: '/component-categories/:name',
|
|
2608
|
-
handler: 'component-categories.deleteCategory',
|
|
2609
|
-
config: {
|
|
2610
|
-
policies: [
|
|
2611
|
-
{
|
|
2612
|
-
name: 'admin::hasPermissions',
|
|
2613
|
-
config: {
|
|
2614
|
-
actions: [
|
|
2615
|
-
'plugin::content-type-builder.read'
|
|
2616
|
-
]
|
|
2617
|
-
}
|
|
2618
|
-
}
|
|
2619
|
-
]
|
|
2620
|
-
}
|
|
2621
|
-
}
|
|
2622
|
-
]
|
|
2623
|
-
};
|
|
2624
|
-
|
|
2625
|
-
var contentApi = {
|
|
2626
|
-
type: 'content-api',
|
|
2627
|
-
routes: [
|
|
2628
|
-
{
|
|
2629
|
-
method: 'GET',
|
|
2630
|
-
path: '/content-types',
|
|
2631
|
-
handler: 'content-types.getContentTypes'
|
|
2632
|
-
},
|
|
2633
|
-
{
|
|
2634
|
-
method: 'GET',
|
|
2635
|
-
path: '/content-types/:uid',
|
|
2636
|
-
handler: 'content-types.getContentType'
|
|
2637
|
-
},
|
|
2638
|
-
{
|
|
2639
|
-
method: 'GET',
|
|
2640
|
-
path: '/components',
|
|
2641
|
-
handler: 'components.getComponents'
|
|
2642
|
-
},
|
|
2643
|
-
{
|
|
2644
|
-
method: 'GET',
|
|
2645
|
-
path: '/components/:uid',
|
|
2646
|
-
handler: 'components.getComponent'
|
|
2647
|
-
}
|
|
2648
|
-
]
|
|
2649
|
-
};
|
|
2650
|
-
|
|
2651
|
-
var routes = {
|
|
2652
|
-
admin,
|
|
2653
|
-
'content-api': contentApi
|
|
2654
|
-
};
|
|
4
|
+
var config = require('./config.js');
|
|
5
|
+
var bootstrap = require('./bootstrap.js');
|
|
6
|
+
var index$1 = require('./services/index.js');
|
|
7
|
+
var index$2 = require('./controllers/index.js');
|
|
8
|
+
var index$3 = require('./routes/index.js');
|
|
2655
9
|
|
|
2656
10
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2657
11
|
var index = (()=>({
|
|
2658
12
|
config,
|
|
2659
13
|
bootstrap,
|
|
2660
|
-
services,
|
|
2661
|
-
controllers:
|
|
2662
|
-
routes
|
|
14
|
+
services: index$1,
|
|
15
|
+
controllers: index$2,
|
|
16
|
+
routes: index$3
|
|
2663
17
|
}));
|
|
2664
18
|
|
|
2665
19
|
module.exports = index;
|