ObjectOS
Construir

Modelo de datos

Objetos, campos, relaciones, validación, índices — descritos a la IA o escritos en TypeScript.

Modelo de datos

El modelo de datos es la única fuente de verdad de tu aplicación. Una vez que existe un objeto, ObjectOS te ofrece APIs REST, una vista en Console, puntos de control de RBAC, entradas en el registro de auditoría y exposición de herramientas de IA — de forma gratuita.

La mayoría de los clientes nunca escriben el esquema a mano. Describen lo que necesitan en el AI Builder y la plataforma crea los objetos, campos, índices y traducciones. Esta página describe la forma subyacente — para que entiendas lo que la IA está generando y puedas editarlo directamente cuando quieras.

Vías de creación

VíaCómo se ve
AI Builder (principal)"Crea un objeto support_ticket con asunto, descripción, prioridad, estado y responsable."
Construcción con clics en ConsoleConsole → Objects → New Object → formularios
TypeScript (*.object.ts)El TS que se muestra a continuación — normalmente dentro de una plantilla bifurcada

Las tres producen el mismo esquema. El esquema es canónico; todo lo demás se deriva de él.

Anatomía de un objeto

// src/objects/task.ts
import { ObjectSchema, Field } from '@objectstack/spec/data';

export const Task = ObjectSchema.create({
  name: 'todo_task',
  label: 'Task',
  pluralLabel: 'Tasks',
  icon: 'check-square',
  description: 'A single unit of work.',

  fields: {
    subject:     Field.text({ label: 'Subject', required: true, maxLength: 200 }),
    description: Field.markdown({ label: 'Description' }),
    status:      Field.select({
      label: 'Status',
      options: [
        { label: 'To Do',       value: 'todo', default: true },
        { label: 'In Progress', value: 'in_progress' },
        { label: 'Done',        value: 'done' },
      ],
    }),
    due:         Field.date({ label: 'Due' }),
    assignee:    Field.lookup('sys_user', { label: 'Assignee' }),
  },

  enable: {
    trackHistory: true,    // record field changes in audit log
    apiEnabled: true,      // expose REST endpoints (default true)
    feeds: true,           // chatter / comments / @mentions
  },
});

Regístralo en tu stack:

// objectstack.config.ts
import { defineStack } from '@objectstack/spec';
import * as objects from './src/objects';

export default defineStack({
  manifest: { id: 'my.app', namespace: 'myapp', version: '0.1.0', type: 'app', name: 'My App' },
  objects: Object.values(objects),
});

Eso es todo lo que necesitas. os dev recompila, y /api/v1/data/todo_task, la vista Task de Console y la fila de permisos de Console aparecen todas.

Tipos de campo

ObjectStack incluye unos 25 tipos de campo. Los más usados:

Escalares

TipoQué almacenaHelper
textCadena cortaField.text({ maxLength, required })
textareaCadena largaField.textarea(...)
markdownTexto enriquecido con markdownField.markdown(...)
numberEnteroField.number({ min, max })
decimalDecimal exacto (dinero, etc.)Field.decimal({ precision, scale })
booleanVerdadero/falsoField.boolean({ defaultValue })
dateFecha de calendarioField.date(...)
datetimeMarca de tiempoField.datetime(...)
emailCorreo electrónico validadoField.email(...)
urlURL validadaField.url(...)
phoneTeléfono validadoField.phone(...)
jsonJSON arbitrarioField.json(...)

Opciones

TipoSe usa para
selectOpción única (enum)
multiselectVarias opciones

Relaciones

TipoCardinalidadHelper
lookupUno a muchos (FK)Field.lookup({ reference: 'sys_user' })
masterDetailUno a muchos con eliminación en cascadaField.masterDetail({ reference: 'order' })

Archivos y multimedia

TipoQué almacena
fileUn archivo mediante el servicio de almacenamiento
imageArchivo de imagen con vista previa

Calculados / derivados

TipoComportamiento
formulaCalculado en el momento de la lectura a partir de una expresión CEL
summaryAgregado de registros relacionados (suma/recuento/promedio)
autonumberSecuencia (INV-{000001})
created, lastModifiedMarcas de tiempo mantenidas por el sistema
createdBy, lastModifiedByReferencias de usuario mantenidas por el sistema

Required / unique / default

Modificadores comunes en cada campo escalar:

Field.text({
  label: 'Code',
  required: true,
  unique: true,          // unique constraint enforced at DB level
  defaultValue: '',
  helpText: 'Internal short code',
})

Validación

En línea:

Field.number({ label: 'Quantity', min: 1, max: 9999 })
Field.text({ label: 'SKU', pattern: '^[A-Z]{3}-[0-9]{4}$' })

Reglas a nivel de objeto (entre campos):

ObjectSchema.create({
  name: 'order',
  fields: { /* ... */ },
  validations: [
    {
      name: 'discount_lt_total',
      message: 'Discount cannot exceed total',
      condition: 'discount < total',
    },
  ],
});

La validación se ejecuta en cada escritura — REST, Console, ObjectQL — por lo que no hay "puerta trasera".

Índices y rendimiento

ObjectSchema.create({
  name: 'order',
  fields: { /* ... */ },
  indexes: [
    { fields: ['status', 'created_at'] },
    { fields: ['account', 'created_at'], unique: false },
  ],
});

El controlador crea índices reales en la base de datos al sincronizar el esquema.

Grupos de campos

Para formularios largos, agrupa los campos en Console:

ObjectSchema.create({
  name: 'task',
  fieldGroups: [
    { key: 'core',     label: 'Task',     icon: 'check-square' },
    { key: 'planning', label: 'Planning', icon: 'calendar' },
    { key: 'meta',     label: 'Metadata', icon: 'info', defaultExpanded: false },
  ],
  fields: {
    subject: Field.text({ label: 'Subject', group: 'core' }),
    due:     Field.date({ label: 'Due',     group: 'planning' }),
  },
});

Ciclo de vida y propiedad

ObjectSchema.create({
  name: 'task',
  ownership: 'own',          // 'own' | 'shared' | 'system'
  enable: {
    apiEnabled: true,         // generated REST endpoints
    trackHistory: true,       // audit log of field changes
    feeds: true,              // sys_comment / sys_activity / @mentions
    softDelete: true,         // tombstone instead of hard delete
  },
});

Objetos del sistema (gratuitos con cada proyecto)

No tienes que declararlos — siempre están ahí:

ObjetoQué
sys_userCuentas de usuario
sys_orgOrganizaciones / tenants
sys_memberPertenencia a una organización
sys_role, sys_permission_setPrimitivas de RBAC
sys_audit_logRastro de auditoría (cuando se carga la capacidad de auditoría)
sys_file, sys_attachmentMetadatos de archivos (cuando se carga el almacenamiento)
sys_comment, sys_activityFeed / chatter (cuando se carga el feed)
sys_session, sys_api_keyArtefactos de autenticación
sys_webhook, sys_webhook_deliverySuscripciones de webhook (cuando están habilitadas)

Haz referencia a ellos en los campos lookup por su nombre — p. ej. Field.lookup({ reference: 'sys_user' }).

Funciones polimórficas de la plataforma

Cuando habilitas feeds: true y trackHistory: true, tu objeto participa automáticamente en:

  • sys_comment (thread_id = <object>:<id>)
  • sys_attachment (parent_object = <object>, parent_id = <id>)
  • sys_activity (cronología)
  • sys_audit_log (diferencias a nivel de campo)

No conectas esto por cada objeto — es polimórfico en la plataforma.

Adónde ir a continuación

On this page