Resumen
Los objetos personalizados son nuevos tipos de registro que tu aplicación añade a un espacio de trabajo — Tarjeta postal, Factura, Suscripción, cualquier cosa específica de tu dominio. Cada objeto declara su esquema (campos, relaciones, valores predeterminados) y un identificador universal estable que se mantiene a través de sincronizaciones e implementaciones.src/objects/post-card.object.ts
Puntos clave
- El
universalIdentifierdebe ser único y estable entre implementaciones. - Cada campo requiere
name,type,labely su propiouniversalIdentifierestable. - La matriz
fieldses opcional: puedes definir objetos sin campos personalizados. openRecordInestablece dónde se abren los registros de este objeto al hacer clic:ObjectOpenRecordIn.USER_CHOICE(el valor predeterminado, que sigue la preferencia de cada miembro del espacio de trabajo en Settings → Experience),ObjectOpenRecordIn.SIDE_PANELoObjectOpenRecordIn.RECORD_PAGE. Fíjalo enRECORD_PAGEpara los registros que necesitan una página completa para ser utilizables, como ocurre con los flujos de trabajo y los paneles, o enSIDE_PANELpara los registros que solo tienen sentido como un panel rápido, como los eventos del calendario.disabledObjectPermissionActionsenumera los permisos de objeto que no se pueden conceder sobre el objeto: cualquiera de'canReadObjectRecords','canUpdateObjectRecords','canSoftDeleteObjectRecords'y'canDestroyObjectRecords', las mismas marcas que un rol establece por objeto. Los usuarios, las claves de API y los agentes nunca obtienen estas acciones sobre el objeto, independientemente de lo que conceda su rol, y falla al guardar un permiso de objeto que concede una de ellas. Las funciones de lógica propias de tu aplicación las conservan. Por ejemplo,['canUpdateObjectRecords', 'canSoftDeleteObjectRecords', 'canDestroyObjectRecords']hace que un objeto solo pueda ser escrito por tu aplicación, para registros similares a configuraciones que conceden comportamiento.colorestablece el color de acento del objeto en la IU. Omítelo y Twenty elegirá uno para el objeto.imageIdentifierFieldMetadataUniversalIdentifiernombra el campo cuyo valor se muestra como el avatar del registro. Omítelo para que Twenty elija el predeterminado.isLabelSyncedWithName, en un objeto o en un campo, mantiene el nombre de la API sincronizado con la etiqueta cuando esta se edita en Configuración. De forma predeterminada esfalse, por lo que una etiqueta renombrada deja el nombre sin cambios.isSearchable: true, en un campo, incluye sus valores en la búsqueda de texto completo del objeto (búsqueda global y el menú de comandos). Requiere que el propio objeto permita búsquedas y que el tipo de campo sea compatible con texto. Un valor omitido significa que no permite búsquedas, excepto en el campo identificador de etiqueta del objeto, que siempre permite búsquedas y no se puede excluir. Cada sincronización aplica el estado declarado, por lo que un campo cuya opción de búsqueda se active desde Configuración se revertirá en la siguiente sincronización de tu aplicación, a menos que el manifiesto lo declare.isAuditLogged: falseen un campo evita que sus cambios aparezcan en la cronología del registro. De forma predeterminada estrue, excepto en un campoPOSITION, cuyos cambios aparecen en blanco en la cronología y nunca se registran. Establécelo en los campos que tu aplicación reescribe de forma programada, como una marca de tiempo del último contacto o una relación de acumulación, para que cada sincronización no agregue una fila de actividad a cada registro que modifique. Una actualización cuyo diferencial completo está compuesto por campos sin registro de auditoría no produce ninguna actividad en la cronología. Al igual queisSearchable, cada sincronización aplica el estado declarado.disabledFieldPermissionActions, en un campo, enumera los permisos de campo que no se pueden conceder en él:'canReadFieldValue','canUpdateFieldValue'o ambos, los mismos indicadores que un rol establece por campo. Los usuarios, las claves de API, los agentes y otras aplicaciones nunca obtienen estas acciones en el campo, independientemente de lo que conceda su rol, y guardar un permiso de campo que conceda una de ellas falla. Las funciones de lógica de tu propia aplicación las conservan. Por ejemplo,['canUpdateFieldValue']mantiene un valor que tu aplicación calcula o sincroniza, como un estado o una puntuación, en modo de solo lectura para todos los demás. También funciona en los campos que agregas a objetos que no te pertenecen condefineField().- Los campos en línea definidos aquí no necesitan un
objectUniversalIdentifier, ya que se hereda del objeto padre. UsadefineField()para añadir campos a objetos que no te pertenecen. - Puedes generar nuevos objetos con
twenty app add object, que te guía en la asignación de nombres, los campos y las relaciones. Consulta Arquitectura → Generación de entidades.
Los campos base se añaden automáticamente. Cuando defines un objeto personalizado,
Twenty crea campos estándar como
id, name, createdAt, updatedAt,
createdBy, updatedBy y deletedAt por ti. No necesitas declararlos
en tu matriz fields; solo tus campos personalizados. Puedes sobrescribir un
campo predeterminado declarando uno con el mismo nombre, pero esto rara vez es una buena
idea.Tipos de campo
El conjunto completo de valores deFieldType, exportados desde twenty-sdk/define:
Los tipos compuestos almacenan múltiples subcampos (por ejemplo,
FULL_NAME = nombre + apellido; CURRENCY = amountMicros + currencyCode). SELECT y MULTI_SELECT requieren un arreglo options como en el ejemplo anterior.
Selecciona opciones
ParaSELECT y MULTI_SELECT, proporcione una matriz no vacía de objetos options. Cada opción tiene un value, un label y una position. Su color es opcional y toma de forma predeterminada el valor gray cuando se omite o es nulo.
Cuando se proporciona, color debe ser uno de los siguientes: red, ruby, crimson, tomato, orange, amber, yellow, lime, grass, green, jade, mint, turquoise, cyan, sky, blue, iris, violet, purple, plum, pink, bronze, gold, brown, gray.
Tanto defineObject() como defineField() devuelven errores de validación para colores no compatibles o entradas de opciones que son nulas, primitivas o matrices.
Valores predeterminados
Los valores predeterminados de cadenas literales deben ir entre comillas simples dentro de la cadena —defaultValue: "'Draft'", no defaultValue: "Draft". Por eso el campo status anterior utiliza `'${PostCardStatus.DRAFT}'`.
Las cadenas sin comillas se reservan para valores predeterminados calculados, evaluados cuando se crea un registro:
'uuid'— genera un UUID (para camposUUID)'now'— la marca de tiempo actual (para camposDATE_TIME)
{ source: "'MANUAL'" } en un campo ACTOR) y a los valores de SELECT/MULTI_SELECT. Un valor predeterminado de tipo cadena literal dejado sin comillas genera una advertencia cuando se compila tu aplicación.
Nulabilidad
isNullable controla si un campo acepta NULL. Su valor predeterminado es true — omítelo para campos opcionales. Configura isNullable: false para hacer que un campo sea obligatorio a nivel de base de datos.
Los cambios en isNullable se aplican en cada sincronización, incluidas las sincronizaciones que actualizan un campo existente; de este modo, puedes cambiar la nulabilidad de un campo editando el manifiesto y sincronizando de nuevo.
Hacer que un campo existente no acepte valores nulos requiere un valor predeterminado. Cuando
cambies un campo a
isNullable: false, también debes proporcionar un defaultValue no nulo. El valor predeterminado rellena cualquier fila NULL existente antes de que se aplique la restricción NOT NULL; sin él, la sincronización falla con Default value cannot be null for non-nullable fields. Los campos de relación y los campos TS_VECTOR
siempre aceptan valores nulos, por lo que isNullable no tiene ningún efecto en ellos.¿Qué sigue
- Conecta este objeto con otros: consulta Relaciones para el patrón de relación bidireccional.
- Añade campos a objetos de otras aplicaciones: consulta Extender objetos para
defineField(). - Mostrar este objeto en la IU — consulta Elementos del menú de navegación para añadir una entrada en la barra lateral; consulta Vistas para añadir configuraciones de lista personalizadas.