小橘 d84a860d15 feat: initial ograph repo — engine (85 tests) + cli (31 tests)
Extracted from uncaged monorepo (oc-xiaoju/uncaged).
Resolves oc-xiaoju/uncaged#224.

- @uncaged/ograph: CF Worker engine (events, projections, reactions)
- @uncaged/ograph-cli: CLI for managing OGraph instances
- Removed @uncaged/oid dependency (unused)
- 116 tests, all passing
- CI: GitHub Actions

小橘 🍊(NEKO Team)
2026-04-12 23:43:56 +00:00

114 lines
3.9 KiB
SQL

-- OGraph v2.4 Schema
-- object_defs 回归单表(去掉 object_def_versions + object_def_names)
-- version 表加 parent_hash(版本链)和 name(反查)
-- projection_def 加 value_schema NOT NULL + initial_value NOT NULL
-- projections.value NOT NULL
-- objects.type 直接存名字(不存 hash)
-- Drop all v2.3 tables
DROP TABLE IF EXISTS reactions;
DROP TABLE IF EXISTS projections;
DROP TABLE IF EXISTS event_refs;
DROP TABLE IF EXISTS events;
DROP TABLE IF EXISTS objects;
DROP TABLE IF EXISTS projection_def_names;
DROP TABLE IF EXISTS projection_def_versions;
DROP TABLE IF EXISTS event_def_names;
DROP TABLE IF EXISTS event_def_versions;
DROP TABLE IF EXISTS object_def_names;
DROP TABLE IF EXISTS object_def_versions;
-- ============================================
-- Object 定义(无版本,纯名字)
-- ============================================
CREATE TABLE object_defs (
name TEXT PRIMARY KEY
);
-- ============================================
-- Event 定义(版本链 + 名字指针)
-- ============================================
CREATE TABLE event_def_versions (
hash TEXT PRIMARY KEY,
name TEXT NOT NULL, -- 属于哪个定义(反查)
parent_hash TEXT REFERENCES event_def_versions(hash), -- 前一版本,首版 NULL
schema TEXT NOT NULL, -- JSON: { properties: { ... } }
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
);
CREATE TABLE event_def_names (
name TEXT PRIMARY KEY,
current_hash TEXT NOT NULL REFERENCES event_def_versions(hash),
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
);
-- ============================================
-- Projection 定义(版本链 + 名字指针 + value schema)
-- ============================================
CREATE TABLE projection_def_versions (
hash TEXT PRIMARY KEY,
name TEXT NOT NULL,
parent_hash TEXT REFERENCES projection_def_versions(hash),
driven_by TEXT NOT NULL, -- JSON: [event_def_hash, ...]
params TEXT NOT NULL, -- JSON: input schema
filter TEXT NOT NULL, -- JSONata
expression TEXT NOT NULL, -- JSONata
value_schema TEXT NOT NULL, -- JSON: { type: "number" } 等
initial_value TEXT NOT NULL, -- JSON: 必须符合 value_schema
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
);
CREATE TABLE projection_def_names (
name TEXT PRIMARY KEY,
current_hash TEXT NOT NULL REFERENCES projection_def_versions(hash),
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
);
-- ============================================
-- 实例表
-- ============================================
CREATE TABLE objects (
id TEXT PRIMARY KEY,
type TEXT NOT NULL REFERENCES object_defs(name),
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
);
CREATE TABLE events (
id TEXT PRIMARY KEY,
type_hash TEXT NOT NULL REFERENCES event_def_versions(hash),
payload TEXT NOT NULL,
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
);
CREATE TABLE event_refs (
event_id TEXT NOT NULL REFERENCES events(id),
property TEXT NOT NULL,
ref_id TEXT NOT NULL REFERENCES objects(id),
PRIMARY KEY (event_id, property)
);
CREATE INDEX idx_event_refs_obj ON event_refs(ref_id);
CREATE TABLE projections (
def_hash TEXT NOT NULL REFERENCES projection_def_versions(hash),
params_hash TEXT NOT NULL,
params TEXT NOT NULL,
value TEXT NOT NULL, -- NOT NULL,至少是 initial_value
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
updated_at INTEGER,
PRIMARY KEY (def_hash, params_hash)
);
CREATE TABLE reactions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
projection_def_hash TEXT NOT NULL REFERENCES projection_def_versions(hash),
params_hash TEXT NOT NULL,
params TEXT NOT NULL,
webhook_url TEXT NOT NULL,
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
);
CREATE INDEX idx_reactions_projection ON reactions(projection_def_hash, params_hash);