From 5023a58cc17e96024a4ecdeec36dee36a58e8b2f Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Sat, 27 May 2023 13:59:52 +0300 Subject: [PATCH] schema --- .idea/jsonSchemas.xml | 57 ++++-- schema/metadata/app/metadata.json | 2 +- schema/metadata/app/orm.json | 35 ++++ schema/metadata/app/pdfEngines.json | 39 ++++ schema/metadata/app/popupNotifications.json | 45 +++++ .../metadata/app/portalContainerServices.json | 25 +++ schema/metadata/app/rebuild.json | 16 ++ schema/metadata/app/recordId.json | 32 +++ schema/metadata/app/regExpPatterns.json | 21 ++ schema/metadata/app/relationships.json | 17 ++ schema/metadata/app/scheduledJobs.json | 33 ++++ schema/metadata/app/select.json | 30 +++ schema/metadata/app/smsProviders.json | 17 ++ schema/metadata/app/templateHelpers.json | 11 ++ schema/metadata/app/templates.json | 35 ++++ schema/metadata/app/webSocket.json | 44 +++++ schema/metadata/authenticationMethods.json | 111 +++++++++++ schema/metadata/entityDefs.json | 183 +++++++++--------- schema/metadata/fields.json | 164 ++++++++++++++++ 19 files changed, 807 insertions(+), 110 deletions(-) create mode 100644 schema/metadata/app/orm.json create mode 100644 schema/metadata/app/pdfEngines.json create mode 100644 schema/metadata/app/popupNotifications.json create mode 100644 schema/metadata/app/portalContainerServices.json create mode 100644 schema/metadata/app/rebuild.json create mode 100644 schema/metadata/app/recordId.json create mode 100644 schema/metadata/app/regExpPatterns.json create mode 100644 schema/metadata/app/relationships.json create mode 100644 schema/metadata/app/scheduledJobs.json create mode 100644 schema/metadata/app/select.json create mode 100644 schema/metadata/app/smsProviders.json create mode 100644 schema/metadata/app/templateHelpers.json create mode 100644 schema/metadata/app/templates.json create mode 100644 schema/metadata/app/webSocket.json create mode 100644 schema/metadata/authenticationMethods.json create mode 100644 schema/metadata/fields.json diff --git a/.idea/jsonSchemas.xml b/.idea/jsonSchemas.xml index de76164c7b..b695485bae 100644 --- a/.idea/jsonSchemas.xml +++ b/.idea/jsonSchemas.xml @@ -167,25 +167,6 @@ - - - - - - - @@ -1079,6 +1060,25 @@ + + + + + + + @@ -1155,6 +1155,25 @@ + + + + + + + diff --git a/schema/metadata/app/metadata.json b/schema/metadata/app/metadata.json index 860922c15b..fb2b8e0da2 100644 --- a/schema/metadata/app/metadata.json +++ b/schema/metadata/app/metadata.json @@ -14,7 +14,7 @@ { "type": "array", "items": { - "type": "array" + "type": "string" } } ] diff --git a/schema/metadata/app/orm.json b/schema/metadata/app/orm.json new file mode 100644 index 0000000000..ecfcecc006 --- /dev/null +++ b/schema/metadata/app/orm.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/orm.json", + "title": "app/orm", + "description": "ORM definitions.", + "type": "object", + "properties": { + "platforms": { + "type": "object", + "description": "Platforms.", + "additionalProperties": { + "type": "object", + "description": "A platform name.", + "properties": { + "queryComposerClassName": { + "type": "string", + "description": "A query composer. Should implement Espo\\ORM\\QueryComposer\\QueryComposer." + }, + "pdoFactoryClassName": { + "type": "string", + "description": "A PDF factory. Should implement Espo\\ORM\\PDO\\PDOFactory." + }, + "functionConverterClassNameMap": { + "type": "object", + "description": "Function converters. Should implement Espo\\ORM\\QueryComposer\\Part\\FunctionConverter.", + "additionalProperties": { + "description": "A function name. Only upper case letters and _ are allowed.", + "type": "string" + } + } + } + } + } + } +} diff --git a/schema/metadata/app/pdfEngines.json b/schema/metadata/app/pdfEngines.json new file mode 100644 index 0000000000..c64c0d4451 --- /dev/null +++ b/schema/metadata/app/pdfEngines.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/pdfEngines.json", + "title": "app/pdfEngines", + "description": "PDF printing engines.", + "type": "object", + "additionalProperties": { + "type": "object", + "description": "An engine name.", + "properties": { + "implementationClassNameMap": { + "type": "object", + "description": "Implementations.", + "properties": { + "entity": { + "type": "string", + "description": "An entity printer. Should implement Espo\\Tools\\Pdf\\EntityPrinter." + }, + "collection": { + "type": "string", + "description": "An entity printer. Should implement Espo\\Tools\\Pdf\\CollectionPrinter." + } + } + }, + "fontFaceList": { + "type": "array", + "description": "A list of fonts available for the engine.", + "items": { + "anyOf": [ + {"const": "__APPEND__"}, + { + "type": "string" + } + ] + } + } + } + } +} diff --git a/schema/metadata/app/popupNotifications.json b/schema/metadata/app/popupNotifications.json new file mode 100644 index 0000000000..7435c21dad --- /dev/null +++ b/schema/metadata/app/popupNotifications.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/popupNotifications.json", + "title": "app/popupNotifications", + "description": "Popup notifications.", + "type": "object", + "additionalProperties": { + "type": "object", + "description": "A name.", + "properties": { + "grouped": { + "type": "boolean", + "description": "Grouped popup notifications are fetched with a single API request." + }, + "providerClassName": { + "type": "string", + "description": "A provider class. Actual only if the `grouped` parameter is set to true. Should implement Espo\\Tools\\PopupNotification\\Provider." + }, + "useWebSocket": { + "type": "boolean", + "description": "If the WebSocked is configured and the parameter is set to true, notifications won't be polled in the front-end (except once, when page is loaded)." + }, + "disabled": { + "type": "boolean", + "description": "Disables." + }, + "portalDisabled": { + "type": "boolean", + "description": "Disables in portals." + }, + "view": { + "type": "string", + "description": "A frontend view for the popup notification." + }, + "interval": { + "type": "integer", + "description": "A polling interval in seconds. Actual if `grouped` is false." + }, + "url": { + "type": "string", + "description": "An API endpoint used for polling. Actual if `grouped` is false." + } + } + } +} diff --git a/schema/metadata/app/portalContainerServices.json b/schema/metadata/app/portalContainerServices.json new file mode 100644 index 0000000000..4dceb3e482 --- /dev/null +++ b/schema/metadata/app/portalContainerServices.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/consoleCommands", + "$id": "https://www.espocrm.com/schema/metadata/app/portalContainerServices.json", + "title": "app/portalContainerServices", + "description": "Overriding of container services for portals. Provides the ability to define custom implementations for portals.", + "type": "object", + "additionalProperties": { + "type": "object", + "description": "A service name.", + "properties": { + "className": { + "type": "string", + "description": "A service class." + }, + "loaderClassName": { + "type": "string", + "description": "A service loader class. Should implement Espo\\Core\\Container\\Loader interface." + }, + "settable": { + "type": "boolean", + "description": "Whether the service can be set to the container externally (with the `set` method)." + } + } + } +} diff --git a/schema/metadata/app/rebuild.json b/schema/metadata/app/rebuild.json new file mode 100644 index 0000000000..eb33f5fe09 --- /dev/null +++ b/schema/metadata/app/rebuild.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/rebuild.json", + "title": "app/rebuild", + "description": "Rebuild definitions.", + "type": "object", + "properties": { + "actionClassNameList": { + "type": "array", + "description": "Array of class names. Actions being processed when the application is being rebuilt. Should implement Espo\\Core\\Rebuild\\RebuildAction.", + "items": { + "type": "string" + } + } + } +} diff --git a/schema/metadata/app/recordId.json b/schema/metadata/app/recordId.json new file mode 100644 index 0000000000..234f5b69f1 --- /dev/null +++ b/schema/metadata/app/recordId.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/recordId.json", + "title": "app/recordId", + "description": "Record ID definitions.", + "type": "object", + "properties": { + "type": { + "enum": [ + "id", + "uuid4" + ], + "description": "A type of generated IDs." + }, + "length": { + "type": "integer", + "description": "ID column length. By default, set to 17." + }, + "dbType": { + "description": "An ID column data type. By default, set to string (equivalent to varchar in MySQL). Changing this parameter will change types of all ID columns once you run rebuild." + "anyOf": [ + {"type": "string"}, + { + "enum": [ + "string", + "uuid" + ] + } + ] + } + } +} diff --git a/schema/metadata/app/regExpPatterns.json b/schema/metadata/app/regExpPatterns.json new file mode 100644 index 0000000000..fcab92e5db --- /dev/null +++ b/schema/metadata/app/regExpPatterns.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/regExpPatterns.json", + "title": "app/regExpPatterns", + "description": "Predefined regular expression patterns. Predefined patterns can be used for field validation.", + "type": "object", + "additionalProperties": { + "type": "object", + "description": "A pattern name.", + "properties": { + "pattern": { + "type": "string", + "description": "A regular expression pattern." + }, + "isSystem": { + "type": "boolean", + "description": "If true, the pattern won't be available when defining a validation for a field." + } + } + } +} diff --git a/schema/metadata/app/relationships.json b/schema/metadata/app/relationships.json new file mode 100644 index 0000000000..9d935b108e --- /dev/null +++ b/schema/metadata/app/relationships.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/relationships.json", + "title": "app/relationships", + "description": "Definitions of specific named relationships.", + "type": "object", + "additionalProperties": { + "description": "A relationship name.", + "type": "object", + "properties": { + "converterClassName": { + "type": "string", + "description": "A converter. Converts metadata link definitions to ORM definitions. Should implement Espo\\Core\\Utils\\Database\\Orm\\LinkConverter." + } + } + } +} diff --git a/schema/metadata/app/scheduledJobs.json b/schema/metadata/app/scheduledJobs.json new file mode 100644 index 0000000000..210e4db20f --- /dev/null +++ b/schema/metadata/app/scheduledJobs.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/scheduledJobs.json", + "title": "app/scheduledJobs", + "description": "Scheduled jobs definitions. Defined scheduled job will be available for the admin when creating a scheduled job.", + "type": "object", + "additionalProperties": { + "description": "A job name. Should start with the upper case letter.", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "A name to be used for job records. Not important." + }, + "isSystem": { + "type": "boolean", + "description": "Whether the job is system." + }, + "scheduling": { + "type": "string", + "description": "A default scheduling in crontab notation." + }, + "jobClassName": { + "type": "string", + "description": "A job implementation. Should implement either Espo\\Core\\Job\\Job|Espo\\Core\\Job or Espo\\Core\\Job\\Job|Espo\\Core\\JobDataLess interfaces. Usage of the former requires having the preparator." + }, + "preparatorClassName": { + "type": "string", + "description": "A preparator. Optional. The preparator is called by the application. It serves for creating job records. E.g. for email checking, the preparator creates jobs for each email account. Should implement Espo\\Core\\Job\\Preparator." + } + } + } +} diff --git a/schema/metadata/app/select.json b/schema/metadata/app/select.json new file mode 100644 index 0000000000..c4b8a56fe4 --- /dev/null +++ b/schema/metadata/app/select.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/select.json", + "title": "app/select", + "description": "Select framework definitions.", + "type": "object", + "properties": { + "boolFilterClassNameMap": { + "type": "object", + "description": "Bool filters available for all entity types. Should implement Espo\\Core\\Select\\Bool\\Filter.", + "additionalProperties": { + "type": "string" + } + }, + "orderItemConverterClassNameMap": { + "type": "object", + "description": "Order item converters for field types. Should implement Espo\\Core\\Select\\Order\\ItemConverter.", + "additionalProperties": { + "type": "string" + } + }, + "whereItemConverterClassNameMap": { + "type": "object", + "description": "Where item converters. Should implement Espo\\Core\\Select\\Where\\ItemConverter.", + "additionalProperties": { + "type": "string" + } + } + } +} diff --git a/schema/metadata/app/smsProviders.json b/schema/metadata/app/smsProviders.json new file mode 100644 index 0000000000..fbbcc5603b --- /dev/null +++ b/schema/metadata/app/smsProviders.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/smsProviders.json", + "title": "app/smsProviders", + "description": "SMS providers.", + "type": "object", + "additionalProperties": { + "type": "object", + "description": "A provider name.", + "properties": { + "senderClassName": { + "type": "string", + "description": "A sender class. Should implement Espo\\Core\\Sms\\Sender." + } + } + } +} diff --git a/schema/metadata/app/templateHelpers.json b/schema/metadata/app/templateHelpers.json new file mode 100644 index 0000000000..30af6188f1 --- /dev/null +++ b/schema/metadata/app/templateHelpers.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/templateHelpers.json", + "title": "app/templateHelpers", + "description": "Template helpers for the back-end templating system (used for PDF printing, email templates).", + "type": "object", + "additionalProperties": { + "type": "string", + "description": "A helper name and its implementation. Should implement Espo\\Core\\Htmlizer\\Helper." + } +} diff --git a/schema/metadata/app/templates.json b/schema/metadata/app/templates.json new file mode 100644 index 0000000000..f5949fc6a7 --- /dev/null +++ b/schema/metadata/app/templates.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/smsProviders.json", + "title": "app/smsProviders", + "description": "Templates (available at Administration > Templates). Usually used for system emails.", + "type": "object", + "additionalProperties": { + "type": "object", + "description": "A template name. Should start with the lower case letter.", + "properties": { + "scopeList": { + "type": "array", + "description": "A list of scopes (entity types) for which the template is available.", + "items": { + "anyOf": [ + {"const": "__APPEND__"}, + {"type": "string"} + ] + } + }, + "scope": { + "type": "string", + "description": "A scope (entity types) for which the template is available. Use it if it's needed only for one entity type." + }, + "scopeListConfigParam": { + "type": "string", + "description": "A config parameter defining for which entity types the template is available." + }, + "module": { + "type": "string", + "description": "A module name." + } + } + } +} diff --git a/schema/metadata/app/webSocket.json b/schema/metadata/app/webSocket.json new file mode 100644 index 0000000000..245cf0e386 --- /dev/null +++ b/schema/metadata/app/webSocket.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/webSocket.json", + "title": "app/webSocket", + "description": "WebSocket definitions.", + "type": "object", + "properties": { + "categories": { + "type": "object", + "description": "Categories. Define custom WebSocket events here. You can use dots in category names.", + "additionalProperties": { + "type": "object", + "description": "A category.", + "properties": { + "paramList": { + "type": "array", + "items": {"type": "string"}, + "description": "Parameters passed within a topic. E.g. the topic name myGroupName.myCustomName.Account.someId. This makes a topic name unique for a specific record. For global events, omit this parameter." + }, + "accessCheckCommand": { + "type": "string", + "description": "A console command that will be used to check whether a topic is allowed for a user when they attempting to subscribe. Patameter placeholders starts with the colon :. The userId parameter contains a user ID. If access checking is not needed, omit this parameter." + } + } + } + }, + "messagers": { + "type": "object", + "description": "Provides the ability to implement other messagers rather than the default ZeroMQ. E.g. RabbitMQ.", + "additionalProperties": { + "type": "object", + "description": "A messager.", + "properties": { + "senderClassName": { + "description": "A sender. Should implement Espo\\Core\\WebSocket\\Sender." + }, + "subscriberClassName": { + "description": "A subscriber. Should implement Espo\\Core\\WebSocket\\Subscriber." + } + } + } + } + } +} diff --git a/schema/metadata/authenticationMethods.json b/schema/metadata/authenticationMethods.json new file mode 100644 index 0000000000..088f74479f --- /dev/null +++ b/schema/metadata/authenticationMethods.json @@ -0,0 +1,111 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/authenticationMethods.json", + "title": "authenticationMethods", + "description": "An authentication method.", + "type": "object", + "properties": { + "api": { + "type": "boolean", + "description": "Defines that the method is to be used for pure API request, not from the front-end." + }, + "credentialsHeader": { + "type": "string", + "description": "A header that is supposed to contain credentials. Actual only for API methods." + }, + "login": { + "type": "object", + "description": "A framework providing the ability to call custom code on Sign-In button click on the login page.", + "properties": { + "handler": { + "type": "string", + "description": "A front-end class (should extend the abstract class handlers/login)." + }, + "fallback": { + "type": "boolean", + "description": "Defines that a regular username/password login method is also available on the login page." + }, + "fallbackConfigParam": { + "type": "string", + "description": "A config parameter name to be used to check whether fallback login is allowed." + }, + "portal": { + "type": "boolean", + "description": "Whether the handler will be available for portals, (bool)." + }, + "portalConfigParam": { + "type": "string", + "description": "A config parameter name to be used to check whether the handler will be available for portals." + }, + "data": { + "type": "object", + "additionalProperties": true, + "description": "Arbitrary data to be passed to the handler. Can be actual as application metadata is not yet available on the login page." + } + } + }, + "portalDefault": { + "type": "boolean", + "description": "If true, the method will be applied for portals when the method is selected as the default in the settings and the portal does not have a specific authentication provider." + }, + "settings": { + "type": "object", + "description": "Defines config parameters and a form on the admin UI.", + "properties": { + "isAvailable": { + "type": "boolean", + "description": "Whether the method is available in the settings." + }, + "layout": { + "description": "A layout.", + "$ref": "./../layouts/detail.json#/definitions/panel" + }, + "fieldList": { + "description": "Settings fields.", + "type": "array", + "items": { + "type": "string" + } + }, + "dynamicLogic": { + "type": "object", + "description": "Dynamic logic.", + "properties": { + "fields": { + "type": "object", + "description": "Fields.", + "additionalProperties": { + "type": "object", + "description": "A field.", + "properties": { + "visible": { + "description": "Conditions making the field visible.", + "$ref": "./clientDefs.json#/definitions/dynamicLogicVisible" + }, + "required": { + "$ref": "./clientDefs.json#/definitions/dynamicLogicRequired" + }, + "readOnly": { + "$ref": "./clientDefs.json#/definitions/dynamicLogicReadOnly" + }, + "invalid": { + "$ref": "./clientDefs.json#/definitions/dynamicLogicInvalid" + } + } + } + } + } + } + } + }, + "provider": { + "type": "object", + "properties": { + "isAvailable": { + "type": "boolean", + "description": "Whether is available in the Authentication Provider entity." + } + } + } + } +} diff --git a/schema/metadata/entityDefs.json b/schema/metadata/entityDefs.json index 5b04635980..03f9fab0bb 100644 --- a/schema/metadata/entityDefs.json +++ b/schema/metadata/entityDefs.json @@ -16,96 +16,7 @@ "description": "Links.", "type": "object", "additionalProperties": { - "type": "object", - "description": "A link.", - "additionalProperties": true, - "properties": { - "type": { - "type": "string", - "description": "A link type.", - "enum": ["belongsTo", "hasMany", "hasOne", "belongsToParent", "hasChildren"] - }, - "entity": { - "type": "string", - "description": "A foreign entity type." - }, - "foreign": { - "type": "string", - "description": "A foreign link name." - }, - "noJoin": { - "type": "boolean", - "description": "Prevents joining a foreign table when fetching a record. Available for belongsTo, hasOne." - }, - "foreignName": { - "type": "string", - "description": "A field to be used as a name of a foreign record. Needed when a foreign entity type does not have the field name." - }, - "audited": { - "type": "boolean", - "description": "Linking and unlinking will be logged in the Stream. Available for hasMany." - }, - "layoutRelationshipsDisabled": { - "type": "boolean", - "description": "Makes the link not available in the Bottom Panels layout (in the Layout Manager tool). Available for hasMany" - }, - "relationName": { - "type": "string", - "description": "A relationship name. Defines how a middle table will be named (for a many-to-many relationships). Available for hasMany" - }, - "additionalColumns": { - "type": "object", - "description": "Additional columns to be created in a middle table (for a many-to-many relationships).", - "additionalProperties": { - "type": "object", - "properties": { - "type": { - "enum": ["varchar", "int", "float", "bool"] - }, - "maxLength": { - "type": "integer" - }, - "default": { - "type": ["integer", "string", "boolean", "null", "number"] - }, - "dbType": { - "type": "string" - } - } - } - }, - "conditions": { - "type": "object", - "description": "Where-conditions (for a many-to-many relationships). If multiple links share the same relationship name (middle table), conditions must be defined for each link. For many-to-many.", - "additionalProperties": { - "type": ["string", "integer", "number", "boolean", "null"] - } - }, - "indexes": { - "type": "object", - "description": "Indexes for a middle table.", - "additionalProperties": { - "type": "object", - "properties": { - "columns": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Database columns of the index." - }, - "unique": { - "type": "boolean", - "description": "Whether the index is unique." - } - } - } - }, - "notMergeable": { - "type": "boolean", - "description": "Disable merging related records when duplicate records are being merged. For hasMany, hasChildren." - } - } + "$ref": "#/definitions/linkDefs" } }, "indexes": { @@ -646,6 +557,98 @@ } } } + }, + "linkDefs": { + "type": "object", + "description": "A link.", + "additionalProperties": true, + "properties": { + "type": { + "type": "string", + "description": "A link type.", + "enum": ["belongsTo", "hasMany", "hasOne", "belongsToParent", "hasChildren"] + }, + "entity": { + "type": "string", + "description": "A foreign entity type." + }, + "foreign": { + "type": "string", + "description": "A foreign link name." + }, + "noJoin": { + "type": "boolean", + "description": "Prevents joining a foreign table when fetching a record. Available for belongsTo, hasOne." + }, + "foreignName": { + "type": "string", + "description": "A field to be used as a name of a foreign record. Needed when a foreign entity type does not have the field name." + }, + "audited": { + "type": "boolean", + "description": "Linking and unlinking will be logged in the Stream. Available for hasMany." + }, + "layoutRelationshipsDisabled": { + "type": "boolean", + "description": "Makes the link not available in the Bottom Panels layout (in the Layout Manager tool). Available for hasMany" + }, + "relationName": { + "type": "string", + "description": "A relationship name. Defines how a middle table will be named (for a many-to-many relationships). Available for hasMany" + }, + "additionalColumns": { + "type": "object", + "description": "Additional columns to be created in a middle table (for a many-to-many relationships).", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "enum": ["varchar", "int", "float", "bool"] + }, + "maxLength": { + "type": "integer" + }, + "default": { + "type": ["integer", "string", "boolean", "null", "number"] + }, + "dbType": { + "type": "string" + } + } + } + }, + "conditions": { + "type": "object", + "description": "Where-conditions (for a many-to-many relationships). If multiple links share the same relationship name (middle table), conditions must be defined for each link. For many-to-many.", + "additionalProperties": { + "type": ["string", "integer", "number", "boolean", "null"] + } + }, + "indexes": { + "type": "object", + "description": "Indexes for a middle table.", + "additionalProperties": { + "type": "object", + "properties": { + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Database columns of the index." + }, + "unique": { + "type": "boolean", + "description": "Whether the index is unique." + } + } + } + }, + "notMergeable": { + "type": "boolean", + "description": "Disable merging related records when duplicate records are being merged. For hasMany, hasChildren." + } + } } } } diff --git a/schema/metadata/fields.json b/schema/metadata/fields.json new file mode 100644 index 0000000000..7c4838fd35 --- /dev/null +++ b/schema/metadata/fields.json @@ -0,0 +1,164 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/fields.json", + "title": "fields", + "description": "Field definitions.", + "type": "object", + "properties": { + "notMergeable": { + "type": "boolean", + "description": "Whether this field type is mergeable (when merging duplicate records)." + }, + "notCreatable": { + "type": "boolean", + "description": "Whether the field of this type can be created in the Entity Manager tool." + }, + "readOnly": { + "type": "boolean", + "description": "Is this field type Read Only (can't be edited)." + }, + "skipOrmDefs": { + "type": "boolean", + "description": "Skip converting to defs for the ORM." + }, + "filter": { + "type": "boolean", + "description": "Records can be filtered by this field (available as filter on the list view)." + }, + "view": { + "type": "string", + "description": "A frontend view." + }, + "params": { + "type": "array", + "description": "Field parameters.", + "items": { + "allOf": [ + { + "$ref": "./entityDefs.json#/definitions/fieldDefs" + }, + { + "properties": { + "hidden": { + "type": "boolean", + "description": "Do not display the parameter in the field manager." + }, + "name": { + "type": "string", + "description": "A name." + } + } + } + ] + } + }, + "fieldDefs": { + "description": "An object of field type definition", + "$ref": "./entityDefs.json#/definitions/fieldDefs" + }, + "translatedOptions": { + "type": "boolean", + "description": "Does the field have options that can be translated." + }, + "hookClassName": { + "type": "string", + "description": "A hook class. Called after the field is created or edited in the Entity Manager tool." + }, + "fields": { + "type": "object", + "description": "Definitions of additional fields that will be created with this field. E.g. for address field, separate fields (street, city, etc.) are created.", + "additionalProperties": { + "$ref": "./entityDefs.json#/definitions/fieldDefs" + } + }, + "naming": { + "enum": ["suffix", "prefix"], + "description": "The naming determines how additional fields will be named." + }, + "actualFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The list of actual attributes (which contain useful data). For example, for field type link in actualFields is ['id'], in notActualFields is ['name']. Means, if you load record with link field, you have values in {fieldName}Id and {fieldName}Name (suffix naming). But you need set only {fieldName}Id, if you want to update this field." + }, + "notActualFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The list of not actual attributes." + }, + "personalData": { + "type": "boolean", + "description": "Where the field may contain personal data." + }, + "textFilter": { + "type": "boolean", + "description": "The field will be available in the list of text filters (in the Entity Manager tool)." + }, + "textFilterForeign": { + "type": "boolean", + "description": "The field will be available in the list of text filters as a foreign field." + }, + "linkDefs": { + "$ref": "./entityDefs.json#/definitions/linkDefs", + "description": "If defined, a link with the same name as the field name will be created." + }, + "fullTextSearch": { + "type": "boolean", + "description": "Full-text search will be available for the field." + }, + "fullTextSearchColumnList": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Columns used in full-text search." + }, + "valueFactoryClassName": { + "type": "string", + "description": "A factory that creates value-objects for this field. A value-object can be obtained by calling getValueObject method on an Entity. Should implement Espo\\ORM\\Value\\ValueFactory." + }, + "attributeExtractorClassName": { + "type": "string", + "description": "A class that extracts values (attribute => value map) from a value-object. Used internally for obtaining values from a value-object and writing them to an entity. Should implement Espo\\ORM\\Value\\AttributeExtractor." + }, + "validationList": { + "type": "array", + "items": { + "anyOf": [ + {"type": "string"}, + {"const": "__APPEND__"} + ] + }, + "description": "Validations applied server-side." + }, + "mandatoryValidationList": { + "type": "array", + "items": { + "anyOf": [ + {"type": "string"}, + {"const": "__APPEND__"} + ] + }, + "description": "Validations applied server-side." + }, + "validatorClassNameMap": { + "type": "object", + "description": "Validators. Should implement Espo\\Core\\FieldValidation\\Validator.", + "additionalProperties": { + "type": "string", + "description": "A validation name." + } + }, + "duplicatorClassName": { + "type": "string", + "description": "Duplicates attributes of a field. Some fields can require some processing when an entity is being duplicated. Should implement Espo\\Core\\Record\\Duplicator\\FieldDuplicator." + }, + "converterClassName": { + "type": "string", + "description": "A metadata converter. Converts field metadata to ORM metadata. Should implement Espo\\Core\\Utils\\Database\\Orm\\FieldConverter." + } + } +}