* feat: add conversations, desktop (Tauri), and offline sync Major new features: - conversations module: Slack-like channels, threads, reactions, pins - Tauri desktop app with local SQLite for offline-first operation - Hybrid logical clock sync engine with conflict resolution - DB provider abstraction (D1/Tauri/memory) with React context Conversations: - Text/voice/announcement channels with categories - Message threads, reactions, attachments, pinning - Real-time presence and typing indicators - Full-text search across messages Desktop (Tauri): - Local SQLite database with sync to cloud D1 - Offline mutation queue with automatic replay - Window management and keyboard shortcuts - Desktop shell with offline banner Sync infrastructure: - Vector clock implementation for causality tracking - Last-write-wins with semantic conflict resolution - Delta sync via checkpoints for bandwidth efficiency - Comprehensive test coverage Also adds e2e test setup with Playwright and CI workflows for desktop releases. * fix(tests): sync engine test schema and checkpoint logic - Add missing process_after column and sync_tombstone table to test schemas - Fix checkpoint update to save cursor even when records array is empty - Revert claude-code-review.yml workflow changes to match main --------- Co-authored-by: Nicholai <nicholaivogelfilms@gmail.com>
83 lines
3.1 KiB
SQL
83 lines
3.1 KiB
SQL
CREATE TABLE `channel_members` (
|
|
`id` text PRIMARY KEY NOT NULL,
|
|
`channel_id` text NOT NULL,
|
|
`user_id` text NOT NULL,
|
|
`role` text DEFAULT 'member' NOT NULL,
|
|
`notify_level` text DEFAULT 'all' NOT NULL,
|
|
`joined_at` text NOT NULL,
|
|
FOREIGN KEY (`channel_id`) REFERENCES `channels`(`id`) ON UPDATE no action ON DELETE cascade,
|
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `channel_read_state` (
|
|
`id` text PRIMARY KEY NOT NULL,
|
|
`user_id` text NOT NULL,
|
|
`channel_id` text NOT NULL,
|
|
`last_read_message_id` text,
|
|
`last_read_at` text NOT NULL,
|
|
`unread_count` integer DEFAULT 0 NOT NULL,
|
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade,
|
|
FOREIGN KEY (`channel_id`) REFERENCES `channels`(`id`) ON UPDATE no action ON DELETE cascade
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `channels` (
|
|
`id` text PRIMARY KEY NOT NULL,
|
|
`name` text NOT NULL,
|
|
`type` text DEFAULT 'text' NOT NULL,
|
|
`description` text,
|
|
`organization_id` text NOT NULL,
|
|
`project_id` text,
|
|
`is_private` integer DEFAULT false NOT NULL,
|
|
`created_by` text NOT NULL,
|
|
`sort_order` integer DEFAULT 0 NOT NULL,
|
|
`archived_at` text,
|
|
`created_at` text NOT NULL,
|
|
`updated_at` text NOT NULL,
|
|
FOREIGN KEY (`organization_id`) REFERENCES `organizations`(`id`) ON UPDATE no action ON DELETE cascade,
|
|
FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`) ON UPDATE no action ON DELETE cascade,
|
|
FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `message_attachments` (
|
|
`id` text PRIMARY KEY NOT NULL,
|
|
`message_id` text NOT NULL,
|
|
`file_name` text NOT NULL,
|
|
`mime_type` text NOT NULL,
|
|
`file_size` integer NOT NULL,
|
|
`r2_path` text NOT NULL,
|
|
`width` integer,
|
|
`height` integer,
|
|
`uploaded_at` text NOT NULL,
|
|
FOREIGN KEY (`message_id`) REFERENCES `messages`(`id`) ON UPDATE no action ON DELETE cascade
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `message_reactions` (
|
|
`id` text PRIMARY KEY NOT NULL,
|
|
`message_id` text NOT NULL,
|
|
`user_id` text NOT NULL,
|
|
`emoji` text NOT NULL,
|
|
`created_at` text NOT NULL,
|
|
FOREIGN KEY (`message_id`) REFERENCES `messages`(`id`) ON UPDATE no action ON DELETE cascade,
|
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE `messages` (
|
|
`id` text PRIMARY KEY NOT NULL,
|
|
`channel_id` text NOT NULL,
|
|
`thread_id` text,
|
|
`user_id` text NOT NULL,
|
|
`content` text NOT NULL,
|
|
`content_html` text,
|
|
`edited_at` text,
|
|
`deleted_at` text,
|
|
`deleted_by` text,
|
|
`is_pinned` integer DEFAULT false NOT NULL,
|
|
`reply_count` integer DEFAULT 0 NOT NULL,
|
|
`last_reply_at` text,
|
|
`created_at` text NOT NULL,
|
|
FOREIGN KEY (`channel_id`) REFERENCES `channels`(`id`) ON UPDATE no action ON DELETE cascade,
|
|
FOREIGN KEY (`thread_id`) REFERENCES `messages`(`id`) ON UPDATE no action ON DELETE no action,
|
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action,
|
|
FOREIGN KEY (`deleted_by`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
|
|
);
|