@storyshelf/db-mysql 0.8.0 → 0.9.0-next-d2cc082

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ddl.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  /** Canonical MySQL DDL for all StoryShelf tables and indexes. */
4
- declare const DDL = "\nCREATE TABLE IF NOT EXISTS projects (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT NOT NULL,\n slug VARCHAR(255) NOT NULL UNIQUE,\n git_repository TEXT,\n git_default_branch VARCHAR(255) NOT NULL DEFAULT 'main',\n pixel_threshold DOUBLE NOT NULL DEFAULT 0.1,\n max_diff_ratio DOUBLE NOT NULL DEFAULT 0.01,\n public_branch_regex TEXT,\n storybook_meta TEXT,\n execute_play TINYINT(1) NOT NULL DEFAULT false,\n play_timeout_ms INTEGER NOT NULL DEFAULT 10000,\n run_a11y TINYINT(1) NOT NULL DEFAULT true,\n run_tests TINYINT(1) NOT NULL DEFAULT false,\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n viewports TEXT,\n browsers TEXT,\n modes_allowlist TEXT,\n automigrate TINYINT(1) NOT NULL DEFAULT false,\n ai_profile TEXT,\n review_enabled TINYINT(1) NOT NULL DEFAULT true,\n review_approvals INT NOT NULL DEFAULT 1,\n storybook_url_ttl_seconds INT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS builds (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n git_sha VARCHAR(64) NOT NULL,\n git_branch VARCHAR(255) NOT NULL,\n is_default TINYINT(1) NOT NULL DEFAULT false,\n author_email TEXT,\n author_name TEXT,\n message TEXT,\n public TINYINT(1) NOT NULL DEFAULT false,\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n snapshot_count INTEGER NOT NULL DEFAULT 0,\n changed_count INTEGER NOT NULL DEFAULT 0,\n approved_count INTEGER NOT NULL DEFAULT 0,\n rejected_count INTEGER NOT NULL DEFAULT 0,\n inherited_count INTEGER NOT NULL DEFAULT 0,\n affected_only TINYINT(1) NOT NULL DEFAULT true,\n baseline_sha TEXT,\n changed_files TEXT,\n affected_import_paths TEXT,\n test_results TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_builds_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX builds_project_gitsha_idx ON builds (project_id, git_sha);\nCREATE INDEX builds_git_branch_idx ON builds (git_branch);\nCREATE TABLE IF NOT EXISTS capture_attempts (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n attempt_no INTEGER NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'queued',\n error TEXT,\n req_id TEXT,\n story_count INTEGER NOT NULL DEFAULT 0,\n failed_count INTEGER NOT NULL DEFAULT 0,\n queued_at DATETIME(3) NOT NULL,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_attempts_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_attempts_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX capture_attempts_build_no_idx ON capture_attempts (build_id, attempt_no);\nCREATE INDEX capture_attempts_build_id_idx ON capture_attempts (build_id);\nCREATE TABLE IF NOT EXISTS capture_shards (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n kind VARCHAR(32) NOT NULL,\n ordinal INTEGER NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n attempt_id VARCHAR(64),\n payload TEXT,\n result TEXT,\n error TEXT,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_shards_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_shards_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX capture_shards_build_kind_ordinal_idx ON capture_shards (build_id, kind, ordinal);\nCREATE INDEX capture_shards_build_id_idx ON capture_shards (build_id);\nCREATE TABLE IF NOT EXISTS capture_jobs (\n id VARCHAR(64) PRIMARY KEY,\n entry VARCHAR(64) NOT NULL,\n job_id VARCHAR(64) NOT NULL,\n kind VARCHAR(32) NOT NULL,\n build_id VARCHAR(64),\n shard_id VARCHAR(64),\n attempt INTEGER NOT NULL DEFAULT 0,\n max_attempts INTEGER NOT NULL DEFAULT 3,\n status VARCHAR(32) NOT NULL,\n visible_at DATETIME(3),\n owner TEXT,\n payload TEXT,\n cancel_requested_at DATETIME(3),\n error TEXT,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE INDEX capture_jobs_poll_idx ON capture_jobs (kind, visible_at, status);\nCREATE INDEX capture_jobs_job_id_idx ON capture_jobs (job_id);\nCREATE INDEX capture_jobs_build_id_idx ON capture_jobs (build_id);\nCREATE INDEX capture_jobs_entry_created_idx ON capture_jobs (entry, created_at);\nCREATE TABLE IF NOT EXISTS site_settings (\n id VARCHAR(64) PRIMARY KEY,\n value TEXT NOT NULL,\n updated_by TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS build_components (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n import_path VARCHAR(512) NOT NULL,\n title TEXT NOT NULL,\n story_count INTEGER NOT NULL DEFAULT 0,\n hash TEXT NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_components_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_components_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX build_components_build_id_idx ON build_components (build_id);\nCREATE INDEX build_components_project_import_path_idx ON build_components (project_id, import_path);\nCREATE TABLE IF NOT EXISTS capture_logs (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n attempt_id VARCHAR(64) NOT NULL,\n seq INTEGER NOT NULL,\n level VARCHAR(16) NOT NULL DEFAULT 'info',\n message TEXT NOT NULL,\n fields TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_logs_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_logs_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_logs_attempt_id FOREIGN KEY (attempt_id) REFERENCES capture_attempts(id) ON DELETE CASCADE\n);\nCREATE INDEX capture_logs_attempt_seq_idx ON capture_logs (attempt_id, seq);\nCREATE TABLE IF NOT EXISTS snapshots (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n story_id VARCHAR(255) NOT NULL,\n story_name TEXT NOT NULL,\n story_title TEXT NOT NULL,\n story_import_path VARCHAR(512),\n design_url TEXT,\n viewport_name VARCHAR(64) NOT NULL DEFAULT 'desktop',\n viewport_width INTEGER NOT NULL DEFAULT 1280,\n viewport_height INTEGER NOT NULL DEFAULT 720,\n screenshot_path TEXT NOT NULL,\n diff_path TEXT,\n diff_pixels INTEGER,\n diff_ratio DOUBLE,\n diff_passed TINYINT(1),\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n reviewed_by TEXT,\n reviewed_at DATETIME(3),\n infra_hash TEXT,\n env_change TEXT,\n inherited TINYINT(1) NOT NULL DEFAULT false,\n baseline_id VARCHAR(64),\n baseline_version TEXT,\n source_build_id TEXT,\n comparison_image_path TEXT,\n comparison_metadata TEXT,\n mode VARCHAR(64),\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n duration_ms INT,\n a11y_violations TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_snapshots_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_snapshots_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX snapshots_build_id_idx ON snapshots (build_id);\nCREATE INDEX snapshots_project_import_path_idx ON snapshots (project_id, story_import_path);\nCREATE TABLE IF NOT EXISTS baselines (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n story_id VARCHAR(255) NOT NULL,\n viewport_name VARCHAR(64) NOT NULL DEFAULT 'desktop',\n branch VARCHAR(255) NOT NULL,\n snapshot_id VARCHAR(64),\n source_build_id TEXT,\n screenshot_path TEXT NOT NULL,\n infra_hash TEXT,\n fingerprint TEXT,\n mode VARCHAR(64),\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_baselines_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX baselines_project_story_idx ON baselines (project_id, story_id);\nCREATE TABLE IF NOT EXISTS users (\n id VARCHAR(64) PRIMARY KEY,\n email VARCHAR(255) NOT NULL UNIQUE,\n name TEXT NOT NULL,\n avatar_url TEXT,\n role VARCHAR(32) NOT NULL DEFAULT 'member',\n last_login_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n password_hash TEXT,\n display_name_override TEXT,\n auth_provider VARCHAR(32) NOT NULL DEFAULT 'oidc',\n disabled TINYINT(1) NOT NULL DEFAULT 0\n);\nCREATE TABLE IF NOT EXISTS user_connections (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n service VARCHAR(64) NOT NULL,\n token_encrypted TEXT NOT NULL,\n refresh_token_encrypted TEXT,\n expires_at DATETIME(3),\n status VARCHAR(32) NOT NULL DEFAULT 'ok',\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_user_connections_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX user_connections_user_service_idx ON user_connections (user_id, service);\nCREATE TABLE IF NOT EXISTS comments (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n snapshot_id VARCHAR(64),\n user_id VARCHAR(64),\n body TEXT NOT NULL,\n parent_id TEXT,\n resolved TINYINT(1) NOT NULL DEFAULT false,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n story_id TEXT,\n CONSTRAINT fk_comments_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_snapshot_id FOREIGN KEY (snapshot_id) REFERENCES snapshots(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE INDEX comments_build_id_idx ON comments (build_id);\nCREATE TABLE IF NOT EXISTS build_reviews (\n id VARCHAR(64) PRIMARY KEY,\n build_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64),\n verdict TEXT NOT NULL,\n body TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_reviews_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_reviews_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE INDEX build_reviews_build_id_idx ON build_reviews (build_id);\nCREATE TABLE IF NOT EXISTS label_types (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n `key` VARCHAR(255) NOT NULL,\n name TEXT NOT NULL,\n link_template TEXT,\n color TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_label_types_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX label_types_project_key_idx ON label_types (project_id, `key`);\nCREATE TABLE IF NOT EXISTS build_labels (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n type_key VARCHAR(64) NOT NULL,\n value VARCHAR(255) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_labels_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_labels_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX build_labels_build_type_value_idx ON build_labels (build_id, type_key, value);\nCREATE TABLE IF NOT EXISTS project_links (\n id VARCHAR(64) PRIMARY KEY,\n downstream_id VARCHAR(64) NOT NULL,\n upstream_id VARCHAR(64) NOT NULL,\n package_name VARCHAR(255) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_links_downstream_id FOREIGN KEY (downstream_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_project_links_upstream_id FOREIGN KEY (upstream_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_links_downstream_package_idx ON project_links (downstream_id, package_name);\nCREATE TABLE IF NOT EXISTS design_links (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n import_path VARCHAR(512),\n label TEXT,\n url TEXT NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_links_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX design_links_project_id_idx ON design_links (project_id);\nCREATE TABLE IF NOT EXISTS design_credentials (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n provider VARCHAR(64) NOT NULL,\n token_encrypted TEXT NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'unknown',\n checked_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_credentials_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX design_credentials_project_provider_idx ON design_credentials (project_id, provider);\nCREATE TABLE IF NOT EXISTS design_nodes (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n provider VARCHAR(64) NOT NULL,\n viewer_id VARCHAR(128) NOT NULL DEFAULT '',\n file_key VARCHAR(128) NOT NULL,\n node_id VARCHAR(128) NOT NULL DEFAULT '',\n name TEXT,\n version TEXT,\n last_modified TEXT,\n state VARCHAR(32) NOT NULL DEFAULT 'ok',\n render_path TEXT,\n render_version TEXT,\n fetched_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_nodes_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX design_nodes_project_file_node_idx ON design_nodes (project_id, provider, viewer_id, file_key, node_id);\nCREATE TABLE IF NOT EXISTS build_package_usage (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n story_import_path TEXT NOT NULL,\n package_name TEXT NOT NULL,\n module_path TEXT NOT NULL,\n version TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_package_usage_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_package_usage_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX build_package_usage_build_id_idx ON build_package_usage (build_id);\nCREATE TABLE IF NOT EXISTS tokens (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n name TEXT NOT NULL,\n hash VARCHAR(128) NOT NULL UNIQUE,\n user_id VARCHAR(64),\n last_used_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_tokens_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS webhooks (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n url TEXT NOT NULL,\n secret_encrypted TEXT NOT NULL,\n events TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_webhooks_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS notification_channels (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64),\n provider TEXT NOT NULL,\n config TEXT NOT NULL,\n secret_encrypted TEXT,\n events TEXT,\n enabled BOOLEAN NOT NULL DEFAULT TRUE,\n last_error TEXT,\n last_error_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_notification_channels_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX notification_channels_project_id_idx ON notification_channels (project_id);\nCREATE TABLE IF NOT EXISTS notification_subscriptions (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n events TEXT,\n via TEXT,\n enabled BOOLEAN NOT NULL DEFAULT TRUE,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_notification_subscriptions_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_notification_subscriptions_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX notification_subscriptions_project_user_idx ON notification_subscriptions (project_id, user_id);\nCREATE TABLE IF NOT EXISTS insights (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64),\n kind VARCHAR(32) NOT NULL,\n window_key VARCHAR(64),\n input_hash VARCHAR(64) NOT NULL,\n status VARCHAR(32) NOT NULL,\n profile TEXT NOT NULL,\n model TEXT NOT NULL,\n prompt_version TEXT NOT NULL,\n verdict TEXT,\n summary TEXT,\n result TEXT,\n error_code TEXT,\n created_at DATETIME(3) NOT NULL,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n CONSTRAINT fk_insights_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_insights_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX insights_project_build_idx ON insights (project_id, build_id);\nCREATE INDEX insights_created_at_idx ON insights (created_at);\nCREATE UNIQUE INDEX insights_triage_unique_idx ON insights (project_id, build_id, kind, input_hash);\nCREATE UNIQUE INDEX insights_health_unique_idx ON insights (project_id, kind, window_key);\nCREATE TABLE IF NOT EXISTS ai_usage (\n id VARCHAR(64) PRIMARY KEY,\n insight_id TEXT,\n project_id VARCHAR(64) NOT NULL,\n profile TEXT NOT NULL,\n task TEXT NOT NULL,\n model TEXT NOT NULL,\n input_tokens INTEGER NOT NULL DEFAULT 0,\n output_tokens INTEGER NOT NULL DEFAULT 0,\n estimated TINYINT(1) NOT NULL DEFAULT false,\n images INTEGER NOT NULL DEFAULT 0,\n status VARCHAR(32) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_ai_usage_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX ai_usage_created_at_idx ON ai_usage (created_at);\nCREATE INDEX ai_usage_project_created_idx ON ai_usage (project_id, created_at);\nCREATE TABLE IF NOT EXISTS ai_budget_alerts (\n id VARCHAR(64) PRIMARY KEY,\n day TEXT NOT NULL,\n threshold INTEGER NOT NULL,\n created_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS user_invite_tokens (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n token_hash VARCHAR(128) NOT NULL UNIQUE,\n expires_at DATETIME(3) NOT NULL,\n used_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_user_invite_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS project_members (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n role VARCHAR(32) NOT NULL DEFAULT 'viewer',\n source VARCHAR(32) NOT NULL DEFAULT 'manual',\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_members_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_project_members_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_members_project_user_idx ON project_members (project_id, user_id);\nCREATE TABLE IF NOT EXISTS project_group_mappings (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n group_name VARCHAR(255) NOT NULL,\n role VARCHAR(32) NOT NULL DEFAULT 'viewer',\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_group_mappings_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_group_mappings_project_group_idx ON project_group_mappings (project_id, group_name);\nCREATE TABLE IF NOT EXISTS content_refs (\n hash VARCHAR(128) PRIMARY KEY,\n ref_count INTEGER NOT NULL DEFAULT 1,\n last_seen_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS `user` (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT NOT NULL,\n email VARCHAR(255) NOT NULL UNIQUE,\n email_verified TINYINT(1) NOT NULL DEFAULT false,\n image TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS session (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n token VARCHAR(512) NOT NULL UNIQUE,\n expires_at DATETIME(3) NOT NULL,\n ip_address TEXT,\n user_agent TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_session_user_id FOREIGN KEY (user_id) REFERENCES `user`(id) ON DELETE CASCADE\n);\nCREATE INDEX session_token_idx ON session (token);\nCREATE INDEX session_user_id_idx ON session (user_id);\nCREATE TABLE IF NOT EXISTS account (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n account_id TEXT NOT NULL,\n provider_id TEXT NOT NULL,\n access_token TEXT,\n refresh_token TEXT,\n id_token TEXT,\n access_token_expires_at DATETIME(3),\n refresh_token_expires_at DATETIME(3),\n scope TEXT,\n expires_at DATETIME(3),\n password TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_account_user_id FOREIGN KEY (user_id) REFERENCES `user`(id) ON DELETE CASCADE\n);\nCREATE INDEX account_user_id_idx ON account (user_id);\nCREATE TABLE IF NOT EXISTS verification (\n id VARCHAR(64) PRIMARY KEY,\n identifier VARCHAR(255) NOT NULL,\n value TEXT NOT NULL,\n expires_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE INDEX verification_identifier_idx ON verification (identifier);\nCREATE TABLE IF NOT EXISTS passkey (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT,\n public_key TEXT NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n credential_id VARCHAR(255) NOT NULL,\n counter INTEGER NOT NULL,\n device_type TEXT NOT NULL,\n backed_up TINYINT(1) NOT NULL DEFAULT false,\n transports TEXT,\n aaguid TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3),\n CONSTRAINT fk_passkey_user_id FOREIGN KEY (user_id) REFERENCES `user`(id) ON DELETE CASCADE\n);\nCREATE INDEX passkey_user_id_idx ON passkey (user_id);\nCREATE INDEX passkey_credential_id_idx ON passkey (credential_id);\nCREATE TABLE IF NOT EXISTS `ssoProvider` (\n id VARCHAR(64) PRIMARY KEY,\n issuer TEXT NOT NULL,\n oidc_config TEXT,\n saml_config TEXT,\n user_id VARCHAR(64) NOT NULL,\n provider_id VARCHAR(64) NOT NULL UNIQUE,\n organization_id TEXT,\n domain VARCHAR(255) NOT NULL,\n CONSTRAINT fk_ssoProvider_user_id FOREIGN KEY (user_id) REFERENCES `user`(id) ON DELETE CASCADE\n);\nCREATE INDEX ssoprovider_domain_idx ON `ssoProvider` (domain);\n";
4
+ declare const DDL = "\nCREATE TABLE IF NOT EXISTS projects (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT NOT NULL,\n slug VARCHAR(255) NOT NULL UNIQUE,\n git_repository TEXT,\n git_default_branch VARCHAR(255) NOT NULL DEFAULT 'main',\n pixel_threshold DOUBLE NOT NULL DEFAULT 0.1,\n max_diff_ratio DOUBLE NOT NULL DEFAULT 0.01,\n public_branch_regex TEXT,\n storybook_meta TEXT,\n execute_play TINYINT(1) NOT NULL DEFAULT false,\n play_timeout_ms INTEGER NOT NULL DEFAULT 10000,\n run_a11y TINYINT(1) NOT NULL DEFAULT true,\n run_tests TINYINT(1) NOT NULL DEFAULT false,\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n viewports TEXT,\n browsers TEXT,\n modes_allowlist TEXT,\n automigrate TINYINT(1) NOT NULL DEFAULT false,\n ai_profile TEXT,\n review_enabled TINYINT(1) NOT NULL DEFAULT true,\n review_approvals INT NOT NULL DEFAULT 1,\n storybook_url_ttl_seconds INT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS builds (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n git_sha VARCHAR(64) NOT NULL,\n git_branch VARCHAR(255) NOT NULL,\n is_default TINYINT(1) NOT NULL DEFAULT false,\n author_email TEXT,\n author_name TEXT,\n message TEXT,\n public TINYINT(1) NOT NULL DEFAULT false,\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n snapshot_count INTEGER NOT NULL DEFAULT 0,\n changed_count INTEGER NOT NULL DEFAULT 0,\n approved_count INTEGER NOT NULL DEFAULT 0,\n rejected_count INTEGER NOT NULL DEFAULT 0,\n inherited_count INTEGER NOT NULL DEFAULT 0,\n affected_only TINYINT(1) NOT NULL DEFAULT true,\n baseline_sha TEXT,\n changed_files TEXT,\n affected_import_paths TEXT,\n test_results TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_builds_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX builds_project_gitsha_idx ON builds (project_id, git_sha);\nCREATE INDEX builds_git_branch_idx ON builds (git_branch);\nCREATE TABLE IF NOT EXISTS capture_attempts (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n attempt_no INTEGER NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'queued',\n error TEXT,\n req_id TEXT,\n story_count INTEGER NOT NULL DEFAULT 0,\n failed_count INTEGER NOT NULL DEFAULT 0,\n queued_at DATETIME(3) NOT NULL,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_attempts_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_attempts_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX capture_attempts_build_no_idx ON capture_attempts (build_id, attempt_no);\nCREATE INDEX capture_attempts_build_id_idx ON capture_attempts (build_id);\nCREATE TABLE IF NOT EXISTS capture_shards (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n kind VARCHAR(32) NOT NULL,\n ordinal INTEGER NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n attempt_id VARCHAR(64),\n payload TEXT,\n result TEXT,\n error TEXT,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_shards_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_shards_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX capture_shards_build_kind_ordinal_idx ON capture_shards (build_id, kind, ordinal);\nCREATE INDEX capture_shards_build_id_idx ON capture_shards (build_id);\nCREATE TABLE IF NOT EXISTS capture_jobs (\n id VARCHAR(64) PRIMARY KEY,\n entry VARCHAR(64) NOT NULL,\n job_id VARCHAR(64) NOT NULL,\n kind VARCHAR(32) NOT NULL,\n build_id VARCHAR(64),\n shard_id VARCHAR(64),\n attempt INTEGER NOT NULL DEFAULT 0,\n max_attempts INTEGER NOT NULL DEFAULT 3,\n status VARCHAR(32) NOT NULL,\n visible_at DATETIME(3),\n owner TEXT,\n payload TEXT,\n cancel_requested_at DATETIME(3),\n error TEXT,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE INDEX capture_jobs_poll_idx ON capture_jobs (kind, visible_at, status);\nCREATE INDEX capture_jobs_job_id_idx ON capture_jobs (job_id);\nCREATE INDEX capture_jobs_build_id_idx ON capture_jobs (build_id);\nCREATE INDEX capture_jobs_entry_created_idx ON capture_jobs (entry, created_at);\nCREATE TABLE IF NOT EXISTS site_settings (\n id VARCHAR(64) PRIMARY KEY,\n value TEXT NOT NULL,\n updated_by TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS build_components (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n import_path VARCHAR(512) NOT NULL,\n title TEXT NOT NULL,\n story_count INTEGER NOT NULL DEFAULT 0,\n hash TEXT NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_components_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_components_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX build_components_build_id_idx ON build_components (build_id);\nCREATE INDEX build_components_project_import_path_idx ON build_components (project_id, import_path);\nCREATE TABLE IF NOT EXISTS capture_logs (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n attempt_id VARCHAR(64) NOT NULL,\n seq INTEGER NOT NULL,\n level VARCHAR(16) NOT NULL DEFAULT 'info',\n message TEXT NOT NULL,\n fields TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_logs_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_logs_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_logs_attempt_id FOREIGN KEY (attempt_id) REFERENCES capture_attempts(id) ON DELETE CASCADE\n);\nCREATE INDEX capture_logs_attempt_seq_idx ON capture_logs (attempt_id, seq);\nCREATE TABLE IF NOT EXISTS snapshots (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n story_id VARCHAR(255) NOT NULL,\n story_name TEXT NOT NULL,\n story_title TEXT NOT NULL,\n story_import_path VARCHAR(512),\n design_url TEXT,\n viewport_name VARCHAR(64) NOT NULL DEFAULT 'desktop',\n viewport_width INTEGER NOT NULL DEFAULT 1280,\n viewport_height INTEGER NOT NULL DEFAULT 720,\n screenshot_path TEXT NOT NULL,\n diff_path TEXT,\n diff_pixels INTEGER,\n diff_ratio DOUBLE,\n diff_passed TINYINT(1),\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n reviewed_by TEXT,\n reviewed_at DATETIME(3),\n infra_hash TEXT,\n env_change TEXT,\n inherited TINYINT(1) NOT NULL DEFAULT false,\n baseline_id VARCHAR(64),\n baseline_version TEXT,\n source_build_id TEXT,\n comparison_image_path TEXT,\n comparison_metadata TEXT,\n mode VARCHAR(64),\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n duration_ms INT,\n a11y_violations TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_snapshots_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_snapshots_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX snapshots_build_id_idx ON snapshots (build_id);\nCREATE INDEX snapshots_project_import_path_idx ON snapshots (project_id, story_import_path);\nCREATE TABLE IF NOT EXISTS baselines (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n story_id VARCHAR(255) NOT NULL,\n viewport_name VARCHAR(64) NOT NULL DEFAULT 'desktop',\n branch VARCHAR(255) NOT NULL,\n snapshot_id VARCHAR(64),\n source_build_id TEXT,\n screenshot_path TEXT NOT NULL,\n infra_hash TEXT,\n fingerprint TEXT,\n mode VARCHAR(64),\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_baselines_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX baselines_project_story_idx ON baselines (project_id, story_id);\nCREATE TABLE IF NOT EXISTS users (\n id VARCHAR(64) PRIMARY KEY,\n email VARCHAR(255) NOT NULL UNIQUE,\n name TEXT NOT NULL,\n avatar_url TEXT,\n role VARCHAR(32) NOT NULL DEFAULT 'member',\n last_login_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n password_hash TEXT,\n display_name_override TEXT,\n auth_provider VARCHAR(32) NOT NULL DEFAULT 'oidc',\n disabled TINYINT(1) NOT NULL DEFAULT 0\n);\nCREATE TABLE IF NOT EXISTS user_connections (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n service VARCHAR(64) NOT NULL,\n token_encrypted TEXT NOT NULL,\n refresh_token_encrypted TEXT,\n expires_at DATETIME(3),\n status VARCHAR(32) NOT NULL DEFAULT 'ok',\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_user_connections_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX user_connections_user_service_idx ON user_connections (user_id, service);\nCREATE TABLE IF NOT EXISTS comments (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n snapshot_id VARCHAR(64),\n user_id VARCHAR(64),\n body TEXT NOT NULL,\n parent_id TEXT,\n resolved TINYINT(1) NOT NULL DEFAULT false,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n story_id TEXT,\n CONSTRAINT fk_comments_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_snapshot_id FOREIGN KEY (snapshot_id) REFERENCES snapshots(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE INDEX comments_build_id_idx ON comments (build_id);\nCREATE TABLE IF NOT EXISTS build_reviews (\n id VARCHAR(64) PRIMARY KEY,\n build_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64),\n verdict TEXT NOT NULL,\n body TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_reviews_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_reviews_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE INDEX build_reviews_build_id_idx ON build_reviews (build_id);\nCREATE TABLE IF NOT EXISTS label_types (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n `key` VARCHAR(255) NOT NULL,\n name TEXT NOT NULL,\n link_template TEXT,\n color TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_label_types_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX label_types_project_key_idx ON label_types (project_id, `key`);\nCREATE TABLE IF NOT EXISTS build_labels (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n type_key VARCHAR(64) NOT NULL,\n value VARCHAR(255) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_labels_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_labels_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX build_labels_build_type_value_idx ON build_labels (build_id, type_key, value);\nCREATE TABLE IF NOT EXISTS project_links (\n id VARCHAR(64) PRIMARY KEY,\n downstream_id VARCHAR(64) NOT NULL,\n upstream_id VARCHAR(64) NOT NULL,\n package_name VARCHAR(255) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_links_downstream_id FOREIGN KEY (downstream_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_project_links_upstream_id FOREIGN KEY (upstream_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_links_downstream_package_idx ON project_links (downstream_id, package_name);\nCREATE TABLE IF NOT EXISTS design_links (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n import_path VARCHAR(512),\n label TEXT,\n url TEXT NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_links_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX design_links_project_id_idx ON design_links (project_id);\nCREATE TABLE IF NOT EXISTS design_credentials (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n provider VARCHAR(64) NOT NULL,\n token_encrypted TEXT NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'unknown',\n checked_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_credentials_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX design_credentials_project_provider_idx ON design_credentials (project_id, provider);\nCREATE TABLE IF NOT EXISTS design_nodes (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n provider VARCHAR(64) NOT NULL,\n viewer_id VARCHAR(128) NOT NULL DEFAULT '',\n file_key VARCHAR(128) NOT NULL,\n node_id VARCHAR(128) NOT NULL DEFAULT '',\n name TEXT,\n version TEXT,\n last_modified TEXT,\n state VARCHAR(32) NOT NULL DEFAULT 'ok',\n render_path TEXT,\n render_version TEXT,\n notified_version TEXT,\n fetched_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_nodes_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX design_nodes_project_file_node_idx ON design_nodes (project_id, provider, viewer_id, file_key, node_id);\nCREATE TABLE IF NOT EXISTS build_package_usage (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n story_import_path TEXT NOT NULL,\n package_name TEXT NOT NULL,\n module_path TEXT NOT NULL,\n version TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_package_usage_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_package_usage_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX build_package_usage_build_id_idx ON build_package_usage (build_id);\nCREATE TABLE IF NOT EXISTS tokens (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n name TEXT NOT NULL,\n hash VARCHAR(128) NOT NULL UNIQUE,\n user_id VARCHAR(64),\n last_used_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_tokens_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS webhooks (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n url TEXT NOT NULL,\n secret_encrypted TEXT NOT NULL,\n events TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_webhooks_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS notification_channels (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64),\n provider TEXT NOT NULL,\n config TEXT NOT NULL,\n secret_encrypted TEXT,\n events TEXT,\n enabled BOOLEAN NOT NULL DEFAULT TRUE,\n last_error TEXT,\n last_error_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_notification_channels_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX notification_channels_project_id_idx ON notification_channels (project_id);\nCREATE TABLE IF NOT EXISTS notification_subscriptions (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n events TEXT,\n via TEXT,\n enabled BOOLEAN NOT NULL DEFAULT TRUE,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_notification_subscriptions_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_notification_subscriptions_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX notification_subscriptions_project_user_idx ON notification_subscriptions (project_id, user_id);\nCREATE TABLE IF NOT EXISTS insights (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64),\n kind VARCHAR(32) NOT NULL,\n window_key VARCHAR(64),\n input_hash VARCHAR(64) NOT NULL,\n status VARCHAR(32) NOT NULL,\n profile TEXT NOT NULL,\n model TEXT NOT NULL,\n prompt_version TEXT NOT NULL,\n verdict TEXT,\n summary TEXT,\n result TEXT,\n error_code TEXT,\n created_at DATETIME(3) NOT NULL,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n CONSTRAINT fk_insights_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_insights_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX insights_project_build_idx ON insights (project_id, build_id);\nCREATE INDEX insights_created_at_idx ON insights (created_at);\nCREATE UNIQUE INDEX insights_triage_unique_idx ON insights (project_id, build_id, kind, input_hash);\nCREATE UNIQUE INDEX insights_health_unique_idx ON insights (project_id, kind, window_key);\nCREATE TABLE IF NOT EXISTS ai_usage (\n id VARCHAR(64) PRIMARY KEY,\n insight_id TEXT,\n project_id VARCHAR(64) NOT NULL,\n profile TEXT NOT NULL,\n task TEXT NOT NULL,\n model TEXT NOT NULL,\n input_tokens INTEGER NOT NULL DEFAULT 0,\n output_tokens INTEGER NOT NULL DEFAULT 0,\n estimated TINYINT(1) NOT NULL DEFAULT false,\n images INTEGER NOT NULL DEFAULT 0,\n status VARCHAR(32) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_ai_usage_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX ai_usage_created_at_idx ON ai_usage (created_at);\nCREATE INDEX ai_usage_project_created_idx ON ai_usage (project_id, created_at);\nCREATE TABLE IF NOT EXISTS ai_budget_alerts (\n id VARCHAR(64) PRIMARY KEY,\n day TEXT NOT NULL,\n threshold INTEGER NOT NULL,\n created_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS user_invite_tokens (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n token_hash VARCHAR(128) NOT NULL UNIQUE,\n expires_at DATETIME(3) NOT NULL,\n used_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_user_invite_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS project_members (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n role VARCHAR(32) NOT NULL DEFAULT 'viewer',\n source VARCHAR(32) NOT NULL DEFAULT 'manual',\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_members_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_project_members_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_members_project_user_idx ON project_members (project_id, user_id);\nCREATE TABLE IF NOT EXISTS project_group_mappings (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n group_name VARCHAR(255) NOT NULL,\n role VARCHAR(32) NOT NULL DEFAULT 'viewer',\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_group_mappings_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_group_mappings_project_group_idx ON project_group_mappings (project_id, group_name);\nCREATE TABLE IF NOT EXISTS content_refs (\n hash VARCHAR(128) PRIMARY KEY,\n ref_count INTEGER NOT NULL DEFAULT 1,\n last_seen_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS `user` (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT NOT NULL,\n email VARCHAR(255) NOT NULL UNIQUE,\n email_verified TINYINT(1) NOT NULL DEFAULT false,\n image TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS session (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n token VARCHAR(512) NOT NULL UNIQUE,\n expires_at DATETIME(3) NOT NULL,\n ip_address TEXT,\n user_agent TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_session_user_id FOREIGN KEY (user_id) REFERENCES `user`(id) ON DELETE CASCADE\n);\nCREATE INDEX session_token_idx ON session (token);\nCREATE INDEX session_user_id_idx ON session (user_id);\nCREATE TABLE IF NOT EXISTS account (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n account_id TEXT NOT NULL,\n provider_id TEXT NOT NULL,\n access_token TEXT,\n refresh_token TEXT,\n id_token TEXT,\n access_token_expires_at DATETIME(3),\n refresh_token_expires_at DATETIME(3),\n scope TEXT,\n expires_at DATETIME(3),\n password TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_account_user_id FOREIGN KEY (user_id) REFERENCES `user`(id) ON DELETE CASCADE\n);\nCREATE INDEX account_user_id_idx ON account (user_id);\nCREATE TABLE IF NOT EXISTS verification (\n id VARCHAR(64) PRIMARY KEY,\n identifier VARCHAR(255) NOT NULL,\n value TEXT NOT NULL,\n expires_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE INDEX verification_identifier_idx ON verification (identifier);\nCREATE TABLE IF NOT EXISTS passkey (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT,\n public_key TEXT NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n credential_id VARCHAR(255) NOT NULL,\n counter INTEGER NOT NULL,\n device_type TEXT NOT NULL,\n backed_up TINYINT(1) NOT NULL DEFAULT false,\n transports TEXT,\n aaguid TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3),\n CONSTRAINT fk_passkey_user_id FOREIGN KEY (user_id) REFERENCES `user`(id) ON DELETE CASCADE\n);\nCREATE INDEX passkey_user_id_idx ON passkey (user_id);\nCREATE INDEX passkey_credential_id_idx ON passkey (credential_id);\nCREATE TABLE IF NOT EXISTS `ssoProvider` (\n id VARCHAR(64) PRIMARY KEY,\n issuer TEXT NOT NULL,\n oidc_config TEXT,\n saml_config TEXT,\n user_id VARCHAR(64) NOT NULL,\n provider_id VARCHAR(64) NOT NULL UNIQUE,\n organization_id TEXT,\n domain VARCHAR(255) NOT NULL,\n CONSTRAINT fk_ssoProvider_user_id FOREIGN KEY (user_id) REFERENCES `user`(id) ON DELETE CASCADE\n);\nCREATE INDEX ssoprovider_domain_idx ON `ssoProvider` (domain);\n";
5
5
  export { DDL };
6
6
  //# sourceMappingURL=ddl.d.mts.map
package/dist/ddl.mjs CHANGED
@@ -337,6 +337,7 @@ CREATE TABLE IF NOT EXISTS design_nodes (
337
337
  state VARCHAR(32) NOT NULL DEFAULT 'ok',
338
338
  render_path TEXT,
339
339
  render_version TEXT,
340
+ notified_version TEXT,
340
341
  fetched_at DATETIME(3) NOT NULL,
341
342
  created_at DATETIME(3) NOT NULL,
342
343
  updated_at DATETIME(3) NOT NULL,
package/dist/ddl.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ddl.mjs","names":[],"sources":["../src/ddl.ts"],"sourcesContent":["/** Canonical MySQL DDL for all StoryShelf tables and indexes. */\nexport const DDL = `\nCREATE TABLE IF NOT EXISTS projects (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT NOT NULL,\n slug VARCHAR(255) NOT NULL UNIQUE,\n git_repository TEXT,\n git_default_branch VARCHAR(255) NOT NULL DEFAULT 'main',\n pixel_threshold DOUBLE NOT NULL DEFAULT 0.1,\n max_diff_ratio DOUBLE NOT NULL DEFAULT 0.01,\n public_branch_regex TEXT,\n storybook_meta TEXT,\n execute_play TINYINT(1) NOT NULL DEFAULT false,\n play_timeout_ms INTEGER NOT NULL DEFAULT 10000,\n run_a11y TINYINT(1) NOT NULL DEFAULT true,\n run_tests TINYINT(1) NOT NULL DEFAULT false,\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n viewports TEXT,\n browsers TEXT,\n modes_allowlist TEXT,\n automigrate TINYINT(1) NOT NULL DEFAULT false,\n ai_profile TEXT,\n review_enabled TINYINT(1) NOT NULL DEFAULT true,\n review_approvals INT NOT NULL DEFAULT 1,\n storybook_url_ttl_seconds INT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS builds (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n git_sha VARCHAR(64) NOT NULL,\n git_branch VARCHAR(255) NOT NULL,\n is_default TINYINT(1) NOT NULL DEFAULT false,\n author_email TEXT,\n author_name TEXT,\n message TEXT,\n public TINYINT(1) NOT NULL DEFAULT false,\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n snapshot_count INTEGER NOT NULL DEFAULT 0,\n changed_count INTEGER NOT NULL DEFAULT 0,\n approved_count INTEGER NOT NULL DEFAULT 0,\n rejected_count INTEGER NOT NULL DEFAULT 0,\n inherited_count INTEGER NOT NULL DEFAULT 0,\n affected_only TINYINT(1) NOT NULL DEFAULT true,\n baseline_sha TEXT,\n changed_files TEXT,\n affected_import_paths TEXT,\n test_results TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_builds_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX builds_project_gitsha_idx ON builds (project_id, git_sha);\nCREATE INDEX builds_git_branch_idx ON builds (git_branch);\nCREATE TABLE IF NOT EXISTS capture_attempts (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n attempt_no INTEGER NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'queued',\n error TEXT,\n req_id TEXT,\n story_count INTEGER NOT NULL DEFAULT 0,\n failed_count INTEGER NOT NULL DEFAULT 0,\n queued_at DATETIME(3) NOT NULL,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_attempts_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_attempts_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX capture_attempts_build_no_idx ON capture_attempts (build_id, attempt_no);\nCREATE INDEX capture_attempts_build_id_idx ON capture_attempts (build_id);\nCREATE TABLE IF NOT EXISTS capture_shards (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n kind VARCHAR(32) NOT NULL,\n ordinal INTEGER NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n attempt_id VARCHAR(64),\n payload TEXT,\n result TEXT,\n error TEXT,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_shards_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_shards_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX capture_shards_build_kind_ordinal_idx ON capture_shards (build_id, kind, ordinal);\nCREATE INDEX capture_shards_build_id_idx ON capture_shards (build_id);\nCREATE TABLE IF NOT EXISTS capture_jobs (\n id VARCHAR(64) PRIMARY KEY,\n entry VARCHAR(64) NOT NULL,\n job_id VARCHAR(64) NOT NULL,\n kind VARCHAR(32) NOT NULL,\n build_id VARCHAR(64),\n shard_id VARCHAR(64),\n attempt INTEGER NOT NULL DEFAULT 0,\n max_attempts INTEGER NOT NULL DEFAULT 3,\n status VARCHAR(32) NOT NULL,\n visible_at DATETIME(3),\n owner TEXT,\n payload TEXT,\n cancel_requested_at DATETIME(3),\n error TEXT,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE INDEX capture_jobs_poll_idx ON capture_jobs (kind, visible_at, status);\nCREATE INDEX capture_jobs_job_id_idx ON capture_jobs (job_id);\nCREATE INDEX capture_jobs_build_id_idx ON capture_jobs (build_id);\nCREATE INDEX capture_jobs_entry_created_idx ON capture_jobs (entry, created_at);\nCREATE TABLE IF NOT EXISTS site_settings (\n id VARCHAR(64) PRIMARY KEY,\n value TEXT NOT NULL,\n updated_by TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS build_components (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n import_path VARCHAR(512) NOT NULL,\n title TEXT NOT NULL,\n story_count INTEGER NOT NULL DEFAULT 0,\n hash TEXT NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_components_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_components_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX build_components_build_id_idx ON build_components (build_id);\nCREATE INDEX build_components_project_import_path_idx ON build_components (project_id, import_path);\nCREATE TABLE IF NOT EXISTS capture_logs (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n attempt_id VARCHAR(64) NOT NULL,\n seq INTEGER NOT NULL,\n level VARCHAR(16) NOT NULL DEFAULT 'info',\n message TEXT NOT NULL,\n fields TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_logs_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_logs_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_logs_attempt_id FOREIGN KEY (attempt_id) REFERENCES capture_attempts(id) ON DELETE CASCADE\n);\nCREATE INDEX capture_logs_attempt_seq_idx ON capture_logs (attempt_id, seq);\nCREATE TABLE IF NOT EXISTS snapshots (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n story_id VARCHAR(255) NOT NULL,\n story_name TEXT NOT NULL,\n story_title TEXT NOT NULL,\n story_import_path VARCHAR(512),\n design_url TEXT,\n viewport_name VARCHAR(64) NOT NULL DEFAULT 'desktop',\n viewport_width INTEGER NOT NULL DEFAULT 1280,\n viewport_height INTEGER NOT NULL DEFAULT 720,\n screenshot_path TEXT NOT NULL,\n diff_path TEXT,\n diff_pixels INTEGER,\n diff_ratio DOUBLE,\n diff_passed TINYINT(1),\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n reviewed_by TEXT,\n reviewed_at DATETIME(3),\n infra_hash TEXT,\n env_change TEXT,\n inherited TINYINT(1) NOT NULL DEFAULT false,\n baseline_id VARCHAR(64),\n baseline_version TEXT,\n source_build_id TEXT,\n comparison_image_path TEXT,\n comparison_metadata TEXT,\n mode VARCHAR(64),\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n duration_ms INT,\n a11y_violations TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_snapshots_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_snapshots_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX snapshots_build_id_idx ON snapshots (build_id);\nCREATE INDEX snapshots_project_import_path_idx ON snapshots (project_id, story_import_path);\nCREATE TABLE IF NOT EXISTS baselines (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n story_id VARCHAR(255) NOT NULL,\n viewport_name VARCHAR(64) NOT NULL DEFAULT 'desktop',\n branch VARCHAR(255) NOT NULL,\n snapshot_id VARCHAR(64),\n source_build_id TEXT,\n screenshot_path TEXT NOT NULL,\n infra_hash TEXT,\n fingerprint TEXT,\n mode VARCHAR(64),\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_baselines_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX baselines_project_story_idx ON baselines (project_id, story_id);\nCREATE TABLE IF NOT EXISTS users (\n id VARCHAR(64) PRIMARY KEY,\n email VARCHAR(255) NOT NULL UNIQUE,\n name TEXT NOT NULL,\n avatar_url TEXT,\n role VARCHAR(32) NOT NULL DEFAULT 'member',\n last_login_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n password_hash TEXT,\n display_name_override TEXT,\n auth_provider VARCHAR(32) NOT NULL DEFAULT 'oidc',\n disabled TINYINT(1) NOT NULL DEFAULT 0\n);\nCREATE TABLE IF NOT EXISTS user_connections (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n service VARCHAR(64) NOT NULL,\n token_encrypted TEXT NOT NULL,\n refresh_token_encrypted TEXT,\n expires_at DATETIME(3),\n status VARCHAR(32) NOT NULL DEFAULT 'ok',\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_user_connections_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX user_connections_user_service_idx ON user_connections (user_id, service);\nCREATE TABLE IF NOT EXISTS comments (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n snapshot_id VARCHAR(64),\n user_id VARCHAR(64),\n body TEXT NOT NULL,\n parent_id TEXT,\n resolved TINYINT(1) NOT NULL DEFAULT false,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n story_id TEXT,\n CONSTRAINT fk_comments_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_snapshot_id FOREIGN KEY (snapshot_id) REFERENCES snapshots(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE INDEX comments_build_id_idx ON comments (build_id);\nCREATE TABLE IF NOT EXISTS build_reviews (\n id VARCHAR(64) PRIMARY KEY,\n build_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64),\n verdict TEXT NOT NULL,\n body TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_reviews_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_reviews_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE INDEX build_reviews_build_id_idx ON build_reviews (build_id);\nCREATE TABLE IF NOT EXISTS label_types (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n \\`key\\` VARCHAR(255) NOT NULL,\n name TEXT NOT NULL,\n link_template TEXT,\n color TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_label_types_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX label_types_project_key_idx ON label_types (project_id, \\`key\\`);\nCREATE TABLE IF NOT EXISTS build_labels (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n type_key VARCHAR(64) NOT NULL,\n value VARCHAR(255) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_labels_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_labels_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX build_labels_build_type_value_idx ON build_labels (build_id, type_key, value);\nCREATE TABLE IF NOT EXISTS project_links (\n id VARCHAR(64) PRIMARY KEY,\n downstream_id VARCHAR(64) NOT NULL,\n upstream_id VARCHAR(64) NOT NULL,\n package_name VARCHAR(255) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_links_downstream_id FOREIGN KEY (downstream_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_project_links_upstream_id FOREIGN KEY (upstream_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_links_downstream_package_idx ON project_links (downstream_id, package_name);\nCREATE TABLE IF NOT EXISTS design_links (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n import_path VARCHAR(512),\n label TEXT,\n url TEXT NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_links_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX design_links_project_id_idx ON design_links (project_id);\nCREATE TABLE IF NOT EXISTS design_credentials (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n provider VARCHAR(64) NOT NULL,\n token_encrypted TEXT NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'unknown',\n checked_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_credentials_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX design_credentials_project_provider_idx ON design_credentials (project_id, provider);\nCREATE TABLE IF NOT EXISTS design_nodes (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n provider VARCHAR(64) NOT NULL,\n viewer_id VARCHAR(128) NOT NULL DEFAULT '',\n file_key VARCHAR(128) NOT NULL,\n node_id VARCHAR(128) NOT NULL DEFAULT '',\n name TEXT,\n version TEXT,\n last_modified TEXT,\n state VARCHAR(32) NOT NULL DEFAULT 'ok',\n render_path TEXT,\n render_version TEXT,\n fetched_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_nodes_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX design_nodes_project_file_node_idx ON design_nodes (project_id, provider, viewer_id, file_key, node_id);\nCREATE TABLE IF NOT EXISTS build_package_usage (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n story_import_path TEXT NOT NULL,\n package_name TEXT NOT NULL,\n module_path TEXT NOT NULL,\n version TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_package_usage_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_package_usage_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX build_package_usage_build_id_idx ON build_package_usage (build_id);\nCREATE TABLE IF NOT EXISTS tokens (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n name TEXT NOT NULL,\n hash VARCHAR(128) NOT NULL UNIQUE,\n user_id VARCHAR(64),\n last_used_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_tokens_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS webhooks (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n url TEXT NOT NULL,\n secret_encrypted TEXT NOT NULL,\n events TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_webhooks_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS notification_channels (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64),\n provider TEXT NOT NULL,\n config TEXT NOT NULL,\n secret_encrypted TEXT,\n events TEXT,\n enabled BOOLEAN NOT NULL DEFAULT TRUE,\n last_error TEXT,\n last_error_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_notification_channels_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX notification_channels_project_id_idx ON notification_channels (project_id);\nCREATE TABLE IF NOT EXISTS notification_subscriptions (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n events TEXT,\n via TEXT,\n enabled BOOLEAN NOT NULL DEFAULT TRUE,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_notification_subscriptions_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_notification_subscriptions_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX notification_subscriptions_project_user_idx ON notification_subscriptions (project_id, user_id);\nCREATE TABLE IF NOT EXISTS insights (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64),\n kind VARCHAR(32) NOT NULL,\n window_key VARCHAR(64),\n input_hash VARCHAR(64) NOT NULL,\n status VARCHAR(32) NOT NULL,\n profile TEXT NOT NULL,\n model TEXT NOT NULL,\n prompt_version TEXT NOT NULL,\n verdict TEXT,\n summary TEXT,\n result TEXT,\n error_code TEXT,\n created_at DATETIME(3) NOT NULL,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n CONSTRAINT fk_insights_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_insights_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX insights_project_build_idx ON insights (project_id, build_id);\nCREATE INDEX insights_created_at_idx ON insights (created_at);\nCREATE UNIQUE INDEX insights_triage_unique_idx ON insights (project_id, build_id, kind, input_hash);\nCREATE UNIQUE INDEX insights_health_unique_idx ON insights (project_id, kind, window_key);\nCREATE TABLE IF NOT EXISTS ai_usage (\n id VARCHAR(64) PRIMARY KEY,\n insight_id TEXT,\n project_id VARCHAR(64) NOT NULL,\n profile TEXT NOT NULL,\n task TEXT NOT NULL,\n model TEXT NOT NULL,\n input_tokens INTEGER NOT NULL DEFAULT 0,\n output_tokens INTEGER NOT NULL DEFAULT 0,\n estimated TINYINT(1) NOT NULL DEFAULT false,\n images INTEGER NOT NULL DEFAULT 0,\n status VARCHAR(32) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_ai_usage_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX ai_usage_created_at_idx ON ai_usage (created_at);\nCREATE INDEX ai_usage_project_created_idx ON ai_usage (project_id, created_at);\nCREATE TABLE IF NOT EXISTS ai_budget_alerts (\n id VARCHAR(64) PRIMARY KEY,\n day TEXT NOT NULL,\n threshold INTEGER NOT NULL,\n created_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS user_invite_tokens (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n token_hash VARCHAR(128) NOT NULL UNIQUE,\n expires_at DATETIME(3) NOT NULL,\n used_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_user_invite_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS project_members (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n role VARCHAR(32) NOT NULL DEFAULT 'viewer',\n source VARCHAR(32) NOT NULL DEFAULT 'manual',\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_members_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_project_members_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_members_project_user_idx ON project_members (project_id, user_id);\nCREATE TABLE IF NOT EXISTS project_group_mappings (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n group_name VARCHAR(255) NOT NULL,\n role VARCHAR(32) NOT NULL DEFAULT 'viewer',\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_group_mappings_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_group_mappings_project_group_idx ON project_group_mappings (project_id, group_name);\nCREATE TABLE IF NOT EXISTS content_refs (\n hash VARCHAR(128) PRIMARY KEY,\n ref_count INTEGER NOT NULL DEFAULT 1,\n last_seen_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS \\`user\\` (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT NOT NULL,\n email VARCHAR(255) NOT NULL UNIQUE,\n email_verified TINYINT(1) NOT NULL DEFAULT false,\n image TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS session (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n token VARCHAR(512) NOT NULL UNIQUE,\n expires_at DATETIME(3) NOT NULL,\n ip_address TEXT,\n user_agent TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_session_user_id FOREIGN KEY (user_id) REFERENCES \\`user\\`(id) ON DELETE CASCADE\n);\nCREATE INDEX session_token_idx ON session (token);\nCREATE INDEX session_user_id_idx ON session (user_id);\nCREATE TABLE IF NOT EXISTS account (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n account_id TEXT NOT NULL,\n provider_id TEXT NOT NULL,\n access_token TEXT,\n refresh_token TEXT,\n id_token TEXT,\n access_token_expires_at DATETIME(3),\n refresh_token_expires_at DATETIME(3),\n scope TEXT,\n expires_at DATETIME(3),\n password TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_account_user_id FOREIGN KEY (user_id) REFERENCES \\`user\\`(id) ON DELETE CASCADE\n);\nCREATE INDEX account_user_id_idx ON account (user_id);\nCREATE TABLE IF NOT EXISTS verification (\n id VARCHAR(64) PRIMARY KEY,\n identifier VARCHAR(255) NOT NULL,\n value TEXT NOT NULL,\n expires_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE INDEX verification_identifier_idx ON verification (identifier);\nCREATE TABLE IF NOT EXISTS passkey (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT,\n public_key TEXT NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n credential_id VARCHAR(255) NOT NULL,\n counter INTEGER NOT NULL,\n device_type TEXT NOT NULL,\n backed_up TINYINT(1) NOT NULL DEFAULT false,\n transports TEXT,\n aaguid TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3),\n CONSTRAINT fk_passkey_user_id FOREIGN KEY (user_id) REFERENCES \\`user\\`(id) ON DELETE CASCADE\n);\nCREATE INDEX passkey_user_id_idx ON passkey (user_id);\nCREATE INDEX passkey_credential_id_idx ON passkey (credential_id);\nCREATE TABLE IF NOT EXISTS \\`ssoProvider\\` (\n id VARCHAR(64) PRIMARY KEY,\n issuer TEXT NOT NULL,\n oidc_config TEXT,\n saml_config TEXT,\n user_id VARCHAR(64) NOT NULL,\n provider_id VARCHAR(64) NOT NULL UNIQUE,\n organization_id TEXT,\n domain VARCHAR(255) NOT NULL,\n CONSTRAINT fk_ssoProvider_user_id FOREIGN KEY (user_id) REFERENCES \\`user\\`(id) ON DELETE CASCADE\n);\nCREATE INDEX ssoprovider_domain_idx ON \\`ssoProvider\\` (domain);\n`;\n"],"mappings":";;;;;AACA,MAAa,MAAM"}
1
+ {"version":3,"file":"ddl.mjs","names":[],"sources":["../src/ddl.ts"],"sourcesContent":["/** Canonical MySQL DDL for all StoryShelf tables and indexes. */\nexport const DDL = `\nCREATE TABLE IF NOT EXISTS projects (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT NOT NULL,\n slug VARCHAR(255) NOT NULL UNIQUE,\n git_repository TEXT,\n git_default_branch VARCHAR(255) NOT NULL DEFAULT 'main',\n pixel_threshold DOUBLE NOT NULL DEFAULT 0.1,\n max_diff_ratio DOUBLE NOT NULL DEFAULT 0.01,\n public_branch_regex TEXT,\n storybook_meta TEXT,\n execute_play TINYINT(1) NOT NULL DEFAULT false,\n play_timeout_ms INTEGER NOT NULL DEFAULT 10000,\n run_a11y TINYINT(1) NOT NULL DEFAULT true,\n run_tests TINYINT(1) NOT NULL DEFAULT false,\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n viewports TEXT,\n browsers TEXT,\n modes_allowlist TEXT,\n automigrate TINYINT(1) NOT NULL DEFAULT false,\n ai_profile TEXT,\n review_enabled TINYINT(1) NOT NULL DEFAULT true,\n review_approvals INT NOT NULL DEFAULT 1,\n storybook_url_ttl_seconds INT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS builds (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n git_sha VARCHAR(64) NOT NULL,\n git_branch VARCHAR(255) NOT NULL,\n is_default TINYINT(1) NOT NULL DEFAULT false,\n author_email TEXT,\n author_name TEXT,\n message TEXT,\n public TINYINT(1) NOT NULL DEFAULT false,\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n snapshot_count INTEGER NOT NULL DEFAULT 0,\n changed_count INTEGER NOT NULL DEFAULT 0,\n approved_count INTEGER NOT NULL DEFAULT 0,\n rejected_count INTEGER NOT NULL DEFAULT 0,\n inherited_count INTEGER NOT NULL DEFAULT 0,\n affected_only TINYINT(1) NOT NULL DEFAULT true,\n baseline_sha TEXT,\n changed_files TEXT,\n affected_import_paths TEXT,\n test_results TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_builds_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX builds_project_gitsha_idx ON builds (project_id, git_sha);\nCREATE INDEX builds_git_branch_idx ON builds (git_branch);\nCREATE TABLE IF NOT EXISTS capture_attempts (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n attempt_no INTEGER NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'queued',\n error TEXT,\n req_id TEXT,\n story_count INTEGER NOT NULL DEFAULT 0,\n failed_count INTEGER NOT NULL DEFAULT 0,\n queued_at DATETIME(3) NOT NULL,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_attempts_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_attempts_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX capture_attempts_build_no_idx ON capture_attempts (build_id, attempt_no);\nCREATE INDEX capture_attempts_build_id_idx ON capture_attempts (build_id);\nCREATE TABLE IF NOT EXISTS capture_shards (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n kind VARCHAR(32) NOT NULL,\n ordinal INTEGER NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n attempt_id VARCHAR(64),\n payload TEXT,\n result TEXT,\n error TEXT,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_shards_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_shards_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX capture_shards_build_kind_ordinal_idx ON capture_shards (build_id, kind, ordinal);\nCREATE INDEX capture_shards_build_id_idx ON capture_shards (build_id);\nCREATE TABLE IF NOT EXISTS capture_jobs (\n id VARCHAR(64) PRIMARY KEY,\n entry VARCHAR(64) NOT NULL,\n job_id VARCHAR(64) NOT NULL,\n kind VARCHAR(32) NOT NULL,\n build_id VARCHAR(64),\n shard_id VARCHAR(64),\n attempt INTEGER NOT NULL DEFAULT 0,\n max_attempts INTEGER NOT NULL DEFAULT 3,\n status VARCHAR(32) NOT NULL,\n visible_at DATETIME(3),\n owner TEXT,\n payload TEXT,\n cancel_requested_at DATETIME(3),\n error TEXT,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE INDEX capture_jobs_poll_idx ON capture_jobs (kind, visible_at, status);\nCREATE INDEX capture_jobs_job_id_idx ON capture_jobs (job_id);\nCREATE INDEX capture_jobs_build_id_idx ON capture_jobs (build_id);\nCREATE INDEX capture_jobs_entry_created_idx ON capture_jobs (entry, created_at);\nCREATE TABLE IF NOT EXISTS site_settings (\n id VARCHAR(64) PRIMARY KEY,\n value TEXT NOT NULL,\n updated_by TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS build_components (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n import_path VARCHAR(512) NOT NULL,\n title TEXT NOT NULL,\n story_count INTEGER NOT NULL DEFAULT 0,\n hash TEXT NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_components_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_components_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX build_components_build_id_idx ON build_components (build_id);\nCREATE INDEX build_components_project_import_path_idx ON build_components (project_id, import_path);\nCREATE TABLE IF NOT EXISTS capture_logs (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n attempt_id VARCHAR(64) NOT NULL,\n seq INTEGER NOT NULL,\n level VARCHAR(16) NOT NULL DEFAULT 'info',\n message TEXT NOT NULL,\n fields TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_capture_logs_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_logs_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_capture_logs_attempt_id FOREIGN KEY (attempt_id) REFERENCES capture_attempts(id) ON DELETE CASCADE\n);\nCREATE INDEX capture_logs_attempt_seq_idx ON capture_logs (attempt_id, seq);\nCREATE TABLE IF NOT EXISTS snapshots (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n story_id VARCHAR(255) NOT NULL,\n story_name TEXT NOT NULL,\n story_title TEXT NOT NULL,\n story_import_path VARCHAR(512),\n design_url TEXT,\n viewport_name VARCHAR(64) NOT NULL DEFAULT 'desktop',\n viewport_width INTEGER NOT NULL DEFAULT 1280,\n viewport_height INTEGER NOT NULL DEFAULT 720,\n screenshot_path TEXT NOT NULL,\n diff_path TEXT,\n diff_pixels INTEGER,\n diff_ratio DOUBLE,\n diff_passed TINYINT(1),\n status VARCHAR(32) NOT NULL DEFAULT 'pending',\n reviewed_by TEXT,\n reviewed_at DATETIME(3),\n infra_hash TEXT,\n env_change TEXT,\n inherited TINYINT(1) NOT NULL DEFAULT false,\n baseline_id VARCHAR(64),\n baseline_version TEXT,\n source_build_id TEXT,\n comparison_image_path TEXT,\n comparison_metadata TEXT,\n mode VARCHAR(64),\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n duration_ms INT,\n a11y_violations TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_snapshots_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_snapshots_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX snapshots_build_id_idx ON snapshots (build_id);\nCREATE INDEX snapshots_project_import_path_idx ON snapshots (project_id, story_import_path);\nCREATE TABLE IF NOT EXISTS baselines (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n story_id VARCHAR(255) NOT NULL,\n viewport_name VARCHAR(64) NOT NULL DEFAULT 'desktop',\n branch VARCHAR(255) NOT NULL,\n snapshot_id VARCHAR(64),\n source_build_id TEXT,\n screenshot_path TEXT NOT NULL,\n infra_hash TEXT,\n fingerprint TEXT,\n mode VARCHAR(64),\n browser VARCHAR(64) NOT NULL DEFAULT 'chromium',\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_baselines_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX baselines_project_story_idx ON baselines (project_id, story_id);\nCREATE TABLE IF NOT EXISTS users (\n id VARCHAR(64) PRIMARY KEY,\n email VARCHAR(255) NOT NULL UNIQUE,\n name TEXT NOT NULL,\n avatar_url TEXT,\n role VARCHAR(32) NOT NULL DEFAULT 'member',\n last_login_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n password_hash TEXT,\n display_name_override TEXT,\n auth_provider VARCHAR(32) NOT NULL DEFAULT 'oidc',\n disabled TINYINT(1) NOT NULL DEFAULT 0\n);\nCREATE TABLE IF NOT EXISTS user_connections (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n service VARCHAR(64) NOT NULL,\n token_encrypted TEXT NOT NULL,\n refresh_token_encrypted TEXT,\n expires_at DATETIME(3),\n status VARCHAR(32) NOT NULL DEFAULT 'ok',\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_user_connections_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX user_connections_user_service_idx ON user_connections (user_id, service);\nCREATE TABLE IF NOT EXISTS comments (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n snapshot_id VARCHAR(64),\n user_id VARCHAR(64),\n body TEXT NOT NULL,\n parent_id TEXT,\n resolved TINYINT(1) NOT NULL DEFAULT false,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n story_id TEXT,\n CONSTRAINT fk_comments_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_snapshot_id FOREIGN KEY (snapshot_id) REFERENCES snapshots(id) ON DELETE CASCADE,\n CONSTRAINT fk_comments_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE INDEX comments_build_id_idx ON comments (build_id);\nCREATE TABLE IF NOT EXISTS build_reviews (\n id VARCHAR(64) PRIMARY KEY,\n build_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64),\n verdict TEXT NOT NULL,\n body TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_reviews_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_reviews_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE INDEX build_reviews_build_id_idx ON build_reviews (build_id);\nCREATE TABLE IF NOT EXISTS label_types (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n \\`key\\` VARCHAR(255) NOT NULL,\n name TEXT NOT NULL,\n link_template TEXT,\n color TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_label_types_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX label_types_project_key_idx ON label_types (project_id, \\`key\\`);\nCREATE TABLE IF NOT EXISTS build_labels (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n type_key VARCHAR(64) NOT NULL,\n value VARCHAR(255) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_labels_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_labels_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX build_labels_build_type_value_idx ON build_labels (build_id, type_key, value);\nCREATE TABLE IF NOT EXISTS project_links (\n id VARCHAR(64) PRIMARY KEY,\n downstream_id VARCHAR(64) NOT NULL,\n upstream_id VARCHAR(64) NOT NULL,\n package_name VARCHAR(255) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_links_downstream_id FOREIGN KEY (downstream_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_project_links_upstream_id FOREIGN KEY (upstream_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_links_downstream_package_idx ON project_links (downstream_id, package_name);\nCREATE TABLE IF NOT EXISTS design_links (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n import_path VARCHAR(512),\n label TEXT,\n url TEXT NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_links_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX design_links_project_id_idx ON design_links (project_id);\nCREATE TABLE IF NOT EXISTS design_credentials (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n provider VARCHAR(64) NOT NULL,\n token_encrypted TEXT NOT NULL,\n status VARCHAR(32) NOT NULL DEFAULT 'unknown',\n checked_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_credentials_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX design_credentials_project_provider_idx ON design_credentials (project_id, provider);\nCREATE TABLE IF NOT EXISTS design_nodes (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n provider VARCHAR(64) NOT NULL,\n viewer_id VARCHAR(128) NOT NULL DEFAULT '',\n file_key VARCHAR(128) NOT NULL,\n node_id VARCHAR(128) NOT NULL DEFAULT '',\n name TEXT,\n version TEXT,\n last_modified TEXT,\n state VARCHAR(32) NOT NULL DEFAULT 'ok',\n render_path TEXT,\n render_version TEXT,\n notified_version TEXT,\n fetched_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_design_nodes_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX design_nodes_project_file_node_idx ON design_nodes (project_id, provider, viewer_id, file_key, node_id);\nCREATE TABLE IF NOT EXISTS build_package_usage (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64) NOT NULL,\n story_import_path TEXT NOT NULL,\n package_name TEXT NOT NULL,\n module_path TEXT NOT NULL,\n version TEXT,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_build_package_usage_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_build_package_usage_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX build_package_usage_build_id_idx ON build_package_usage (build_id);\nCREATE TABLE IF NOT EXISTS tokens (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n name TEXT NOT NULL,\n hash VARCHAR(128) NOT NULL UNIQUE,\n user_id VARCHAR(64),\n last_used_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_tokens_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS webhooks (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n url TEXT NOT NULL,\n secret_encrypted TEXT NOT NULL,\n events TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_webhooks_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS notification_channels (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64),\n provider TEXT NOT NULL,\n config TEXT NOT NULL,\n secret_encrypted TEXT,\n events TEXT,\n enabled BOOLEAN NOT NULL DEFAULT TRUE,\n last_error TEXT,\n last_error_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_notification_channels_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX notification_channels_project_id_idx ON notification_channels (project_id);\nCREATE TABLE IF NOT EXISTS notification_subscriptions (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n events TEXT,\n via TEXT,\n enabled BOOLEAN NOT NULL DEFAULT TRUE,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_notification_subscriptions_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_notification_subscriptions_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX notification_subscriptions_project_user_idx ON notification_subscriptions (project_id, user_id);\nCREATE TABLE IF NOT EXISTS insights (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n build_id VARCHAR(64),\n kind VARCHAR(32) NOT NULL,\n window_key VARCHAR(64),\n input_hash VARCHAR(64) NOT NULL,\n status VARCHAR(32) NOT NULL,\n profile TEXT NOT NULL,\n model TEXT NOT NULL,\n prompt_version TEXT NOT NULL,\n verdict TEXT,\n summary TEXT,\n result TEXT,\n error_code TEXT,\n created_at DATETIME(3) NOT NULL,\n started_at DATETIME(3),\n finished_at DATETIME(3),\n CONSTRAINT fk_insights_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_insights_build_id FOREIGN KEY (build_id) REFERENCES builds(id) ON DELETE CASCADE\n);\nCREATE INDEX insights_project_build_idx ON insights (project_id, build_id);\nCREATE INDEX insights_created_at_idx ON insights (created_at);\nCREATE UNIQUE INDEX insights_triage_unique_idx ON insights (project_id, build_id, kind, input_hash);\nCREATE UNIQUE INDEX insights_health_unique_idx ON insights (project_id, kind, window_key);\nCREATE TABLE IF NOT EXISTS ai_usage (\n id VARCHAR(64) PRIMARY KEY,\n insight_id TEXT,\n project_id VARCHAR(64) NOT NULL,\n profile TEXT NOT NULL,\n task TEXT NOT NULL,\n model TEXT NOT NULL,\n input_tokens INTEGER NOT NULL DEFAULT 0,\n output_tokens INTEGER NOT NULL DEFAULT 0,\n estimated TINYINT(1) NOT NULL DEFAULT false,\n images INTEGER NOT NULL DEFAULT 0,\n status VARCHAR(32) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_ai_usage_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX ai_usage_created_at_idx ON ai_usage (created_at);\nCREATE INDEX ai_usage_project_created_idx ON ai_usage (project_id, created_at);\nCREATE TABLE IF NOT EXISTS ai_budget_alerts (\n id VARCHAR(64) PRIMARY KEY,\n day TEXT NOT NULL,\n threshold INTEGER NOT NULL,\n created_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS user_invite_tokens (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n token_hash VARCHAR(128) NOT NULL UNIQUE,\n expires_at DATETIME(3) NOT NULL,\n used_at DATETIME(3),\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_user_invite_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS project_members (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n role VARCHAR(32) NOT NULL DEFAULT 'viewer',\n source VARCHAR(32) NOT NULL DEFAULT 'manual',\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_members_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n CONSTRAINT fk_project_members_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_members_project_user_idx ON project_members (project_id, user_id);\nCREATE TABLE IF NOT EXISTS project_group_mappings (\n id VARCHAR(64) PRIMARY KEY,\n project_id VARCHAR(64) NOT NULL,\n group_name VARCHAR(255) NOT NULL,\n role VARCHAR(32) NOT NULL DEFAULT 'viewer',\n created_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_project_group_mappings_project_id FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE UNIQUE INDEX project_group_mappings_project_group_idx ON project_group_mappings (project_id, group_name);\nCREATE TABLE IF NOT EXISTS content_refs (\n hash VARCHAR(128) PRIMARY KEY,\n ref_count INTEGER NOT NULL DEFAULT 1,\n last_seen_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS \\`user\\` (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT NOT NULL,\n email VARCHAR(255) NOT NULL UNIQUE,\n email_verified TINYINT(1) NOT NULL DEFAULT false,\n image TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE TABLE IF NOT EXISTS session (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n token VARCHAR(512) NOT NULL UNIQUE,\n expires_at DATETIME(3) NOT NULL,\n ip_address TEXT,\n user_agent TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_session_user_id FOREIGN KEY (user_id) REFERENCES \\`user\\`(id) ON DELETE CASCADE\n);\nCREATE INDEX session_token_idx ON session (token);\nCREATE INDEX session_user_id_idx ON session (user_id);\nCREATE TABLE IF NOT EXISTS account (\n id VARCHAR(64) PRIMARY KEY,\n user_id VARCHAR(64) NOT NULL,\n account_id TEXT NOT NULL,\n provider_id TEXT NOT NULL,\n access_token TEXT,\n refresh_token TEXT,\n id_token TEXT,\n access_token_expires_at DATETIME(3),\n refresh_token_expires_at DATETIME(3),\n scope TEXT,\n expires_at DATETIME(3),\n password TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL,\n CONSTRAINT fk_account_user_id FOREIGN KEY (user_id) REFERENCES \\`user\\`(id) ON DELETE CASCADE\n);\nCREATE INDEX account_user_id_idx ON account (user_id);\nCREATE TABLE IF NOT EXISTS verification (\n id VARCHAR(64) PRIMARY KEY,\n identifier VARCHAR(255) NOT NULL,\n value TEXT NOT NULL,\n expires_at DATETIME(3) NOT NULL,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3) NOT NULL\n);\nCREATE INDEX verification_identifier_idx ON verification (identifier);\nCREATE TABLE IF NOT EXISTS passkey (\n id VARCHAR(64) PRIMARY KEY,\n name TEXT,\n public_key TEXT NOT NULL,\n user_id VARCHAR(64) NOT NULL,\n credential_id VARCHAR(255) NOT NULL,\n counter INTEGER NOT NULL,\n device_type TEXT NOT NULL,\n backed_up TINYINT(1) NOT NULL DEFAULT false,\n transports TEXT,\n aaguid TEXT,\n created_at DATETIME(3) NOT NULL,\n updated_at DATETIME(3),\n CONSTRAINT fk_passkey_user_id FOREIGN KEY (user_id) REFERENCES \\`user\\`(id) ON DELETE CASCADE\n);\nCREATE INDEX passkey_user_id_idx ON passkey (user_id);\nCREATE INDEX passkey_credential_id_idx ON passkey (credential_id);\nCREATE TABLE IF NOT EXISTS \\`ssoProvider\\` (\n id VARCHAR(64) PRIMARY KEY,\n issuer TEXT NOT NULL,\n oidc_config TEXT,\n saml_config TEXT,\n user_id VARCHAR(64) NOT NULL,\n provider_id VARCHAR(64) NOT NULL UNIQUE,\n organization_id TEXT,\n domain VARCHAR(255) NOT NULL,\n CONSTRAINT fk_ssoProvider_user_id FOREIGN KEY (user_id) REFERENCES \\`user\\`(id) ON DELETE CASCADE\n);\nCREATE INDEX ssoprovider_domain_idx ON \\`ssoProvider\\` (domain);\n`;\n"],"mappings":";;;;;AACA,MAAa,MAAM"}
package/dist/index.mjs CHANGED
@@ -49,7 +49,7 @@ function createMysqlDatabase(options) {
49
49
  return createDrizzleMySqlAdapter(db, {
50
50
  metadata: {
51
51
  name: "MySQL",
52
- version: "0.8.0",
52
+ version: "0.9.0-next-d2cc082",
53
53
  description: "MySQL/MariaDB database adapter (mysql2 + Drizzle)",
54
54
  kind: "mysql",
55
55
  category: "database"
package/dist/migrate.mjs CHANGED
@@ -243,6 +243,11 @@ const COLUMN_MIGRATIONS = [
243
243
  column: "disabled",
244
244
  definition: "TINYINT(1) NOT NULL DEFAULT 0"
245
245
  },
246
+ {
247
+ table: "design_nodes",
248
+ column: "notified_version",
249
+ definition: "TEXT"
250
+ },
246
251
  {
247
252
  table: "notification_channels",
248
253
  column: "last_error",
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.mjs","names":[],"sources":["../src/migrate.ts"],"sourcesContent":["/**\n * Shared MySQL migrations for every `db-mysql` preset.\n *\n * MySQL 8 has no `ADD COLUMN IF NOT EXISTS`, no `CREATE INDEX IF NOT EXISTS`\n * and no `ALTER COLUMN ... DROP NOT NULL`. The DDL is split into statements,\n * missing columns/indexes are found in `information_schema`, and only a\n * duplicate-index error from a repeated DDL statement is ignored.\n */\nimport { DDL } from \"./ddl.ts\";\nimport { FOREIGN_KEYS, type ForeignKeyMigration } from \"./foreign-keys.ts\";\n\n/** Minimal row-query surface a migration runner needs. */\nexport type MigrationRunner = (sql: string) => Promise<unknown[]>;\n\ninterface ColumnMigration {\n table: string;\n column: string;\n definition: string;\n}\n\nconst COLUMN_MIGRATIONS: ColumnMigration[] = [\n { table: \"projects\", column: \"storybook_meta\", definition: \"TEXT\" },\n {\n table: \"projects\",\n column: \"execute_play\",\n definition: \"TINYINT(1) NOT NULL DEFAULT 0\",\n },\n {\n table: \"projects\",\n column: \"play_timeout_ms\",\n definition: \"INTEGER NOT NULL DEFAULT 10000\",\n },\n { table: \"projects\", column: \"run_a11y\", definition: \"TINYINT(1) NOT NULL DEFAULT 1\" },\n {\n table: \"projects\",\n column: \"browser\",\n definition: \"VARCHAR(64) NOT NULL DEFAULT 'chromium'\",\n },\n { table: \"projects\", column: \"viewports\", definition: \"TEXT\" },\n { table: \"projects\", column: \"browsers\", definition: \"TEXT\" },\n { table: \"projects\", column: \"modes_allowlist\", definition: \"TEXT\" },\n { table: \"projects\", column: \"automigrate\", definition: \"TINYINT(1) NOT NULL DEFAULT 0\" },\n { table: \"projects\", column: \"ai_profile\", definition: \"TEXT\" },\n {\n table: \"projects\",\n column: \"review_enabled\",\n definition: \"TINYINT(1) NOT NULL DEFAULT 1\",\n },\n { table: \"projects\", column: \"review_approvals\", definition: \"INT NOT NULL DEFAULT 1\" },\n { table: \"projects\", column: \"storybook_url_ttl_seconds\", definition: \"INT\" },\n { table: \"projects\", column: \"run_tests\", definition: \"TINYINT(1) NOT NULL DEFAULT 0\" },\n { table: \"snapshots\", column: \"infra_hash\", definition: \"TEXT\" },\n {\n table: \"snapshots\",\n column: \"inherited\",\n definition: \"TINYINT(1) NOT NULL DEFAULT 0\",\n },\n { table: \"snapshots\", column: \"baseline_id\", definition: \"VARCHAR(64)\" },\n { table: \"snapshots\", column: \"baseline_version\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"source_build_id\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"comparison_image_path\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"comparison_metadata\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"design_url\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"env_change\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"mode\", definition: \"VARCHAR(64)\" },\n {\n table: \"snapshots\",\n column: \"browser\",\n definition: \"VARCHAR(64) NOT NULL DEFAULT 'chromium'\",\n },\n { table: \"snapshots\", column: \"duration_ms\", definition: \"INT\" },\n { table: \"snapshots\", column: \"a11y_violations\", definition: \"TEXT\" },\n { table: \"baselines\", column: \"infra_hash\", definition: \"TEXT\" },\n { table: \"baselines\", column: \"fingerprint\", definition: \"TEXT\" },\n { table: \"baselines\", column: \"source_build_id\", definition: \"TEXT\" },\n { table: \"baselines\", column: \"mode\", definition: \"VARCHAR(64)\" },\n {\n table: \"baselines\",\n column: \"browser\",\n definition: \"VARCHAR(64) NOT NULL DEFAULT 'chromium'\",\n },\n {\n table: \"builds\",\n column: \"affected_only\",\n definition: \"TINYINT(1) NOT NULL DEFAULT 1\",\n },\n { table: \"builds\", column: \"baseline_sha\", definition: \"TEXT\" },\n { table: \"builds\", column: \"changed_files\", definition: \"TEXT\" },\n { table: \"builds\", column: \"affected_import_paths\", definition: \"TEXT\" },\n { table: \"builds\", column: \"inherited_count\", definition: \"INTEGER NOT NULL DEFAULT 0\" },\n { table: \"builds\", column: \"test_results\", definition: \"TEXT\" },\n { table: \"webhooks\", column: \"secret_encrypted\", definition: \"TEXT NOT NULL\" },\n { table: \"tokens\", column: \"user_id\", definition: \"VARCHAR(64) NULL\" },\n {\n table: \"project_members\",\n column: \"source\",\n definition: \"VARCHAR(32) NOT NULL DEFAULT 'manual'\",\n },\n { table: \"comments\", column: \"story_id\", definition: \"TEXT\" },\n // Auth columns the SQLite `users` table always had (access control: `disabled`).\n { table: \"users\", column: \"password_hash\", definition: \"TEXT\" },\n { table: \"users\", column: \"display_name_override\", definition: \"TEXT\" },\n {\n table: \"users\",\n column: \"auth_provider\",\n definition: \"VARCHAR(32) NOT NULL DEFAULT 'oidc'\",\n },\n { table: \"users\", column: \"disabled\", definition: \"TINYINT(1) NOT NULL DEFAULT 0\" },\n { table: \"notification_channels\", column: \"last_error\", definition: \"TEXT\" },\n { table: \"notification_channels\", column: \"last_error_at\", definition: \"DATETIME(3)\" },\n];\n\nconst IDENTITY_INDEXES = [\n {\n table: \"snapshots\",\n name: \"snapshots_build_story_mode_browser_idx\",\n sql: \"CREATE UNIQUE INDEX snapshots_build_story_mode_browser_idx ON snapshots (build_id, story_id, viewport_name, browser)\",\n },\n {\n table: \"baselines\",\n name: \"baselines_project_story_mode_browser_branch_idx\",\n sql: \"CREATE UNIQUE INDEX baselines_project_story_mode_browser_branch_idx ON baselines (project_id, story_id, viewport_name, browser, branch)\",\n },\n];\n\n/** Run the full migration set through any row-query runner. */\nexport async function runMigrations(run: MigrationRunner): Promise<void> {\n await runDdl(run);\n await ensureColumns(run);\n await migrateIndexes(run);\n await migrateLegacyColumns(run);\n await ensureForeignKeys(run);\n}\n\nasync function ensureColumns(run: MigrationRunner): Promise<void> {\n for (const migration of COLUMN_MIGRATIONS) {\n // oxlint-disable-next-line no-await-in-loop -- information_schema query then ALTER\n await ensureColumn(run, migration);\n }\n}\n\nasync function migrateIndexes(run: MigrationRunner): Promise<void> {\n await dropIndexIfExists(run, \"snapshots\", \"snapshots_build_story_viewport_idx\");\n await dropIndexIfExists(run, \"baselines\", \"baselines_project_story_viewport_branch_idx\");\n for (const index of IDENTITY_INDEXES) {\n // oxlint-disable-next-line no-await-in-loop -- index creation follows the legacy drops\n await ensureIndex(run, index.table, index.name, index.sql);\n }\n if (await indexIsUnique(run, \"builds\", \"builds_project_gitsha_idx\")) {\n await dropIndexIfExists(run, \"builds\", \"builds_project_gitsha_idx\");\n }\n await ensureIndex(\n run,\n \"builds\",\n \"builds_project_gitsha_idx\",\n \"CREATE INDEX builds_project_gitsha_idx ON builds (project_id, git_sha)\",\n );\n await ensureIndex(\n run,\n \"design_links\",\n \"design_links_project_import_path_idx\",\n \"CREATE UNIQUE INDEX design_links_project_import_path_idx ON design_links (project_id, import_path)\",\n );\n}\n\nasync function migrateLegacyColumns(run: MigrationRunner): Promise<void> {\n await dropColumnIfExists(run, \"webhooks\", \"secret\");\n await migrateCommentsTable(run);\n}\n\nasync function ensureForeignKeys(run: MigrationRunner): Promise<void> {\n for (const foreignKey of FOREIGN_KEYS) {\n // oxlint-disable-next-line no-await-in-loop -- each constraint needs its own check\n await ensureForeignKey(run, foreignKey);\n }\n}\n\nasync function ensureForeignKey(\n run: MigrationRunner,\n foreignKey: ForeignKeyMigration,\n): Promise<void> {\n if (await hasForeignKey(run, foreignKey)) {\n return;\n }\n await deleteOrphans(run, foreignKey);\n const table = quote(foreignKey.table);\n const column = quote(foreignKey.column);\n const parent = quote(foreignKey.parent);\n const parentColumn = quote(foreignKey.parentColumn);\n await run(\n `ALTER TABLE ${table} ADD CONSTRAINT ${foreignKey.name} FOREIGN KEY (${column}) REFERENCES ${parent}(${parentColumn}) ON DELETE CASCADE`,\n );\n}\n\nasync function hasForeignKey(\n run: MigrationRunner,\n foreignKey: ForeignKeyMigration,\n): Promise<boolean> {\n const rows = await run(\n `SELECT 1 FROM information_schema.key_column_usage WHERE constraint_schema = DATABASE() AND table_name = '${foreignKey.table}' AND column_name = '${foreignKey.column}' AND referenced_table_name = '${foreignKey.parent}' AND referenced_column_name = '${foreignKey.parentColumn}' LIMIT 1`,\n );\n return rows.length > 0;\n}\n\nasync function deleteOrphans(run: MigrationRunner, foreignKey: ForeignKeyMigration): Promise<void> {\n const table = quote(foreignKey.table);\n const column = quote(foreignKey.column);\n const parent = quote(foreignKey.parent);\n const parentColumn = quote(foreignKey.parentColumn);\n await run(\n `DELETE FROM ${table} WHERE ${column} IS NOT NULL AND NOT EXISTS (SELECT 1 FROM ${parent} WHERE ${parent}.${parentColumn} = ${table}.${column})`,\n );\n}\n\nfunction quote(identifier: string): string {\n return `\\`${identifier}\\``;\n}\n\nasync function runDdl(run: MigrationRunner): Promise<void> {\n for (const statement of splitStatements(DDL)) {\n try {\n // oxlint-disable-next-line no-await-in-loop -- DDL order matters\n await run(statement);\n } catch (error) {\n if (!isDuplicateIndexError(error)) {\n throw error;\n }\n }\n }\n}\n\nfunction splitStatements(ddl: string): string[] {\n return ddl\n .split(\";\")\n .map((statement) => statement.trim())\n .filter((statement) => statement.length > 0);\n}\n\nfunction isDuplicateIndexError(error: unknown): boolean {\n const code = (error as { code?: string; errno?: number }).code;\n const errno = (error as { errno?: number }).errno;\n return code === \"ER_DUP_KEYNAME\" || errno === 1061;\n}\n\nasync function ensureColumn(run: MigrationRunner, migration: ColumnMigration): Promise<void> {\n if (await hasColumn(run, migration.table, migration.column)) {\n return;\n }\n try {\n await run(\n `ALTER TABLE ${migration.table} ADD COLUMN ${migration.column} ${migration.definition}`,\n );\n } catch (error) {\n // Another instance booting at the same time may have added it between the check and the ALTER.\n if (!isDuplicateColumnError(error)) {\n throw error;\n }\n }\n}\n\nfunction isDuplicateColumnError(error: unknown): boolean {\n const code = (error as { code?: string }).code;\n const errno = (error as { errno?: number }).errno;\n return code === \"ER_DUP_FIELDNAME\" || errno === 1060;\n}\n\nasync function hasColumn(run: MigrationRunner, table: string, column: string): Promise<boolean> {\n const rows = await run(\n `SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = '${table}' AND column_name = '${column}' LIMIT 1`,\n );\n return rows.length > 0;\n}\n\nasync function ensureIndex(\n run: MigrationRunner,\n table: string,\n name: string,\n sql: string,\n): Promise<void> {\n if (await hasIndex(run, table, name)) {\n return;\n }\n await run(sql);\n}\n\nasync function hasIndex(run: MigrationRunner, table: string, name: string): Promise<boolean> {\n const rows = await run(\n `SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = '${table}' AND index_name = '${name}' LIMIT 1`,\n );\n return rows.length > 0;\n}\n\nasync function indexIsUnique(run: MigrationRunner, table: string, name: string): Promise<boolean> {\n const rows = await run(\n `SELECT NON_UNIQUE AS non_unique FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = '${table}' AND index_name = '${name}' LIMIT 1`,\n );\n const nonUnique = (rows[0] as { non_unique?: number | string } | undefined)?.non_unique;\n return nonUnique !== undefined && Number(nonUnique) === 0;\n}\n\nasync function dropIndexIfExists(run: MigrationRunner, table: string, name: string): Promise<void> {\n if (await hasIndex(run, table, name)) {\n await run(`ALTER TABLE ${table} DROP INDEX ${name}`);\n }\n}\n\nasync function dropColumnIfExists(\n run: MigrationRunner,\n table: string,\n column: string,\n): Promise<void> {\n if (await hasColumn(run, table, column)) {\n await run(`ALTER TABLE ${table} DROP COLUMN ${column}`);\n }\n}\n\nasync function migrateCommentsTable(run: MigrationRunner): Promise<void> {\n const rows = await run(\n \"SELECT IS_NULLABLE AS is_nullable FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'comments' AND column_name = 'user_id' LIMIT 1\",\n );\n const isNullable = (rows[0] as { is_nullable?: string } | undefined)?.is_nullable;\n if (isNullable !== \"NO\") {\n return;\n }\n await run(\"ALTER TABLE comments MODIFY COLUMN user_id VARCHAR(64) NULL\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"migrate.mjs","names":[],"sources":["../src/migrate.ts"],"sourcesContent":["/**\n * Shared MySQL migrations for every `db-mysql` preset.\n *\n * MySQL 8 has no `ADD COLUMN IF NOT EXISTS`, no `CREATE INDEX IF NOT EXISTS`\n * and no `ALTER COLUMN ... DROP NOT NULL`. The DDL is split into statements,\n * missing columns/indexes are found in `information_schema`, and only a\n * duplicate-index error from a repeated DDL statement is ignored.\n */\nimport { DDL } from \"./ddl.ts\";\nimport { FOREIGN_KEYS, type ForeignKeyMigration } from \"./foreign-keys.ts\";\n\n/** Minimal row-query surface a migration runner needs. */\nexport type MigrationRunner = (sql: string) => Promise<unknown[]>;\n\ninterface ColumnMigration {\n table: string;\n column: string;\n definition: string;\n}\n\nconst COLUMN_MIGRATIONS: ColumnMigration[] = [\n { table: \"projects\", column: \"storybook_meta\", definition: \"TEXT\" },\n {\n table: \"projects\",\n column: \"execute_play\",\n definition: \"TINYINT(1) NOT NULL DEFAULT 0\",\n },\n {\n table: \"projects\",\n column: \"play_timeout_ms\",\n definition: \"INTEGER NOT NULL DEFAULT 10000\",\n },\n { table: \"projects\", column: \"run_a11y\", definition: \"TINYINT(1) NOT NULL DEFAULT 1\" },\n {\n table: \"projects\",\n column: \"browser\",\n definition: \"VARCHAR(64) NOT NULL DEFAULT 'chromium'\",\n },\n { table: \"projects\", column: \"viewports\", definition: \"TEXT\" },\n { table: \"projects\", column: \"browsers\", definition: \"TEXT\" },\n { table: \"projects\", column: \"modes_allowlist\", definition: \"TEXT\" },\n { table: \"projects\", column: \"automigrate\", definition: \"TINYINT(1) NOT NULL DEFAULT 0\" },\n { table: \"projects\", column: \"ai_profile\", definition: \"TEXT\" },\n {\n table: \"projects\",\n column: \"review_enabled\",\n definition: \"TINYINT(1) NOT NULL DEFAULT 1\",\n },\n { table: \"projects\", column: \"review_approvals\", definition: \"INT NOT NULL DEFAULT 1\" },\n { table: \"projects\", column: \"storybook_url_ttl_seconds\", definition: \"INT\" },\n { table: \"projects\", column: \"run_tests\", definition: \"TINYINT(1) NOT NULL DEFAULT 0\" },\n { table: \"snapshots\", column: \"infra_hash\", definition: \"TEXT\" },\n {\n table: \"snapshots\",\n column: \"inherited\",\n definition: \"TINYINT(1) NOT NULL DEFAULT 0\",\n },\n { table: \"snapshots\", column: \"baseline_id\", definition: \"VARCHAR(64)\" },\n { table: \"snapshots\", column: \"baseline_version\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"source_build_id\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"comparison_image_path\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"comparison_metadata\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"design_url\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"env_change\", definition: \"TEXT\" },\n { table: \"snapshots\", column: \"mode\", definition: \"VARCHAR(64)\" },\n {\n table: \"snapshots\",\n column: \"browser\",\n definition: \"VARCHAR(64) NOT NULL DEFAULT 'chromium'\",\n },\n { table: \"snapshots\", column: \"duration_ms\", definition: \"INT\" },\n { table: \"snapshots\", column: \"a11y_violations\", definition: \"TEXT\" },\n { table: \"baselines\", column: \"infra_hash\", definition: \"TEXT\" },\n { table: \"baselines\", column: \"fingerprint\", definition: \"TEXT\" },\n { table: \"baselines\", column: \"source_build_id\", definition: \"TEXT\" },\n { table: \"baselines\", column: \"mode\", definition: \"VARCHAR(64)\" },\n {\n table: \"baselines\",\n column: \"browser\",\n definition: \"VARCHAR(64) NOT NULL DEFAULT 'chromium'\",\n },\n {\n table: \"builds\",\n column: \"affected_only\",\n definition: \"TINYINT(1) NOT NULL DEFAULT 1\",\n },\n { table: \"builds\", column: \"baseline_sha\", definition: \"TEXT\" },\n { table: \"builds\", column: \"changed_files\", definition: \"TEXT\" },\n { table: \"builds\", column: \"affected_import_paths\", definition: \"TEXT\" },\n { table: \"builds\", column: \"inherited_count\", definition: \"INTEGER NOT NULL DEFAULT 0\" },\n { table: \"builds\", column: \"test_results\", definition: \"TEXT\" },\n { table: \"webhooks\", column: \"secret_encrypted\", definition: \"TEXT NOT NULL\" },\n { table: \"tokens\", column: \"user_id\", definition: \"VARCHAR(64) NULL\" },\n {\n table: \"project_members\",\n column: \"source\",\n definition: \"VARCHAR(32) NOT NULL DEFAULT 'manual'\",\n },\n { table: \"comments\", column: \"story_id\", definition: \"TEXT\" },\n // Auth columns the SQLite `users` table always had (access control: `disabled`).\n { table: \"users\", column: \"password_hash\", definition: \"TEXT\" },\n { table: \"users\", column: \"display_name_override\", definition: \"TEXT\" },\n {\n table: \"users\",\n column: \"auth_provider\",\n definition: \"VARCHAR(32) NOT NULL DEFAULT 'oidc'\",\n },\n { table: \"users\", column: \"disabled\", definition: \"TINYINT(1) NOT NULL DEFAULT 0\" },\n { table: \"design_nodes\", column: \"notified_version\", definition: \"TEXT\" },\n { table: \"notification_channels\", column: \"last_error\", definition: \"TEXT\" },\n { table: \"notification_channels\", column: \"last_error_at\", definition: \"DATETIME(3)\" },\n];\n\nconst IDENTITY_INDEXES = [\n {\n table: \"snapshots\",\n name: \"snapshots_build_story_mode_browser_idx\",\n sql: \"CREATE UNIQUE INDEX snapshots_build_story_mode_browser_idx ON snapshots (build_id, story_id, viewport_name, browser)\",\n },\n {\n table: \"baselines\",\n name: \"baselines_project_story_mode_browser_branch_idx\",\n sql: \"CREATE UNIQUE INDEX baselines_project_story_mode_browser_branch_idx ON baselines (project_id, story_id, viewport_name, browser, branch)\",\n },\n];\n\n/** Run the full migration set through any row-query runner. */\nexport async function runMigrations(run: MigrationRunner): Promise<void> {\n await runDdl(run);\n await ensureColumns(run);\n await migrateIndexes(run);\n await migrateLegacyColumns(run);\n await ensureForeignKeys(run);\n}\n\nasync function ensureColumns(run: MigrationRunner): Promise<void> {\n for (const migration of COLUMN_MIGRATIONS) {\n // oxlint-disable-next-line no-await-in-loop -- information_schema query then ALTER\n await ensureColumn(run, migration);\n }\n}\n\nasync function migrateIndexes(run: MigrationRunner): Promise<void> {\n await dropIndexIfExists(run, \"snapshots\", \"snapshots_build_story_viewport_idx\");\n await dropIndexIfExists(run, \"baselines\", \"baselines_project_story_viewport_branch_idx\");\n for (const index of IDENTITY_INDEXES) {\n // oxlint-disable-next-line no-await-in-loop -- index creation follows the legacy drops\n await ensureIndex(run, index.table, index.name, index.sql);\n }\n if (await indexIsUnique(run, \"builds\", \"builds_project_gitsha_idx\")) {\n await dropIndexIfExists(run, \"builds\", \"builds_project_gitsha_idx\");\n }\n await ensureIndex(\n run,\n \"builds\",\n \"builds_project_gitsha_idx\",\n \"CREATE INDEX builds_project_gitsha_idx ON builds (project_id, git_sha)\",\n );\n await ensureIndex(\n run,\n \"design_links\",\n \"design_links_project_import_path_idx\",\n \"CREATE UNIQUE INDEX design_links_project_import_path_idx ON design_links (project_id, import_path)\",\n );\n}\n\nasync function migrateLegacyColumns(run: MigrationRunner): Promise<void> {\n await dropColumnIfExists(run, \"webhooks\", \"secret\");\n await migrateCommentsTable(run);\n}\n\nasync function ensureForeignKeys(run: MigrationRunner): Promise<void> {\n for (const foreignKey of FOREIGN_KEYS) {\n // oxlint-disable-next-line no-await-in-loop -- each constraint needs its own check\n await ensureForeignKey(run, foreignKey);\n }\n}\n\nasync function ensureForeignKey(\n run: MigrationRunner,\n foreignKey: ForeignKeyMigration,\n): Promise<void> {\n if (await hasForeignKey(run, foreignKey)) {\n return;\n }\n await deleteOrphans(run, foreignKey);\n const table = quote(foreignKey.table);\n const column = quote(foreignKey.column);\n const parent = quote(foreignKey.parent);\n const parentColumn = quote(foreignKey.parentColumn);\n await run(\n `ALTER TABLE ${table} ADD CONSTRAINT ${foreignKey.name} FOREIGN KEY (${column}) REFERENCES ${parent}(${parentColumn}) ON DELETE CASCADE`,\n );\n}\n\nasync function hasForeignKey(\n run: MigrationRunner,\n foreignKey: ForeignKeyMigration,\n): Promise<boolean> {\n const rows = await run(\n `SELECT 1 FROM information_schema.key_column_usage WHERE constraint_schema = DATABASE() AND table_name = '${foreignKey.table}' AND column_name = '${foreignKey.column}' AND referenced_table_name = '${foreignKey.parent}' AND referenced_column_name = '${foreignKey.parentColumn}' LIMIT 1`,\n );\n return rows.length > 0;\n}\n\nasync function deleteOrphans(run: MigrationRunner, foreignKey: ForeignKeyMigration): Promise<void> {\n const table = quote(foreignKey.table);\n const column = quote(foreignKey.column);\n const parent = quote(foreignKey.parent);\n const parentColumn = quote(foreignKey.parentColumn);\n await run(\n `DELETE FROM ${table} WHERE ${column} IS NOT NULL AND NOT EXISTS (SELECT 1 FROM ${parent} WHERE ${parent}.${parentColumn} = ${table}.${column})`,\n );\n}\n\nfunction quote(identifier: string): string {\n return `\\`${identifier}\\``;\n}\n\nasync function runDdl(run: MigrationRunner): Promise<void> {\n for (const statement of splitStatements(DDL)) {\n try {\n // oxlint-disable-next-line no-await-in-loop -- DDL order matters\n await run(statement);\n } catch (error) {\n if (!isDuplicateIndexError(error)) {\n throw error;\n }\n }\n }\n}\n\nfunction splitStatements(ddl: string): string[] {\n return ddl\n .split(\";\")\n .map((statement) => statement.trim())\n .filter((statement) => statement.length > 0);\n}\n\nfunction isDuplicateIndexError(error: unknown): boolean {\n const code = (error as { code?: string; errno?: number }).code;\n const errno = (error as { errno?: number }).errno;\n return code === \"ER_DUP_KEYNAME\" || errno === 1061;\n}\n\nasync function ensureColumn(run: MigrationRunner, migration: ColumnMigration): Promise<void> {\n if (await hasColumn(run, migration.table, migration.column)) {\n return;\n }\n try {\n await run(\n `ALTER TABLE ${migration.table} ADD COLUMN ${migration.column} ${migration.definition}`,\n );\n } catch (error) {\n // Another instance booting at the same time may have added it between the check and the ALTER.\n if (!isDuplicateColumnError(error)) {\n throw error;\n }\n }\n}\n\nfunction isDuplicateColumnError(error: unknown): boolean {\n const code = (error as { code?: string }).code;\n const errno = (error as { errno?: number }).errno;\n return code === \"ER_DUP_FIELDNAME\" || errno === 1060;\n}\n\nasync function hasColumn(run: MigrationRunner, table: string, column: string): Promise<boolean> {\n const rows = await run(\n `SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = '${table}' AND column_name = '${column}' LIMIT 1`,\n );\n return rows.length > 0;\n}\n\nasync function ensureIndex(\n run: MigrationRunner,\n table: string,\n name: string,\n sql: string,\n): Promise<void> {\n if (await hasIndex(run, table, name)) {\n return;\n }\n await run(sql);\n}\n\nasync function hasIndex(run: MigrationRunner, table: string, name: string): Promise<boolean> {\n const rows = await run(\n `SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = '${table}' AND index_name = '${name}' LIMIT 1`,\n );\n return rows.length > 0;\n}\n\nasync function indexIsUnique(run: MigrationRunner, table: string, name: string): Promise<boolean> {\n const rows = await run(\n `SELECT NON_UNIQUE AS non_unique FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = '${table}' AND index_name = '${name}' LIMIT 1`,\n );\n const nonUnique = (rows[0] as { non_unique?: number | string } | undefined)?.non_unique;\n return nonUnique !== undefined && Number(nonUnique) === 0;\n}\n\nasync function dropIndexIfExists(run: MigrationRunner, table: string, name: string): Promise<void> {\n if (await hasIndex(run, table, name)) {\n await run(`ALTER TABLE ${table} DROP INDEX ${name}`);\n }\n}\n\nasync function dropColumnIfExists(\n run: MigrationRunner,\n table: string,\n column: string,\n): Promise<void> {\n if (await hasColumn(run, table, column)) {\n await run(`ALTER TABLE ${table} DROP COLUMN ${column}`);\n }\n}\n\nasync function migrateCommentsTable(run: MigrationRunner): Promise<void> {\n const rows = await run(\n \"SELECT IS_NULLABLE AS is_nullable FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'comments' AND column_name = 'user_id' LIMIT 1\",\n );\n const isNullable = (rows[0] as { is_nullable?: string } | undefined)?.is_nullable;\n if (isNullable !== \"NO\") {\n return;\n }\n await run(\"ALTER TABLE comments MODIFY COLUMN user_id VARCHAR(64) NULL\");\n}\n"],"mappings":"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"}
@@ -480,6 +480,23 @@ declare const designNodes: import("drizzle-orm/mysql-core/table.js").MySqlTableW
480
480
  identity: undefined;
481
481
  generated: undefined;
482
482
  }, {}, {}>;
483
+ notifiedVersion: import("drizzle-orm/mysql-core/index.js").MySqlColumn<{
484
+ name: "notified_version";
485
+ tableName: "design_nodes";
486
+ dataType: "string";
487
+ columnType: "MySqlText";
488
+ data: string;
489
+ driverParam: string;
490
+ notNull: false;
491
+ hasDefault: false;
492
+ isPrimaryKey: false;
493
+ isAutoincrement: false;
494
+ hasRuntimeDefault: false;
495
+ enumValues: [string, ...string[]];
496
+ baseColumn: never;
497
+ identity: undefined;
498
+ generated: undefined;
499
+ }, {}, {}>;
483
500
  fetchedAt: import("drizzle-orm/mysql-core/index.js").MySqlColumn<{
484
501
  name: "fetched_at";
485
502
  tableName: "design_nodes";
@@ -579,6 +596,7 @@ interface DesignNode {
579
596
  renderPath: string | null;
580
597
  /** File `version` the cached render was taken at. */
581
598
  renderVersion: string | null;
599
+ notifiedVersion: string | null;
582
600
  fetchedAt: string;
583
601
  createdAt: string;
584
602
  updatedAt: string;
@@ -55,6 +55,7 @@ const designNodes = mysqlTable("design_nodes", {
55
55
  state: text("state").notNull().default("ok"),
56
56
  renderPath: text("render_path"),
57
57
  renderVersion: text("render_version"),
58
+ notifiedVersion: text("notified_version"),
58
59
  fetchedAt: datetime("fetched_at", {
59
60
  mode: "string",
60
61
  fsp: 3
@@ -1 +1 @@
1
- {"version":3,"file":"design.mjs","names":[],"sources":["../../src/schema/design.ts"],"sourcesContent":["import { index, mysqlTable, text, uniqueIndex } from \"drizzle-orm/mysql-core\";\nimport { datetime } from \"./datetime.ts\";\nimport { projects } from \"./project.ts\";\n\n/** Narrow `design_links` table definition. */\nexport const designLinks = mysqlTable(\n \"design_links\",\n {\n id: text(\"id\").primaryKey(),\n projectId: text(\"project_id\")\n .notNull()\n .references(() => projects.id, { onDelete: \"cascade\" }),\n importPath: text(\"import_path\"),\n label: text(\"label\"),\n url: text(\"url\").notNull(),\n createdAt: datetime(\"created_at\", { mode: \"string\", fsp: 3 }).notNull(),\n updatedAt: datetime(\"updated_at\", { mode: \"string\", fsp: 3 }).notNull(),\n },\n (t) => [\n index(\"design_links_project_id_idx\").on(t.projectId),\n // One mapping per story file; project-level links (null import_path) never collide.\n uniqueIndex(\"design_links_project_import_path_idx\").on(t.projectId, t.importPath),\n ],\n);\n\n/** Narrow `design_credentials` table definition: the project-wide design-provider token. */\nexport const designCredentials = mysqlTable(\n \"design_credentials\",\n {\n id: text(\"id\").primaryKey(),\n projectId: text(\"project_id\")\n .notNull()\n .references(() => projects.id, { onDelete: \"cascade\" }),\n provider: text(\"provider\").notNull(),\n tokenEncrypted: text(\"token_encrypted\").notNull(),\n status: text(\"status\").notNull().default(\"unknown\"),\n checkedAt: datetime(\"checked_at\", { mode: \"string\", fsp: 3 }),\n createdAt: datetime(\"created_at\", { mode: \"string\", fsp: 3 }).notNull(),\n updatedAt: datetime(\"updated_at\", { mode: \"string\", fsp: 3 }).notNull(),\n },\n (t) => [uniqueIndex(\"design_credentials_project_provider_idx\").on(t.projectId, t.provider)],\n);\n\n/** Narrow `design_nodes` table definition (design metadata + render cache). */\nexport const designNodes = mysqlTable(\n \"design_nodes\",\n {\n id: text(\"id\").primaryKey(),\n projectId: text(\"project_id\")\n .notNull()\n .references(() => projects.id, { onDelete: \"cascade\" }),\n provider: text(\"provider\").notNull(),\n viewerId: text(\"viewer_id\").notNull().default(\"\"),\n fileKey: text(\"file_key\").notNull(),\n nodeId: text(\"node_id\").notNull().default(\"\"),\n name: text(\"name\"),\n version: text(\"version\"),\n lastModified: text(\"last_modified\"),\n state: text(\"state\").notNull().default(\"ok\"),\n renderPath: text(\"render_path\"),\n renderVersion: text(\"render_version\"),\n fetchedAt: datetime(\"fetched_at\", { mode: \"string\", fsp: 3 }).notNull(),\n createdAt: datetime(\"created_at\", { mode: \"string\", fsp: 3 }).notNull(),\n updatedAt: datetime(\"updated_at\", { mode: \"string\", fsp: 3 }).notNull(),\n },\n (t) => [\n uniqueIndex(\"design_nodes_project_file_node_idx\").on(\n t.projectId,\n t.provider,\n t.viewerId,\n t.fileKey,\n t.nodeId,\n ),\n ],\n);\n\n/** A design link: a project-level file link (`importPath` null) or a component mapping override. */\nexport interface DesignLink {\n id: string;\n projectId: string;\n /** Story file the URL is mapped to; null for a project-level design file link. */\n importPath: string | null;\n /** Display label of a project-level link. */\n label: string | null;\n url: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/** The project-wide token of a design provider (an admin pastes it; encrypted at rest). */\nexport interface DesignCredential {\n id: string;\n projectId: string;\n /** Provider `metadata.kind`, e.g. `figma`. */\n provider: string;\n tokenEncrypted: string;\n /** Last API outcome: `unknown` | `ok` | `unauthorized` | `forbidden`. */\n status: string;\n checkedAt: string | null;\n /** When the credential was set or replaced; drives the rotation clock. */\n createdAt: string;\n updatedAt: string;\n}\n\n/** Cached design file/node metadata, keyed by project, provider, viewer, file key and node id. */\nexport interface DesignNode {\n id: string;\n projectId: string;\n provider: string;\n /** Whose access fetched the entry: `\"\"` for the project credential, else a user id. */\n viewerId: string;\n fileKey: string;\n /** Provider node id; empty string for a whole-file link. */\n nodeId: string;\n name: string | null;\n version: string | null;\n lastModified: string | null;\n /** `ok` | `deleted` | `unauthorized` | `forbidden`. */\n state: string;\n /** Storage path of the cached PNG render (node links only). */\n renderPath: string | null;\n /** File `version` the cached render was taken at. */\n renderVersion: string | null;\n fetchedAt: string;\n createdAt: string;\n updatedAt: string;\n}\n"],"mappings":";;;;;;;;AAKA,MAAa,cAAc,WACzB,gBACA;CACE,IAAI,KAAK,IAAI,CAAC,CAAC,WAAW;CAC1B,WAAW,KAAK,YAAY,CAAC,CAC1B,QAAQ,CAAC,CACT,iBAAiB,SAAS,IAAI,EAAE,UAAU,UAAU,CAAC;CACxD,YAAY,KAAK,aAAa;CAC9B,OAAO,KAAK,OAAO;CACnB,KAAK,KAAK,KAAK,CAAC,CAAC,QAAQ;CACzB,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;CACtE,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;AACxE,IACC,MAAM,CACL,MAAM,6BAA6B,CAAC,CAAC,GAAG,EAAE,SAAS,GAEnD,YAAY,sCAAsC,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,UAAU,CAClF,CACF;;AAGA,MAAa,oBAAoB,WAC/B,sBACA;CACE,IAAI,KAAK,IAAI,CAAC,CAAC,WAAW;CAC1B,WAAW,KAAK,YAAY,CAAC,CAC1B,QAAQ,CAAC,CACT,iBAAiB,SAAS,IAAI,EAAE,UAAU,UAAU,CAAC;CACxD,UAAU,KAAK,UAAU,CAAC,CAAC,QAAQ;CACnC,gBAAgB,KAAK,iBAAiB,CAAC,CAAC,QAAQ;CAChD,QAAQ,KAAK,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,SAAS;CAClD,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC;CAC5D,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;CACtE,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;AACxE,IACC,MAAM,CAAC,YAAY,yCAAyC,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,CAAC,CAC5F;;AAGA,MAAa,cAAc,WACzB,gBACA;CACE,IAAI,KAAK,IAAI,CAAC,CAAC,WAAW;CAC1B,WAAW,KAAK,YAAY,CAAC,CAC1B,QAAQ,CAAC,CACT,iBAAiB,SAAS,IAAI,EAAE,UAAU,UAAU,CAAC;CACxD,UAAU,KAAK,UAAU,CAAC,CAAC,QAAQ;CACnC,UAAU,KAAK,WAAW,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE;CAChD,SAAS,KAAK,UAAU,CAAC,CAAC,QAAQ;CAClC,QAAQ,KAAK,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE;CAC5C,MAAM,KAAK,MAAM;CACjB,SAAS,KAAK,SAAS;CACvB,cAAc,KAAK,eAAe;CAClC,OAAO,KAAK,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,IAAI;CAC3C,YAAY,KAAK,aAAa;CAC9B,eAAe,KAAK,gBAAgB;CACpC,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;CACtE,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;CACtE,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;AACxE,IACC,MAAM,CACL,YAAY,oCAAoC,CAAC,CAAC,GAChD,EAAE,WACF,EAAE,UACF,EAAE,UACF,EAAE,SACF,EAAE,MACJ,CACF,CACF"}
1
+ {"version":3,"file":"design.mjs","names":[],"sources":["../../src/schema/design.ts"],"sourcesContent":["import { index, mysqlTable, text, uniqueIndex } from \"drizzle-orm/mysql-core\";\nimport { datetime } from \"./datetime.ts\";\nimport { projects } from \"./project.ts\";\n\n/** Narrow `design_links` table definition. */\nexport const designLinks = mysqlTable(\n \"design_links\",\n {\n id: text(\"id\").primaryKey(),\n projectId: text(\"project_id\")\n .notNull()\n .references(() => projects.id, { onDelete: \"cascade\" }),\n importPath: text(\"import_path\"),\n label: text(\"label\"),\n url: text(\"url\").notNull(),\n createdAt: datetime(\"created_at\", { mode: \"string\", fsp: 3 }).notNull(),\n updatedAt: datetime(\"updated_at\", { mode: \"string\", fsp: 3 }).notNull(),\n },\n (t) => [\n index(\"design_links_project_id_idx\").on(t.projectId),\n // One mapping per story file; project-level links (null import_path) never collide.\n uniqueIndex(\"design_links_project_import_path_idx\").on(t.projectId, t.importPath),\n ],\n);\n\n/** Narrow `design_credentials` table definition: the project-wide design-provider token. */\nexport const designCredentials = mysqlTable(\n \"design_credentials\",\n {\n id: text(\"id\").primaryKey(),\n projectId: text(\"project_id\")\n .notNull()\n .references(() => projects.id, { onDelete: \"cascade\" }),\n provider: text(\"provider\").notNull(),\n tokenEncrypted: text(\"token_encrypted\").notNull(),\n status: text(\"status\").notNull().default(\"unknown\"),\n checkedAt: datetime(\"checked_at\", { mode: \"string\", fsp: 3 }),\n createdAt: datetime(\"created_at\", { mode: \"string\", fsp: 3 }).notNull(),\n updatedAt: datetime(\"updated_at\", { mode: \"string\", fsp: 3 }).notNull(),\n },\n (t) => [uniqueIndex(\"design_credentials_project_provider_idx\").on(t.projectId, t.provider)],\n);\n\n/** Narrow `design_nodes` table definition (design metadata + render cache). */\nexport const designNodes = mysqlTable(\n \"design_nodes\",\n {\n id: text(\"id\").primaryKey(),\n projectId: text(\"project_id\")\n .notNull()\n .references(() => projects.id, { onDelete: \"cascade\" }),\n provider: text(\"provider\").notNull(),\n viewerId: text(\"viewer_id\").notNull().default(\"\"),\n fileKey: text(\"file_key\").notNull(),\n nodeId: text(\"node_id\").notNull().default(\"\"),\n name: text(\"name\"),\n version: text(\"version\"),\n lastModified: text(\"last_modified\"),\n state: text(\"state\").notNull().default(\"ok\"),\n renderPath: text(\"render_path\"),\n renderVersion: text(\"render_version\"),\n notifiedVersion: text(\"notified_version\"),\n fetchedAt: datetime(\"fetched_at\", { mode: \"string\", fsp: 3 }).notNull(),\n createdAt: datetime(\"created_at\", { mode: \"string\", fsp: 3 }).notNull(),\n updatedAt: datetime(\"updated_at\", { mode: \"string\", fsp: 3 }).notNull(),\n },\n (t) => [\n uniqueIndex(\"design_nodes_project_file_node_idx\").on(\n t.projectId,\n t.provider,\n t.viewerId,\n t.fileKey,\n t.nodeId,\n ),\n ],\n);\n\n/** A design link: a project-level file link (`importPath` null) or a component mapping override. */\nexport interface DesignLink {\n id: string;\n projectId: string;\n /** Story file the URL is mapped to; null for a project-level design file link. */\n importPath: string | null;\n /** Display label of a project-level link. */\n label: string | null;\n url: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/** The project-wide token of a design provider (an admin pastes it; encrypted at rest). */\nexport interface DesignCredential {\n id: string;\n projectId: string;\n /** Provider `metadata.kind`, e.g. `figma`. */\n provider: string;\n tokenEncrypted: string;\n /** Last API outcome: `unknown` | `ok` | `unauthorized` | `forbidden`. */\n status: string;\n checkedAt: string | null;\n /** When the credential was set or replaced; drives the rotation clock. */\n createdAt: string;\n updatedAt: string;\n}\n\n/** Cached design file/node metadata, keyed by project, provider, viewer, file key and node id. */\nexport interface DesignNode {\n id: string;\n projectId: string;\n provider: string;\n /** Whose access fetched the entry: `\"\"` for the project credential, else a user id. */\n viewerId: string;\n fileKey: string;\n /** Provider node id; empty string for a whole-file link. */\n nodeId: string;\n name: string | null;\n version: string | null;\n lastModified: string | null;\n /** `ok` | `deleted` | `unauthorized` | `forbidden`. */\n state: string;\n /** Storage path of the cached PNG render (node links only). */\n renderPath: string | null;\n /** File `version` the cached render was taken at. */\n renderVersion: string | null;\n notifiedVersion: string | null;\n fetchedAt: string;\n createdAt: string;\n updatedAt: string;\n}\n"],"mappings":";;;;;;;;AAKA,MAAa,cAAc,WACzB,gBACA;CACE,IAAI,KAAK,IAAI,CAAC,CAAC,WAAW;CAC1B,WAAW,KAAK,YAAY,CAAC,CAC1B,QAAQ,CAAC,CACT,iBAAiB,SAAS,IAAI,EAAE,UAAU,UAAU,CAAC;CACxD,YAAY,KAAK,aAAa;CAC9B,OAAO,KAAK,OAAO;CACnB,KAAK,KAAK,KAAK,CAAC,CAAC,QAAQ;CACzB,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;CACtE,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;AACxE,IACC,MAAM,CACL,MAAM,6BAA6B,CAAC,CAAC,GAAG,EAAE,SAAS,GAEnD,YAAY,sCAAsC,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,UAAU,CAClF,CACF;;AAGA,MAAa,oBAAoB,WAC/B,sBACA;CACE,IAAI,KAAK,IAAI,CAAC,CAAC,WAAW;CAC1B,WAAW,KAAK,YAAY,CAAC,CAC1B,QAAQ,CAAC,CACT,iBAAiB,SAAS,IAAI,EAAE,UAAU,UAAU,CAAC;CACxD,UAAU,KAAK,UAAU,CAAC,CAAC,QAAQ;CACnC,gBAAgB,KAAK,iBAAiB,CAAC,CAAC,QAAQ;CAChD,QAAQ,KAAK,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,SAAS;CAClD,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC;CAC5D,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;CACtE,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;AACxE,IACC,MAAM,CAAC,YAAY,yCAAyC,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,CAAC,CAC5F;;AAGA,MAAa,cAAc,WACzB,gBACA;CACE,IAAI,KAAK,IAAI,CAAC,CAAC,WAAW;CAC1B,WAAW,KAAK,YAAY,CAAC,CAC1B,QAAQ,CAAC,CACT,iBAAiB,SAAS,IAAI,EAAE,UAAU,UAAU,CAAC;CACxD,UAAU,KAAK,UAAU,CAAC,CAAC,QAAQ;CACnC,UAAU,KAAK,WAAW,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE;CAChD,SAAS,KAAK,UAAU,CAAC,CAAC,QAAQ;CAClC,QAAQ,KAAK,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE;CAC5C,MAAM,KAAK,MAAM;CACjB,SAAS,KAAK,SAAS;CACvB,cAAc,KAAK,eAAe;CAClC,OAAO,KAAK,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,IAAI;CAC3C,YAAY,KAAK,aAAa;CAC9B,eAAe,KAAK,gBAAgB;CACpC,iBAAiB,KAAK,kBAAkB;CACxC,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;CACtE,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;CACtE,WAAW,SAAS,cAAc;EAAE,MAAM;EAAU,KAAK;CAAE,CAAC,CAAC,CAAC,QAAQ;AACxE,IACC,MAAM,CACL,YAAY,oCAAoC,CAAC,CAAC,GAChD,EAAE,WACF,EAAE,UACF,EAAE,UACF,EAAE,SACF,EAAE,MACJ,CACF,CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storyshelf/db-mysql",
3
- "version": "0.8.0",
3
+ "version": "0.9.0-next-d2cc082",
4
4
  "description": "MySQL/MariaDB database adapter for StoryShelf (mysql2 + Drizzle, PlanetScale/TiDB compatible).",
5
5
  "keywords": [
6
6
  "database",
@@ -72,7 +72,7 @@
72
72
  "prepublishOnly": "nub run build"
73
73
  },
74
74
  "dependencies": {
75
- "@storyshelf/core": "0.8.0",
75
+ "@storyshelf/core": "0.9.0-next-d2cc082",
76
76
  "drizzle-orm": "^0.45.4",
77
77
  "mysql2": "^3.9.0"
78
78
  },
@@ -103,14 +103,5 @@
103
103
  },
104
104
  "engines": {
105
105
  "node": ">=24"
106
- },
107
- "jsr": {
108
- "runtimeCompat": {
109
- "node": true,
110
- "deno": true,
111
- "browser": false,
112
- "workerd": false,
113
- "bun": true
114
- }
115
106
  }
116
107
  }