ObjectOS
構築

データモデル

オブジェクト、フィールド、リレーションシップ、バリデーション、インデックス — AI に説明するか、TypeScript で記述します。

データモデル

データモデルは、アプリにとって唯一の信頼できる情報源です。オブジェクトが 存在するようになると、ObjectOS は REST API、Console ビュー、RBAC の チェックポイント、監査ログのエントリ、そして AI ツールへの公開を — 無償で 提供します。

**ほとんどのお客様はスキーマを手書きすることはありません。**必要なものを AI Builder で説明すると、プラットフォームが オブジェクト、フィールド、インデックス、翻訳を作成します。このページでは その基盤となる構造を説明します — AI が生成しているものを理解し、必要に 応じて直接編集できるようにするためです。

オーサリングのパス

パス具体例
AI Builder(推奨)「subject、description、priority、status、assignee を持つ support_ticket オブジェクトを作成して。」
Console のクリックビルドConsole → Objects → New Object → フォーム
TypeScript(*.object.ts下に示す TS — 通常はフォークしたテンプレートの中で記述

この 3 つはいずれも同じスキーマを生成します。スキーマが正規のものであり、 それ以外はすべて派生物です。

オブジェクトの構造

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

スタックに登録します:

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

必要なのはこれだけです。os dev が再コンパイルを行い、/api/v1/data/todo_task、 Console の Task ビュー、そして Console のパーミッション行がすべて表示されます。

フィールドタイプ

ObjectStack には約 25 種類のフィールドタイプが付属します。よく使われるものは 次のとおりです:

スカラー

タイプ格納する内容ヘルパー
text短い文字列Field.text({ maxLength, required })
textarea長い文字列Field.textarea(...)
markdownmarkdown 形式のリッチテキストField.markdown(...)
number整数Field.number({ min, max })
decimal正確な小数(金額など)Field.decimal({ precision, scale })
boolean真偽値Field.boolean({ defaultValue })
dateカレンダー日付Field.date(...)
datetimeタイムスタンプField.datetime(...)
emailバリデーション済みメールアドレスField.email(...)
urlバリデーション済み URLField.url(...)
phoneバリデーション済み電話番号Field.phone(...)
json任意の JSONField.json(...)

選択肢

タイプ用途
select単一選択(列挙)
multiselect複数選択

リレーションシップ

タイプカーディナリティヘルパー
lookup一対多(FK)Field.lookup({ reference: 'sys_user' })
masterDetailカスケード削除付きの一対多Field.masterDetail({ reference: 'order' })

ファイルとメディア

タイプ格納する内容
fileストレージサービス経由の単一ファイル
imageプレビュー付きの画像ファイル

計算 / 派生

タイプ動作
formulaCEL 式から読み取り時に計算
summary関連レコードの集計(sum/count/avg)
autonumberシーケンス(INV-{000001}
created, lastModifiedシステムが保守するタイムスタンプ
createdBy, lastModifiedByシステムが保守するユーザー参照

必須 / 一意 / デフォルト

すべてのスカラーフィールドで共通の修飾子:

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

バリデーション

インライン:

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

オブジェクトレベルのルール(フィールド間):

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

バリデーションはあらゆる書き込み時に実行されます — REST、Console、ObjectQL のいずれでも — そのため「裏口」は存在しません。

インデックスとパフォーマンス

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

ドライバーはスキーマ同期時に実際の DB インデックスを作成します。

フィールドグループ

長いフォームでは、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' }),
  },
});

ライフサイクルと所有権

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

システムオブジェクト(すべてのプロジェクトで無償)

これらを宣言する必要はありません — 常に存在します:

オブジェクト内容
sys_userユーザーアカウント
sys_org組織 / テナント
sys_member組織のメンバーシップ
sys_role, sys_permission_setRBAC のプリミティブ
sys_audit_log監査証跡(監査機能がロードされている場合)
sys_file, sys_attachmentファイルのメタデータ(ストレージがロードされている場合)
sys_comment, sys_activityフィード / chatter(フィードがロードされている場合)
sys_session, sys_api_key認証アーティファクト
sys_webhook, sys_webhook_deliveryWebhook サブスクリプション(有効化されている場合)

lookup フィールドでは名前で参照します — 例: Field.lookup({ reference: 'sys_user' })

ポリモーフィックなプラットフォーム機能

feeds: truetrackHistory: true を有効にすると、オブジェクトは 自動的に次の機能に参加します:

  • sys_comment(thread_id = <object>:<id>
  • sys_attachment(parent_object = <object>、parent_id = <id>
  • sys_activity(タイムライン)
  • sys_audit_log(フィールドレベルの差分)

これらをオブジェクトごとに配線する必要はありません — プラットフォーム上で ポリモーフィックに動作します。

次に読むべきもの

On this page