資料來源
把 ObjectOS 連線到你現有的業務資料庫,把物件路由到它們,並讓 AI 原生地查詢這些資料。
資料來源是到外部資料儲存的一個具名連線。通過宣告資料來源,你把 ObjectOS 指向你的業務已經在執行的資料庫 —— 一個生產 PostgreSQL、一個用於報表的 MySQL 副本、一個 MongoDB 叢集 —— 然後把物件繫結到它們。物件一旦繫結,平臺 中的其他一切(REST API、許可權、流程、儀表盤和 AI Agent)都會統一地基於 這些資料工作,而不關心資料行實際存放在哪裡。
這是 ObjectOS 最實用的採用路徑之一:不必遷移遺留系統,而是連線它,把你關心 的表建模為物件,然後在原地不動的資料之上用 AI 原生能力擴充套件它 —— 對話、 分析、自動化。
資料來源是什麼
每個資料來源都是一個由 DatasourceSchema 校驗的普通物件。核心欄位:
| 欄位 | 用途 |
|---|---|
name | 物件所引用的唯一識別符號(^[a-z_][a-z0-9_]*$) |
label | 便於閱讀的顯示名稱 |
driver | 由哪個驅動處理連線(postgres、mysql、sqlite、mongodb、memory,或某個外掛提供的驅動) |
config | 驅動專屬的連線設定(主機、資料庫、憑據 ……) |
pool | 連線池大小(min、max、超時) |
schemaMode | 誰擁有模式:managed(預設)允許 ObjectOS 建立和修改表;external 或 validate-only 宣告一個 ObjectOS 不擁有的資料庫,ObjectOS 不會在其上執行任何 DDL |
external | 外部資料來源的聯邦策略 —— 它的寫入門控和啟動校驗 —— 以及 credentialsRef,即任何資料來源都可以攜帶的金鑰儲存引用 |
active | 連線是否啟用 |
readReplicas、capabilities(及其 readOnly 標誌)、healthCheck 和
retryPolicy 已在 ObjectStack 17.0 中移除:沒有任何執行時路徑讀取過它們。
解析時會逐個拒絕它們,並點名真正決定該行為的機制。
自帶的驅動有:
| 驅動包 | driver | 後端 |
|---|---|---|
@objectstack/driver-sql | postgres、mysql、sqlite | PostgreSQL、MySQL、SQLite(通過 knex) |
@objectstack/driver-mongodb | mongodb | MongoDB |
@objectstack/driver-memory | memory | 程序內,用於測試 —— 自 ObjectStack 17.7 起不再作為啟動儲存 |
@objectstack/driver-sqlite-wasm | sqlite(WASM) | WebContainers / 瀏覽器中的 SQLite |
宣告資料來源
資料來源在技術棧上宣告,由 defineStack 組裝。用 defineDatasource() 定義
每個連線,然後把它們列在 datasources 下:
// src/datasources/business.datasource.ts
import { defineDatasource } from '@objectstack/spec';
// Connect to an EXISTING production database that ObjectOS does not own.
// `external` mode: ObjectOS runs no DDL here, and writes stay off until you
// opt in. The password is never inline: it lives in the secrets store, and
// the datasource only references it.
export const BusinessDb = defineDatasource({
name: 'business_primary',
label: 'Business System (Postgres)',
driver: 'postgres',
schemaMode: 'external',
config: {
host: 'db.internal.example.com',
port: 5432,
database: 'business',
username: 'objectos_readonly', // a database user granted SELECT only
},
external: {
allowWrites: false, // the default: the datasource refuses writes
credentialsRef: 'secret:business_db/password',
},
pool: { min: 1, max: 10 },
active: true,
});// objectstack.config.ts
import { defineStack } from '@objectstack/spec';
import * as objects from './src/objects/index.js';
import { BusinessDb } from './src/datasources/business.datasource.js';
export default defineStack({
manifest: {
id: 'app.example.crm-extend',
namespace: 'biz',
version: '1.0.0',
type: 'app',
name: 'CRM extension',
},
datasources: [BusinessDb],
objects: Object.values(objects),
});
defineDatasource()在你編寫它的地方就做校驗。 它從@objectstack/spec(以及@objectstack/spec/data)匯出,在宣告處執行DatasourceSchema校驗,所以錯誤的欄位會在包含它的檔案中報告。框架的examples/app-crm技術棧就是這樣宣告資料來源的。型別為Datasource(來自@objectstack/spec/data)的普通物件也被接受,會在技術棧組裝時校驗。憑據絕不內聯。
DatasourceSchema會拒絕config中的password, 即使它是從環境變數讀取的:資料來源會被完整地儲存在sys_metadata中,所以 內聯的金鑰會以明文躺在那裡。把金鑰放進金鑰儲存,並在external.credentialsRef中指定它。解析出的金鑰會在連線時注入。
把物件繫結到資料來源
每個物件都有一個 datasource 欄位。它預設為 'default'(主資料庫)。設定
它,就能把某個特定物件路由到你所連線的某個系統:
import { ObjectSchema, Field } from '@objectstack/spec/data';
export const Customer = ObjectSchema.create({
name: 'biz_customer',
label: 'Customer',
sharingModel: 'private',
datasource: 'business_primary', // ← queries go to the business DB
external: { remoteName: 'customers' }, // the remote TABLE name
fields: {
name: Field.text({ label: 'Name', required: true }),
email: Field.text({ label: 'Email' }),
tier: Field.select({
label: 'Tier',
options: [
{ label: 'Standard', value: 'standard' },
{ label: 'Premium', value: 'premium' },
],
}),
},
});物件所繫結的資料來源必須能連上,否則啟動失敗。 從 ObjectStack 17.0 起,無法連線的資料來源是啟動失敗,而不是一行警告。過去只有帶
validation.onMismatch: 'fail'的external資料來源會快速失敗:一個聲明瞭datasource: 'analytics'並綁定了物件的應用,用錯誤的 URL 啟動時會乾淨地 啟動並以零退出 —— 然後這些物件的每次讀寫都以Datasource 'x' is not registered失敗。當某個資料驅動停止響應時,/api/v1/ready也會報告 503,所以資料庫已經消失的副本會被移出輪換, 而不是繼續返回錯誤。連線嘗試的上限是 10 秒。參見 17.0 釋出說明。
用 datasourceMapping 集中路由
逐個繫結物件,對少量物件來說沒問題。對於整個名稱空間或包,在技術棧上一次性
宣告路由規則。規則按順序(或按 priority)求值;第一個匹配的規則生效:
// A second connection, for reporting.
export const AnalyticsReplica = defineDatasource({
name: 'analytics_replica',
label: 'Analytics replica',
driver: 'postgres',
schemaMode: 'external',
config: {
host: 'replica.internal.example.com',
port: 5432,
database: 'business',
username: 'objectos_reports',
},
external: { credentialsRef: 'secret:analytics_db/password' },
});
export default defineStack({
datasources: [BusinessDb, AnalyticsReplica],
datasourceMapping: [
{ namespace: 'biz', datasource: 'business_primary' },
{ objectPattern: 'report_*', datasource: 'analytics_replica' },
{ package: 'com.example.logs', datasource: 'default' },
{ default: true, datasource: 'default' },
],
});規則按 namespace、package、objectPattern(glob)或 default 匹配,並
指定目標 datasource。這讓資料駐留的決策集中在一處,而不是散落在各個物件
檔案中。
從現有的表生成物件
你不必為每張表手寫一個物件。如今把遺留模式接入 ObjectOS 最快的方式,是
用一個編碼 Agent(Claude Code)掃描業務表並生成原始碼級的物件定義 ——
每張表一個 *.object.ts 檔案,形態完全符合框架的預期。
hotcrm 參考應用是這種形態的
標準示例:每張表是一個 src/objects/<name>.object.ts 檔案,使用
ObjectSchema.create({ … }) 和 Field.* 定義,全部由 defineStack 組裝。
典型流程:
- 連線業務資料庫,作為一個數據源(見上文)。
- 把 Claude Code 指向模式。 讓它內省所連線的資料庫 —— 表名、列、型別、
外部索引鍵 —— 併為每張表生成一個
ObjectSchema.create檔案,把 SQL 列對映為Field.*型別,把外部索引鍵對映為Field.lookup(...)。把每個物件的datasource設為你的連線(或依賴datasourceMapping),並在表名與物件 名不同時設定external.remoteName。 - 審閱和細化生成的物件 —— 新增標籤、欄位分組、校驗和許可權。輸出是你
擁有並提交的普通原始碼,就像
hotcrm/src/objects/*.object.ts一樣。 - 執行。 這些物件現在通過繫結的資料來源讀取你現有的表。啟動時,執行時會
檢查每個物件與其表是否一致(
external.validation),預設情況下不一致會 導致啟動失敗。寫入保持關閉,直到兩道門控都開啟:資料來源上的external.allowWrites: true和物件上的external.writable: true。
由於生成的物件是普通原始碼,你擁有完全的控制權:保留合適的部分,刪掉你不想 暴露的列,並在一個平臺從未需要擁有的資料庫之上疊加 ObjectOS 的功能(歷史 跟蹤、活動、共享規則)。
查詢下推
什麼在資料庫中執行、什麼由引擎求值,由每個驅動自己決定,而不是由資料來源
後設資料決定。聯邦物件上的過濾條件,比如 ?tier=premium,會被下推到遠端查詢。
沒有可以調節的 capabilities 塊。它已在 ObjectStack 17.0 中移除,因為沒有
任何東西讀取它:宣告一項能力從未改變過實際執行的路徑,它的 readOnly 標誌
也從未阻止過一次寫入。只讀訪問請參見安全說明。
基於已連線資料的 AI
一旦表被建模為物件,AI 層就能免費在它們之上工作。ObjectOS 的 Agent 和
工具 —— list_objects、describe_object、query_records、
aggregate_data,以及資料對話 Agent —— 都經過 ObjectQL,而 ObjectQL 會把
每個物件路由到它所繫結的資料來源。這意味著:
- 使用者可以用自然語言提問存放在遺留業務系統中的資料,答案基於真實的 資料行計算。
- 工具呼叫和查詢遵守呼叫使用者的許可權 —— AI 看到的永遠不會超過已登入使用者 被允許看到的範圍。
- 無論物件背後是主資料庫還是外部業務系統,同樣的 Agent、流程和儀表盤都能 工作。
關於如何接好對話層和 Agent 層,參見 AI 服務和
AI Agent;關於支撐 default 資料來源的主資料庫配置,
參見執行時。
安全說明
- 絕不內聯憑據。 把密碼放進金鑰儲存,並用
external.credentialsRef引用它,如上所示。 - 對你不打算寫入的系統,使用只讀的資料庫使用者 —— 只授予它
SELECT。 這樣,任何經由該連線到達資料庫的東西都無法寫入,無論是否經過 ObjectOS。 在外部資料來源上,external.allowWrites: false—— 預設值 —— 也會在 ObjectOS 自己的查詢路徑中拒絕寫入。沒有readOnly鍵:曾經存在的那個從未攔住過 一次寫入,ObjectStack 17.0 已將其移除。 - 用許可權限定範圍。 物件級和欄位級許可權對已連線資料的作用,與對原生物件 完全相同。
產品內的外部資料來源聯邦
上面的流程 —— 連線資料庫、建模物件、用編碼 Agent 生成它們 —— 執行在
開箱即用的聯邦之上:schemaMode: 'external',由
ADR-0015
(狀態:Accepted)規定,今天就已交付:把物件繫結到 ObjectOS 不擁有的
表,並在其周圍設定校驗門控。它預設只讀,而且還處於早期:讀取路徑是成熟的
那一條。
它只在擁有這塊能力的框架文件中記錄一次 —— External Datasources (Federation)。
下一步
- 執行時 ——
default背後的主資料庫 - AI 服務 —— 對話、embedding、RAG、MCP
- AI Agent —— 基於你的物件的宣告式 Agent
- 資料模型 ——
ObjectSchema.create編寫介面 examples/app-crm資料來源 —— 一個真實的資料來源 + 路由示例