/** * Database schema definitions and migration scripts */ export const SCHEMA_VERSION = 8; export const CREATE_TABLES = ` -- Projects table CREATE TABLE IF NOT EXISTS projects ( id TEXT PRIMARY KEY NOT NULL, user_id TEXT NOT NULL, title TEXT NOT NULL, status TEXT NOT NULL CHECK(status IN ('in_progress', 'done', 'archived')), tags TEXT NOT NULL, -- JSON array cover_image_uri TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); -- Steps table CREATE TABLE IF NOT EXISTS steps ( id TEXT PRIMARY KEY NOT NULL, project_id TEXT NOT NULL, type TEXT NOT NULL CHECK(type IN ('forming', 'trimming', 'drying', 'bisque_firing', 'glazing', 'glaze_firing', 'misc')), notes_markdown TEXT, photo_uris TEXT NOT NULL, -- JSON array created_at TEXT NOT NULL, updated_at TEXT NOT NULL, FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE ); -- Firing fields (for bisque_firing and glaze_firing steps) CREATE TABLE IF NOT EXISTS firing_fields ( step_id TEXT PRIMARY KEY NOT NULL, cone TEXT, temperature_value INTEGER, temperature_unit TEXT CHECK(temperature_unit IN ('F', 'C')), duration_minutes INTEGER, kiln_notes TEXT, FOREIGN KEY (step_id) REFERENCES steps(id) ON DELETE CASCADE ); -- Glazing fields (for glazing steps) CREATE TABLE IF NOT EXISTS glazing_fields ( step_id TEXT PRIMARY KEY NOT NULL, glaze_ids TEXT NOT NULL, -- JSON array coats INTEGER, application TEXT CHECK(application IN ('brush', 'dip', 'spray', 'pour', 'other')), mix_notes TEXT, -- notes about glaze mixing ratios (e.g., "50/50", "3:1") FOREIGN KEY (step_id) REFERENCES steps(id) ON DELETE CASCADE ); -- Glazes catalog CREATE TABLE IF NOT EXISTS glazes ( id TEXT PRIMARY KEY NOT NULL, user_id TEXT, -- NULL for seed glazes, set for custom glazes brand TEXT NOT NULL, name TEXT NOT NULL, code TEXT, color TEXT, -- hex color code for preview finish TEXT CHECK(finish IN ('glossy', 'satin', 'matte', 'special', 'unknown')), notes TEXT, is_custom INTEGER NOT NULL DEFAULT 0, -- 0 = seed, 1 = user custom is_mix INTEGER NOT NULL DEFAULT 0, -- 0 = regular glaze, 1 = mixed glaze mixed_glaze_ids TEXT, -- JSON array of glaze IDs that were mixed mix_ratio TEXT, -- user's notes about the mix ratio (e.g., "50/50", "3:1") created_at TEXT NOT NULL ); -- Settings (per user) CREATE TABLE IF NOT EXISTS settings ( user_id TEXT PRIMARY KEY NOT NULL, unit_system TEXT NOT NULL CHECK(unit_system IN ('imperial', 'metric')), temp_unit TEXT NOT NULL CHECK(temp_unit IN ('F', 'C')), weight_unit TEXT NOT NULL DEFAULT 'lb' CHECK(weight_unit IN ('lb', 'oz', 'kg', 'g')), analytics_opt_in INTEGER NOT NULL DEFAULT 0 ); -- User lists (shopping and wish lists) CREATE TABLE IF NOT EXISTS user_lists ( id TEXT PRIMARY KEY NOT NULL, user_id TEXT NOT NULL, type TEXT NOT NULL CHECK(type IN ('shopping', 'wish')), item TEXT NOT NULL, notes TEXT, is_completed INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL, FOREIGN KEY (user_id) REFERENCES settings(user_id) ); -- Forming step fields (production phase) CREATE TABLE IF NOT EXISTS forming_fields ( step_id TEXT PRIMARY KEY NOT NULL, clay_body TEXT, clay_weight_value REAL, clay_weight_unit TEXT CHECK(clay_weight_unit IN ('lb', 'oz', 'kg', 'g')), production_method TEXT CHECK(production_method IN ('wheel', 'handbuilding', 'casting', 'other')), dimensions TEXT, FOREIGN KEY (step_id) REFERENCES steps(id) ON DELETE CASCADE ); -- News/Tips cache (per user) CREATE TABLE IF NOT EXISTS news_items ( id TEXT PRIMARY KEY NOT NULL, user_id TEXT NOT NULL, title TEXT NOT NULL, excerpt TEXT, url TEXT, content_html TEXT, published_at TEXT NOT NULL, cached_at TEXT NOT NULL ); -- Create indexes for better query performance CREATE INDEX IF NOT EXISTS idx_steps_project_id ON steps(project_id); CREATE INDEX IF NOT EXISTS idx_steps_type ON steps(type); CREATE INDEX IF NOT EXISTS idx_projects_user_id ON projects(user_id); CREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status); CREATE INDEX IF NOT EXISTS idx_projects_updated_at ON projects(updated_at DESC); CREATE INDEX IF NOT EXISTS idx_glazes_user_id ON glazes(user_id); CREATE INDEX IF NOT EXISTS idx_glazes_brand ON glazes(brand); CREATE INDEX IF NOT EXISTS idx_glazes_is_custom ON glazes(is_custom); CREATE INDEX IF NOT EXISTS idx_news_user_id ON news_items(user_id); CREATE INDEX IF NOT EXISTS idx_news_published_at ON news_items(published_at DESC); CREATE INDEX IF NOT EXISTS idx_user_lists_user_id ON user_lists(user_id); CREATE INDEX IF NOT EXISTS idx_user_lists_type ON user_lists(type); `; export const DROP_ALL_TABLES = ` DROP TABLE IF EXISTS firing_fields; DROP TABLE IF EXISTS glazing_fields; DROP TABLE IF EXISTS forming_fields; DROP TABLE IF EXISTS steps; DROP TABLE IF EXISTS projects; DROP TABLE IF EXISTS glazes; DROP TABLE IF EXISTS settings; DROP TABLE IF EXISTS news_items; DROP TABLE IF EXISTS user_lists; `;