ObjectOS
Construire

Modèle de données

Objets, champs, relations, validation, index — décrits à l'IA ou écrits en TypeScript.

Modèle de données

Le modèle de données est la source de vérité unique de votre application. Dès qu'un objet existe, ObjectOS vous fournit des API REST, une vue Console, des points de contrôle RBAC, des entrées de journal d'audit et une exposition aux outils d'IA — gratuitement.

La plupart des clients n'écrivent jamais le schéma à la main. Ils décrivent ce dont ils ont besoin dans l'AI Builder et la plateforme crée les objets, les champs, les index et les traductions. Cette page décrit la structure sous-jacente — afin que vous compreniez ce que l'IA génère et que vous puissiez la modifier directement quand vous le souhaitez.

Méthodes de création

MéthodeÀ quoi cela ressemble
AI Builder (principale)« Créer un objet support_ticket avec sujet, description, priorité, statut, responsable. »
Construction par clic dans la ConsoleConsole → Objects → New Object → formulaires
TypeScript (*.object.ts)Le TS présenté ci-dessous — généralement à l'intérieur d'un template forké

Les trois produisent le même schéma. Le schéma est canonique ; tout le reste en est dérivé.

Anatomie d'un objet

// 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
  },
});

Enregistrez-le dans votre 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),
});

C'est tout ce dont vous avez besoin. os dev recompile, et /api/v1/data/todo_task, la vue Task de la Console et la ligne d'autorisation de la Console apparaissent tous.

Types de champs

ObjectStack fournit environ 25 types de champs. Les plus utilisés :

Scalaires

TypeCe qu'il stockeHelper
textChaîne courteField.text({ maxLength, required })
textareaChaîne longueField.textarea(...)
markdownTexte enrichi avec markdownField.markdown(...)
numberEntierField.number({ min, max })
decimalDécimal exact (monnaie, etc.)Field.decimal({ precision, scale })
booleanVrai/fauxField.boolean({ defaultValue })
dateDate du calendrierField.date(...)
datetimeHorodatageField.datetime(...)
emailE-mail validéField.email(...)
urlURL validéeField.url(...)
phoneTéléphone validéField.phone(...)
jsonJSON arbitraireField.json(...)

Choix

TypeÀ utiliser pour
selectChoix unique (enum)
multiselectChoix multiples

Relations

TypeCardinalitéHelper
lookupUn-à-plusieurs (FK)Field.lookup({ reference: 'sys_user' })
masterDetailUn-à-plusieurs avec suppression en cascadeField.masterDetail({ reference: 'order' })

Fichiers et médias

TypeCe qu'il stocke
fileUn fichier via le service de stockage
imageFichier image avec aperçu

Calculé / dérivé

TypeComportement
formulaCalculé à la lecture à partir d'une expression CEL
summaryAgrégat d'enregistrements liés (somme/nombre/moyenne)
autonumberSéquence (INV-{000001})
created, lastModifiedHorodatages gérés par le système
createdBy, lastModifiedByRéférences utilisateur gérées par le système

Requis / unique / par défaut

Modificateurs courants sur chaque champ scalaire :

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

Validation

En ligne :

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

Règles au niveau de l'objet (entre champs) :

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

La validation s'exécute à chaque écriture — REST, Console, ObjectQL — il n'y a donc aucune « porte dérobée ».

Index et performance

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

Le driver crée de vrais index de base de données lors de la synchronisation du schéma.

Groupes de champs

Pour les formulaires longs, regroupez les champs dans la 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' }),
  },
});

Cycle de vie et propriété

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
  },
});

Objets système (gratuits avec chaque projet)

Vous n'avez pas à les déclarer — ils sont toujours présents :

ObjetQuoi
sys_userComptes utilisateurs
sys_orgOrganisations / locataires
sys_memberAppartenance à une organisation
sys_role, sys_permission_setPrimitives RBAC
sys_audit_logPiste d'audit (lorsque la capacité d'audit est chargée)
sys_file, sys_attachmentMétadonnées de fichier (lorsque le stockage est chargé)
sys_comment, sys_activityFil / chatter (lorsque le fil est chargé)
sys_session, sys_api_keyArtefacts d'authentification
sys_webhook, sys_webhook_deliveryAbonnements webhook (lorsqu'ils sont activés)

Référencez-les dans les champs lookup par leur nom — par exemple Field.lookup({ reference: 'sys_user' }).

Fonctionnalités polymorphes de la plateforme

Lorsque vous activez feeds: true et trackHistory: true, votre objet participe automatiquement à :

  • sys_comment (thread_id = <object>:<id>)
  • sys_attachment (parent_object = <object>, parent_id = <id>)
  • sys_activity (chronologie)
  • sys_audit_log (différences au niveau des champs)

Vous ne câblez pas cela par objet — c'est polymorphe sur la plateforme.

Pour aller plus loin

On this page