feat(schema): 005 — tags, entity_tags, entity_links, attachments

This commit is contained in:
root
2026-05-31 11:02:14 +10:00
parent 1d799105ac
commit 1b51c3c18d
2 changed files with 59 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
CREATE TABLE tags (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name text NOT NULL UNIQUE,
description text,
color text,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE entity_tags (
entity_type text NOT NULL,
entity_id uuid NOT NULL,
tag_id uuid NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
created_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (entity_type, entity_id, tag_id)
);
CREATE TABLE entity_links (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
from_type text NOT NULL,
from_id uuid NOT NULL,
to_type text NOT NULL,
to_id uuid NOT NULL,
relation text NOT NULL DEFAULT 'attached',
created_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (from_type, from_id, to_type, to_id, relation)
);
CREATE TABLE attachments (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
entity_type text,
entity_id uuid,
filename text NOT NULL,
mime_type text,
size_bytes bigint,
blob_path text NOT NULL,
checksum text,
uploaded_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX idx_entity_tags_entity ON entity_tags(entity_type, entity_id);
CREATE INDEX idx_entity_links_from ON entity_links(from_type, from_id);
CREATE INDEX idx_entity_links_to ON entity_links(to_type, to_id);
CREATE INDEX idx_attachments_entity ON attachments(entity_type, entity_id);

View File

@@ -0,0 +1,16 @@
import { describe, it, expect, beforeAll } from 'vitest';
import { resetDb, withClient } from '../helpers/db.js';
import { migrateUp } from '../../lib/db/migrate.js';
describe('migration 005 — cross', () => {
beforeAll(async () => { await resetDb(); await migrateUp(); });
it('creates tags, entity_tags, entity_links, attachments', async () => {
await withClient(async (c) => {
for (const t of ['tags','entity_tags','entity_links','attachments']) {
const { rows } = await c.query(`SELECT to_regclass('public.' || $1) AS t;`, [t]);
expect(rows[0].t).toBe(t);
}
});
});
});