mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 13:21:08 +02:00
- Integrate worldream (text-first world-building platform) into games/ - Configure as @worldream/web workspace package - Remove standalone git repo, now part of monorepo 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
96 lines
No EOL
3.1 KiB
PL/PgSQL
96 lines
No EOL
3.1 KiB
PL/PgSQL
-- Enable UUID extension
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
|
|
-- Create enum for content node kinds
|
|
CREATE TYPE node_kind AS ENUM ('world', 'character', 'object', 'place', 'story');
|
|
|
|
-- Create enum for visibility levels
|
|
CREATE TYPE visibility_level AS ENUM ('private', 'shared', 'public');
|
|
|
|
-- Create enum for story entry types
|
|
CREATE TYPE story_entry_type AS ENUM ('narration', 'dialog', 'note');
|
|
|
|
-- Create content_nodes table
|
|
CREATE TABLE content_nodes (
|
|
-- Meta fields
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
kind node_kind NOT NULL,
|
|
slug TEXT NOT NULL UNIQUE,
|
|
title TEXT NOT NULL,
|
|
summary TEXT,
|
|
owner_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
visibility visibility_level DEFAULT 'private',
|
|
tags TEXT[] DEFAULT '{}',
|
|
world_slug TEXT,
|
|
|
|
-- Content as JSONB
|
|
content JSONB DEFAULT '{}',
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
|
|
-- Indexes for foreign key references
|
|
CONSTRAINT fk_world_slug FOREIGN KEY (world_slug) REFERENCES content_nodes(slug) ON DELETE SET NULL
|
|
);
|
|
|
|
-- Create story_entries table
|
|
CREATE TABLE story_entries (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
story_slug TEXT NOT NULL REFERENCES content_nodes(slug) ON DELETE CASCADE,
|
|
position INTEGER NOT NULL,
|
|
type story_entry_type NOT NULL,
|
|
speaker_slug TEXT,
|
|
body TEXT NOT NULL,
|
|
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
|
|
UNIQUE(story_slug, position)
|
|
);
|
|
|
|
-- Create node_revisions table
|
|
CREATE TABLE node_revisions (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
node_id UUID NOT NULL REFERENCES content_nodes(id) ON DELETE CASCADE,
|
|
node_slug TEXT NOT NULL,
|
|
content_before JSONB,
|
|
content_after JSONB,
|
|
edited_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
edited_at TIMESTAMPTZ DEFAULT NOW(),
|
|
notes TEXT
|
|
);
|
|
|
|
-- Create attachments table
|
|
CREATE TABLE attachments (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
node_slug TEXT NOT NULL REFERENCES content_nodes(slug) ON DELETE CASCADE,
|
|
kind TEXT NOT NULL CHECK (kind IN ('image', 'audio', 'doc')),
|
|
url TEXT NOT NULL,
|
|
notes TEXT,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Create indexes
|
|
CREATE INDEX idx_content_nodes_kind ON content_nodes(kind);
|
|
CREATE INDEX idx_content_nodes_owner ON content_nodes(owner_id);
|
|
CREATE INDEX idx_content_nodes_visibility ON content_nodes(visibility);
|
|
CREATE INDEX idx_content_nodes_world ON content_nodes(world_slug);
|
|
CREATE INDEX idx_content_nodes_tags ON content_nodes USING GIN(tags);
|
|
CREATE INDEX idx_story_entries_story ON story_entries(story_slug);
|
|
CREATE INDEX idx_story_entries_speaker ON story_entries(speaker_slug);
|
|
CREATE INDEX idx_attachments_node ON attachments(node_slug);
|
|
|
|
-- Function to update updated_at timestamp
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ language 'plpgsql';
|
|
|
|
-- Trigger to automatically update updated_at
|
|
CREATE TRIGGER update_content_nodes_updated_at
|
|
BEFORE UPDATE ON content_nodes
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column(); |