5/5 tests preserved. Primary entity = person; orgs + interactions + relationship_graph stay custom. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
66 lines
2.5 KiB
Rust
66 lines
2.5 KiB
Rust
//! kei-social-store EntitySchema — Layer A convergence.
|
|
//!
|
|
//! Primary entity = `person` (table `people`). Secondary tables
|
|
//! `organizations` and `interactions` ride `custom_migrations`: they are
|
|
//! not generic CRUD (orgs use name-keyed upsert; interactions are an
|
|
//! append-only log with per-person index) and keep their existing
|
|
//! column names byte-for-byte so on-disk DBs written before this
|
|
//! migration still open cleanly.
|
|
//!
|
|
//! FTS columns cover name, handle, email, bio — search verb routes
|
|
//! through `fts_people`. The legacy `fts_social` virtual table is
|
|
//! replaced; FTS is rebuilt on first open against the new name.
|
|
|
|
use kei_entity_store::schema::{EdgeKeyKind, EntitySchema, FieldDef};
|
|
|
|
static FIELDS: &[FieldDef] = &[
|
|
FieldDef::pk("id"),
|
|
FieldDef::text_nn("name"),
|
|
FieldDef::text("email"),
|
|
FieldDef::text("handle"),
|
|
FieldDef::text("role"),
|
|
FieldDef::text("organization"),
|
|
FieldDef::text_default("source", "manual"),
|
|
FieldDef::text("bio"),
|
|
FieldDef::created_at(),
|
|
FieldDef::updated_at(),
|
|
];
|
|
|
|
const DDL_SECONDARY: &str = r#"
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_people_email
|
|
ON people(email) WHERE email != '';
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_people_handle_source
|
|
ON people(handle, source) WHERE handle != '';
|
|
|
|
CREATE TABLE IF NOT EXISTS organizations (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL UNIQUE,
|
|
org_type TEXT DEFAULT 'company',
|
|
description TEXT DEFAULT '',
|
|
created_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS interactions (
|
|
id INTEGER PRIMARY KEY,
|
|
person_id INTEGER NOT NULL REFERENCES people(id) ON DELETE CASCADE,
|
|
target_id INTEGER NOT NULL DEFAULT 0,
|
|
interaction_type TEXT NOT NULL,
|
|
channel TEXT NOT NULL DEFAULT 'manual',
|
|
content TEXT DEFAULT '',
|
|
timestamp INTEGER NOT NULL,
|
|
created_at INTEGER NOT NULL
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_int_person ON interactions(person_id);
|
|
"#;
|
|
|
|
pub static SOCIAL_SCHEMA: EntitySchema = EntitySchema {
|
|
name: "person",
|
|
table: "people",
|
|
fields: FIELDS,
|
|
enabled_verbs: &["create", "get", "search", "list"],
|
|
fts_columns: Some(&["name", "handle", "email", "bio"]),
|
|
edge_table: None, // interactions has bespoke columns — managed by interactions.rs
|
|
edge_key_kind: EdgeKeyKind::IntegerPair,
|
|
archived_field: None,
|
|
custom_migrations: &[DDL_SECONDARY],
|
|
};
|