From 59c3e1856480f4e868bfacbfa21dff6f6b896943 Mon Sep 17 00:00:00 2001 From: Pontus Abrahamsson Date: Wed, 15 Jan 2025 15:50:43 +0100 Subject: [PATCH] Feature/provider (#61) * wip * wip * wip * wip --- apps/web/.env-example | 3 +- apps/web/migrations/0017_vengeful_tomas.sql | 3 + apps/web/migrations/0018_worried_salo.sql | 1 + apps/web/migrations/0019_glorious_orphan.sql | 19 + apps/web/migrations/meta/0017_snapshot.json | 1153 ++++++++++++++++ apps/web/migrations/meta/0018_snapshot.json | 1173 ++++++++++++++++ apps/web/migrations/meta/0019_snapshot.json | 1227 +++++++++++++++++ apps/web/migrations/meta/_journal.json | 21 + .../[organization]/[project]/page.tsx | 11 + .../[organization]/[project]/tuning/page.tsx | 20 +- apps/web/src/components/activity.server.tsx | 14 - apps/web/src/components/activity.tsx | 24 +- apps/web/src/components/copy-input.tsx | 14 +- apps/web/src/components/header.tsx | 2 +- .../components/modals/provider-settings.tsx | 256 ++++ apps/web/src/components/onboarding-steps.tsx | 96 ++ apps/web/src/components/settings-card.tsx | 122 +- apps/web/src/components/settings.tsx | 62 - apps/web/src/components/settings/billing.tsx | 5 + apps/web/src/components/settings/index.tsx | 33 +- apps/web/src/components/settings/provider.tsx | 114 ++ apps/web/src/components/sidebar.tsx | 4 +- apps/web/src/components/tuning.tsx | 190 ++- apps/web/src/components/ui/icons.tsx | 44 + apps/web/src/components/ui/select.tsx | 2 +- apps/web/src/db/queries/project-settings.ts | 75 - apps/web/src/db/queries/project.ts | 78 +- apps/web/src/db/queries/translate.ts | 2 +- apps/web/src/db/schema.ts | 82 +- apps/web/src/lib/crypto.ts | 76 + apps/web/src/lib/translators/prompt.ts | 45 + apps/web/src/locales/en.ts | 51 + apps/web/src/trpc/init.ts | 52 +- apps/web/src/trpc/middlewares/ratelimits.ts | 4 +- apps/web/src/trpc/permissions/organization.ts | 42 +- apps/web/src/trpc/permissions/project.ts | 54 - apps/web/src/trpc/routers/analytics.ts | 3 +- apps/web/src/trpc/routers/organization.ts | 8 +- apps/web/src/trpc/routers/project.ts | 90 +- apps/web/src/trpc/routers/translate.ts | 10 +- apps/web/src/trpc/routers/user.ts | 8 +- packages/cli/README.md | 12 + packages/cli/src/providers.ts | 2 +- 43 files changed, 4996 insertions(+), 311 deletions(-) create mode 100644 apps/web/migrations/0017_vengeful_tomas.sql create mode 100644 apps/web/migrations/0018_worried_salo.sql create mode 100644 apps/web/migrations/0019_glorious_orphan.sql create mode 100644 apps/web/migrations/meta/0017_snapshot.json create mode 100644 apps/web/migrations/meta/0018_snapshot.json create mode 100644 apps/web/migrations/meta/0019_snapshot.json delete mode 100644 apps/web/src/components/activity.server.tsx create mode 100644 apps/web/src/components/modals/provider-settings.tsx create mode 100644 apps/web/src/components/onboarding-steps.tsx delete mode 100644 apps/web/src/components/settings.tsx create mode 100644 apps/web/src/components/settings/billing.tsx create mode 100644 apps/web/src/components/settings/provider.tsx create mode 100644 apps/web/src/components/ui/icons.tsx delete mode 100644 apps/web/src/db/queries/project-settings.ts create mode 100644 apps/web/src/lib/crypto.ts delete mode 100644 apps/web/src/trpc/permissions/project.ts diff --git a/apps/web/.env-example b/apps/web/.env-example index 67321c7c..32202497 100644 --- a/apps/web/.env-example +++ b/apps/web/.env-example @@ -6,4 +6,5 @@ TURSO_AUTH_TOKEN= RESEND_API_KEY= UPSTASH_REDIS_REST_URL= UPSTASH_REDIS_REST_TOKEN= -OPENAI_API_KEY= \ No newline at end of file +OPENAI_API_KEY= +ENCRYPTION_SECRET= \ No newline at end of file diff --git a/apps/web/migrations/0017_vengeful_tomas.sql b/apps/web/migrations/0017_vengeful_tomas.sql new file mode 100644 index 00000000..fb0a6bc8 --- /dev/null +++ b/apps/web/migrations/0017_vengeful_tomas.sql @@ -0,0 +1,3 @@ +ALTER TABLE `project_settings` ADD `provider` text DEFAULT 'openai' NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `model` text DEFAULT 'gpt-4-turbo' NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `provider_api_key` text; \ No newline at end of file diff --git a/apps/web/migrations/0018_worried_salo.sql b/apps/web/migrations/0018_worried_salo.sql new file mode 100644 index 00000000..f4d45f16 --- /dev/null +++ b/apps/web/migrations/0018_worried_salo.sql @@ -0,0 +1 @@ +ALTER TABLE `project_settings` ADD `organization_id` text NOT NULL REFERENCES organizations(id); \ No newline at end of file diff --git a/apps/web/migrations/0019_glorious_orphan.sql b/apps/web/migrations/0019_glorious_orphan.sql new file mode 100644 index 00000000..33baa10a --- /dev/null +++ b/apps/web/migrations/0019_glorious_orphan.sql @@ -0,0 +1,19 @@ +ALTER TABLE `project_settings` ADD `translation_memory` integer DEFAULT true NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `quality_checks` integer DEFAULT true NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `context_detection` integer DEFAULT true NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `length_control` text DEFAULT 'flexible' NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `inclusive_language` integer DEFAULT true NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `formality` text DEFAULT 'casual' NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `tone_of_voice` text DEFAULT 'casual' NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `brand_name` text;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `brand_voice` text;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `emotive_intent` text DEFAULT 'neutral' NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `idioms` integer DEFAULT true NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `terminology` text;--> statement-breakpoint +ALTER TABLE `project_settings` ADD `domain_expertise` text DEFAULT 'general' NOT NULL;--> statement-breakpoint +ALTER TABLE `project_settings` DROP COLUMN `cache`;--> statement-breakpoint +ALTER TABLE `project_settings` DROP COLUMN `context`;--> statement-breakpoint +ALTER TABLE `project_settings` DROP COLUMN `temperature`;--> statement-breakpoint +ALTER TABLE `project_settings` DROP COLUMN `instructions`;--> statement-breakpoint +ALTER TABLE `project_settings` DROP COLUMN `memory`;--> statement-breakpoint +ALTER TABLE `project_settings` DROP COLUMN `grammar`; \ No newline at end of file diff --git a/apps/web/migrations/meta/0017_snapshot.json b/apps/web/migrations/meta/0017_snapshot.json new file mode 100644 index 00000000..6bf1d22c --- /dev/null +++ b/apps/web/migrations/meta/0017_snapshot.json @@ -0,0 +1,1153 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "299f065a-d6c5-4bbb-a415-c41a27a38da5", + "prevId": "9af33789-52f1-4bfc-a6f5-cb0373123815", + "tables": { + "accounts": { + "name": "accounts", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "accounts_user_id_idx": { + "name": "accounts_user_id_idx", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "provider_compound_idx": { + "name": "provider_compound_idx", + "columns": [ + "provider_id", + "account_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "accounts_user_id_users_id_fk": { + "name": "accounts_user_id_users_id_fk", + "tableFrom": "accounts", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "invitations": { + "name": "invitations", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "org_email_idx": { + "name": "org_email_idx", + "columns": [ + "organization_id", + "email" + ], + "isUnique": false + }, + "invitations_expires_at_idx": { + "name": "invitations_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "invitations_organization_id_organizations_id_fk": { + "name": "invitations_organization_id_organizations_id_fk", + "tableFrom": "invitations", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitations_inviter_id_users_id_fk": { + "name": "invitations_inviter_id_users_id_fk", + "tableFrom": "invitations", + "tableTo": "users", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "members": { + "name": "members", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "org_user_idx": { + "name": "org_user_idx", + "columns": [ + "organization_id", + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "members_organization_id_organizations_id_fk": { + "name": "members_organization_id_organizations_id_fk", + "tableFrom": "members", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "members_user_id_users_id_fk": { + "name": "members_user_id_users_id_fk", + "tableFrom": "members", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "organizations": { + "name": "organizations", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'free'" + }, + "api_key": { + "name": "api_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "organizations_slug_unique": { + "name": "organizations_slug_unique", + "columns": [ + "slug" + ], + "isUnique": true + }, + "organizations_api_key_unique": { + "name": "organizations_api_key_unique", + "columns": [ + "api_key" + ], + "isUnique": true + }, + "slug_idx": { + "name": "slug_idx", + "columns": [ + "slug" + ], + "isUnique": false + }, + "org_api_key_idx": { + "name": "org_api_key_idx", + "columns": [ + "api_key" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "project_settings": { + "name": "project_settings", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "cache": { + "name": "cache", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "context": { + "name": "context", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "temperature": { + "name": "temperature", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "instructions": { + "name": "instructions", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "memory": { + "name": "memory", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "grammar": { + "name": "grammar", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'openai'" + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'gpt-4-turbo'" + }, + "provider_api_key": { + "name": "provider_api_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "project_idx": { + "name": "project_idx", + "columns": [ + "project_id" + ], + "isUnique": false + }, + "created_at_idx": { + "name": "created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "project_settings_project_id_projects_id_fk": { + "name": "project_settings_project_id_projects_id_fk", + "tableFrom": "project_settings", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "projects": { + "name": "projects", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "org_idx": { + "name": "org_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "slug_org_idx": { + "name": "slug_org_idx", + "columns": [ + "slug", + "organization_id" + ], + "isUnique": true + }, + "project_slug_idx": { + "name": "project_slug_idx", + "columns": [ + "slug" + ], + "isUnique": false + }, + "project_org_id_idx": { + "name": "project_org_id_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "projects_organization_id_organizations_id_fk": { + "name": "projects_organization_id_organizations_id_fk", + "tableFrom": "projects", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sessions": { + "name": "sessions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "sessions_token_unique": { + "name": "sessions_token_unique", + "columns": [ + "token" + ], + "isUnique": true + }, + "user_id_idx": { + "name": "user_id_idx", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "token_idx": { + "name": "token_idx", + "columns": [ + "token" + ], + "isUnique": false + }, + "expires_at_idx": { + "name": "expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "translations": { + "name": "translations", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source_format": { + "name": "source_format", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_language": { + "name": "source_language", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_language": { + "name": "target_language", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "translation_key": { + "name": "translation_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_text": { + "name": "source_text", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "translated_text": { + "name": "translated_text", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "context": { + "name": "context", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "commit": { + "name": "commit", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "commit_message": { + "name": "commit_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "project_translations_idx": { + "name": "project_translations_idx", + "columns": [ + "project_id" + ], + "isUnique": false + }, + "translations_created_at_idx": { + "name": "translations_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + }, + "unique_translation_idx": { + "name": "unique_translation_idx", + "columns": [ + "project_id", + "translation_key", + "target_language" + ], + "isUnique": true + }, + "org_translations_idx": { + "name": "org_translations_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "source_language_idx": { + "name": "source_language_idx", + "columns": [ + "source_language" + ], + "isUnique": false + }, + "target_language_idx": { + "name": "target_language_idx", + "columns": [ + "target_language" + ], + "isUnique": false + }, + "translations_project_id_idx": { + "name": "translations_project_id_idx", + "columns": [ + "project_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "translations_project_id_projects_id_fk": { + "name": "translations_project_id_projects_id_fk", + "tableFrom": "translations", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "translations_organization_id_organizations_id_fk": { + "name": "translations_organization_id_organizations_id_fk", + "tableFrom": "translations", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "translations_user_id_users_id_fk": { + "name": "translations_user_id_users_id_fk", + "tableFrom": "translations", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "users": { + "name": "users", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email_verified": { + "name": "email_verified", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "api_key": { + "name": "api_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "users_email_unique": { + "name": "users_email_unique", + "columns": [ + "email" + ], + "isUnique": true + }, + "users_api_key_unique": { + "name": "users_api_key_unique", + "columns": [ + "api_key" + ], + "isUnique": true + }, + "email_idx": { + "name": "email_idx", + "columns": [ + "email" + ], + "isUnique": false + }, + "api_key_idx": { + "name": "api_key_idx", + "columns": [ + "api_key" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "verifications": { + "name": "verifications", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "identifier_idx": { + "name": "identifier_idx", + "columns": [ + "identifier" + ], + "isUnique": false + }, + "verifications_expires_at_idx": { + "name": "verifications_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/apps/web/migrations/meta/0018_snapshot.json b/apps/web/migrations/meta/0018_snapshot.json new file mode 100644 index 00000000..64100919 --- /dev/null +++ b/apps/web/migrations/meta/0018_snapshot.json @@ -0,0 +1,1173 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "e77979ef-a276-404b-8d66-74e3dde4bff3", + "prevId": "299f065a-d6c5-4bbb-a415-c41a27a38da5", + "tables": { + "accounts": { + "name": "accounts", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "accounts_user_id_idx": { + "name": "accounts_user_id_idx", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "provider_compound_idx": { + "name": "provider_compound_idx", + "columns": [ + "provider_id", + "account_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "accounts_user_id_users_id_fk": { + "name": "accounts_user_id_users_id_fk", + "tableFrom": "accounts", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "invitations": { + "name": "invitations", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "org_email_idx": { + "name": "org_email_idx", + "columns": [ + "organization_id", + "email" + ], + "isUnique": false + }, + "invitations_expires_at_idx": { + "name": "invitations_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "invitations_organization_id_organizations_id_fk": { + "name": "invitations_organization_id_organizations_id_fk", + "tableFrom": "invitations", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitations_inviter_id_users_id_fk": { + "name": "invitations_inviter_id_users_id_fk", + "tableFrom": "invitations", + "tableTo": "users", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "members": { + "name": "members", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "org_user_idx": { + "name": "org_user_idx", + "columns": [ + "organization_id", + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "members_organization_id_organizations_id_fk": { + "name": "members_organization_id_organizations_id_fk", + "tableFrom": "members", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "members_user_id_users_id_fk": { + "name": "members_user_id_users_id_fk", + "tableFrom": "members", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "organizations": { + "name": "organizations", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'free'" + }, + "api_key": { + "name": "api_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "organizations_slug_unique": { + "name": "organizations_slug_unique", + "columns": [ + "slug" + ], + "isUnique": true + }, + "organizations_api_key_unique": { + "name": "organizations_api_key_unique", + "columns": [ + "api_key" + ], + "isUnique": true + }, + "slug_idx": { + "name": "slug_idx", + "columns": [ + "slug" + ], + "isUnique": false + }, + "org_api_key_idx": { + "name": "org_api_key_idx", + "columns": [ + "api_key" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "project_settings": { + "name": "project_settings", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "cache": { + "name": "cache", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "context": { + "name": "context", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "temperature": { + "name": "temperature", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "instructions": { + "name": "instructions", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "memory": { + "name": "memory", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "grammar": { + "name": "grammar", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'openai'" + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'gpt-4-turbo'" + }, + "provider_api_key": { + "name": "provider_api_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "project_idx": { + "name": "project_idx", + "columns": [ + "project_id" + ], + "isUnique": false + }, + "created_at_idx": { + "name": "created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "project_settings_project_id_projects_id_fk": { + "name": "project_settings_project_id_projects_id_fk", + "tableFrom": "project_settings", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "project_settings_organization_id_organizations_id_fk": { + "name": "project_settings_organization_id_organizations_id_fk", + "tableFrom": "project_settings", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "projects": { + "name": "projects", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "org_idx": { + "name": "org_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "slug_org_idx": { + "name": "slug_org_idx", + "columns": [ + "slug", + "organization_id" + ], + "isUnique": true + }, + "project_slug_idx": { + "name": "project_slug_idx", + "columns": [ + "slug" + ], + "isUnique": false + }, + "project_org_id_idx": { + "name": "project_org_id_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "projects_organization_id_organizations_id_fk": { + "name": "projects_organization_id_organizations_id_fk", + "tableFrom": "projects", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sessions": { + "name": "sessions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "sessions_token_unique": { + "name": "sessions_token_unique", + "columns": [ + "token" + ], + "isUnique": true + }, + "user_id_idx": { + "name": "user_id_idx", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "token_idx": { + "name": "token_idx", + "columns": [ + "token" + ], + "isUnique": false + }, + "expires_at_idx": { + "name": "expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "translations": { + "name": "translations", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source_format": { + "name": "source_format", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_language": { + "name": "source_language", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_language": { + "name": "target_language", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "translation_key": { + "name": "translation_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_text": { + "name": "source_text", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "translated_text": { + "name": "translated_text", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "context": { + "name": "context", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "commit": { + "name": "commit", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "commit_message": { + "name": "commit_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "project_translations_idx": { + "name": "project_translations_idx", + "columns": [ + "project_id" + ], + "isUnique": false + }, + "translations_created_at_idx": { + "name": "translations_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + }, + "unique_translation_idx": { + "name": "unique_translation_idx", + "columns": [ + "project_id", + "translation_key", + "target_language" + ], + "isUnique": true + }, + "org_translations_idx": { + "name": "org_translations_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "source_language_idx": { + "name": "source_language_idx", + "columns": [ + "source_language" + ], + "isUnique": false + }, + "target_language_idx": { + "name": "target_language_idx", + "columns": [ + "target_language" + ], + "isUnique": false + }, + "translations_project_id_idx": { + "name": "translations_project_id_idx", + "columns": [ + "project_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "translations_project_id_projects_id_fk": { + "name": "translations_project_id_projects_id_fk", + "tableFrom": "translations", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "translations_organization_id_organizations_id_fk": { + "name": "translations_organization_id_organizations_id_fk", + "tableFrom": "translations", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "translations_user_id_users_id_fk": { + "name": "translations_user_id_users_id_fk", + "tableFrom": "translations", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "users": { + "name": "users", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email_verified": { + "name": "email_verified", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "api_key": { + "name": "api_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "users_email_unique": { + "name": "users_email_unique", + "columns": [ + "email" + ], + "isUnique": true + }, + "users_api_key_unique": { + "name": "users_api_key_unique", + "columns": [ + "api_key" + ], + "isUnique": true + }, + "email_idx": { + "name": "email_idx", + "columns": [ + "email" + ], + "isUnique": false + }, + "api_key_idx": { + "name": "api_key_idx", + "columns": [ + "api_key" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "verifications": { + "name": "verifications", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "identifier_idx": { + "name": "identifier_idx", + "columns": [ + "identifier" + ], + "isUnique": false + }, + "verifications_expires_at_idx": { + "name": "verifications_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/apps/web/migrations/meta/0019_snapshot.json b/apps/web/migrations/meta/0019_snapshot.json new file mode 100644 index 00000000..49501332 --- /dev/null +++ b/apps/web/migrations/meta/0019_snapshot.json @@ -0,0 +1,1227 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "0a34e697-541e-44a7-950e-33b027883c4a", + "prevId": "e77979ef-a276-404b-8d66-74e3dde4bff3", + "tables": { + "accounts": { + "name": "accounts", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "accounts_user_id_idx": { + "name": "accounts_user_id_idx", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "provider_compound_idx": { + "name": "provider_compound_idx", + "columns": [ + "provider_id", + "account_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "accounts_user_id_users_id_fk": { + "name": "accounts_user_id_users_id_fk", + "tableFrom": "accounts", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "invitations": { + "name": "invitations", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "org_email_idx": { + "name": "org_email_idx", + "columns": [ + "organization_id", + "email" + ], + "isUnique": false + }, + "invitations_expires_at_idx": { + "name": "invitations_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "invitations_organization_id_organizations_id_fk": { + "name": "invitations_organization_id_organizations_id_fk", + "tableFrom": "invitations", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitations_inviter_id_users_id_fk": { + "name": "invitations_inviter_id_users_id_fk", + "tableFrom": "invitations", + "tableTo": "users", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "members": { + "name": "members", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "org_user_idx": { + "name": "org_user_idx", + "columns": [ + "organization_id", + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "members_organization_id_organizations_id_fk": { + "name": "members_organization_id_organizations_id_fk", + "tableFrom": "members", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "members_user_id_users_id_fk": { + "name": "members_user_id_users_id_fk", + "tableFrom": "members", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "organizations": { + "name": "organizations", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'free'" + }, + "api_key": { + "name": "api_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "organizations_slug_unique": { + "name": "organizations_slug_unique", + "columns": [ + "slug" + ], + "isUnique": true + }, + "organizations_api_key_unique": { + "name": "organizations_api_key_unique", + "columns": [ + "api_key" + ], + "isUnique": true + }, + "slug_idx": { + "name": "slug_idx", + "columns": [ + "slug" + ], + "isUnique": false + }, + "org_api_key_idx": { + "name": "org_api_key_idx", + "columns": [ + "api_key" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "project_settings": { + "name": "project_settings", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "translation_memory": { + "name": "translation_memory", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "quality_checks": { + "name": "quality_checks", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "context_detection": { + "name": "context_detection", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "length_control": { + "name": "length_control", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'flexible'" + }, + "inclusive_language": { + "name": "inclusive_language", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "formality": { + "name": "formality", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'casual'" + }, + "tone_of_voice": { + "name": "tone_of_voice", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'casual'" + }, + "brand_name": { + "name": "brand_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "brand_voice": { + "name": "brand_voice", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "emotive_intent": { + "name": "emotive_intent", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'neutral'" + }, + "idioms": { + "name": "idioms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "terminology": { + "name": "terminology", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "domain_expertise": { + "name": "domain_expertise", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'general'" + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'openai'" + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'gpt-4-turbo'" + }, + "provider_api_key": { + "name": "provider_api_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "project_idx": { + "name": "project_idx", + "columns": [ + "project_id" + ], + "isUnique": false + }, + "created_at_idx": { + "name": "created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "project_settings_project_id_projects_id_fk": { + "name": "project_settings_project_id_projects_id_fk", + "tableFrom": "project_settings", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "project_settings_organization_id_organizations_id_fk": { + "name": "project_settings_organization_id_organizations_id_fk", + "tableFrom": "project_settings", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "projects": { + "name": "projects", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "org_idx": { + "name": "org_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "slug_org_idx": { + "name": "slug_org_idx", + "columns": [ + "slug", + "organization_id" + ], + "isUnique": true + }, + "project_slug_idx": { + "name": "project_slug_idx", + "columns": [ + "slug" + ], + "isUnique": false + }, + "project_org_id_idx": { + "name": "project_org_id_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "projects_organization_id_organizations_id_fk": { + "name": "projects_organization_id_organizations_id_fk", + "tableFrom": "projects", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sessions": { + "name": "sessions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "sessions_token_unique": { + "name": "sessions_token_unique", + "columns": [ + "token" + ], + "isUnique": true + }, + "user_id_idx": { + "name": "user_id_idx", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "token_idx": { + "name": "token_idx", + "columns": [ + "token" + ], + "isUnique": false + }, + "expires_at_idx": { + "name": "expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "translations": { + "name": "translations", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source_format": { + "name": "source_format", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_language": { + "name": "source_language", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_language": { + "name": "target_language", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "translation_key": { + "name": "translation_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_text": { + "name": "source_text", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "translated_text": { + "name": "translated_text", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "context": { + "name": "context", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "commit": { + "name": "commit", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "commit_message": { + "name": "commit_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "project_translations_idx": { + "name": "project_translations_idx", + "columns": [ + "project_id" + ], + "isUnique": false + }, + "translations_created_at_idx": { + "name": "translations_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + }, + "unique_translation_idx": { + "name": "unique_translation_idx", + "columns": [ + "project_id", + "translation_key", + "target_language" + ], + "isUnique": true + }, + "org_translations_idx": { + "name": "org_translations_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "source_language_idx": { + "name": "source_language_idx", + "columns": [ + "source_language" + ], + "isUnique": false + }, + "target_language_idx": { + "name": "target_language_idx", + "columns": [ + "target_language" + ], + "isUnique": false + }, + "translations_project_id_idx": { + "name": "translations_project_id_idx", + "columns": [ + "project_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "translations_project_id_projects_id_fk": { + "name": "translations_project_id_projects_id_fk", + "tableFrom": "translations", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "translations_organization_id_organizations_id_fk": { + "name": "translations_organization_id_organizations_id_fk", + "tableFrom": "translations", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "translations_user_id_users_id_fk": { + "name": "translations_user_id_users_id_fk", + "tableFrom": "translations", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "users": { + "name": "users", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email_verified": { + "name": "email_verified", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "api_key": { + "name": "api_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "users_email_unique": { + "name": "users_email_unique", + "columns": [ + "email" + ], + "isUnique": true + }, + "users_api_key_unique": { + "name": "users_api_key_unique", + "columns": [ + "api_key" + ], + "isUnique": true + }, + "email_idx": { + "name": "email_idx", + "columns": [ + "email" + ], + "isUnique": false + }, + "api_key_idx": { + "name": "api_key_idx", + "columns": [ + "api_key" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "verifications": { + "name": "verifications", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "identifier_idx": { + "name": "identifier_idx", + "columns": [ + "identifier" + ], + "isUnique": false + }, + "verifications_expires_at_idx": { + "name": "verifications_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/apps/web/migrations/meta/_journal.json b/apps/web/migrations/meta/_journal.json index a8db096e..43eaeaec 100644 --- a/apps/web/migrations/meta/_journal.json +++ b/apps/web/migrations/meta/_journal.json @@ -120,6 +120,27 @@ "when": 1736851711514, "tag": "0016_fantastic_susan_delgado", "breakpoints": true + }, + { + "idx": 17, + "version": "6", + "when": 1736861325663, + "tag": "0017_vengeful_tomas", + "breakpoints": true + }, + { + "idx": 18, + "version": "6", + "when": 1736862373027, + "tag": "0018_worried_salo", + "breakpoints": true + }, + { + "idx": 19, + "version": "6", + "when": 1736938400515, + "tag": "0019_glorious_orphan", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/web/src/app/[locale]/(dashboard)/(sidebar)/[organization]/[project]/page.tsx b/apps/web/src/app/[locale]/(dashboard)/(sidebar)/[organization]/[project]/page.tsx index c9335580..9e1c8d4e 100644 --- a/apps/web/src/app/[locale]/(dashboard)/(sidebar)/[organization]/[project]/page.tsx +++ b/apps/web/src/app/[locale]/(dashboard)/(sidebar)/[organization]/[project]/page.tsx @@ -3,6 +3,7 @@ import { AnalyticsChart, AnalyticsChartSkeleton, } from "@/components/charts/analytics"; +import { OnboardingSteps } from "@/components/onboarding-steps"; import { HydrateClient, trpc } from "@/trpc/server"; import { Suspense } from "react"; @@ -23,6 +24,16 @@ export default async function Page({ organizationId: organization, }); + const translations = await trpc.translate.getTranslationsBySlug({ + slug: project, + organizationId: organization, + }); + + // If there are no translations, show the onboarding + if (!translations.length) { + return ; + } + return ( }> diff --git a/apps/web/src/app/[locale]/(dashboard)/(sidebar)/[organization]/[project]/tuning/page.tsx b/apps/web/src/app/[locale]/(dashboard)/(sidebar)/[organization]/[project]/tuning/page.tsx index d707e404..a4a7a387 100644 --- a/apps/web/src/app/[locale]/(dashboard)/(sidebar)/[organization]/[project]/tuning/page.tsx +++ b/apps/web/src/app/[locale]/(dashboard)/(sidebar)/[organization]/[project]/tuning/page.tsx @@ -1,5 +1,21 @@ import { Tuning } from "@/components/tuning"; +import { HydrateClient, trpc } from "@/trpc/server"; -export default function Page() { - return ; +export default async function Page({ + params, +}: { + params: Promise<{ organization: string; project: string }>; +}) { + const { organization, project } = await params; + + trpc.project.getBySlug.prefetch({ + slug: project, + organizationId: organization, + }); + + return ( + + + + ); } diff --git a/apps/web/src/components/activity.server.tsx b/apps/web/src/components/activity.server.tsx deleted file mode 100644 index f423c4d1..00000000 --- a/apps/web/src/components/activity.server.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { Activity } from "@/components/activity"; -import { getI18n } from "@/locales/server"; - -export async function ActivityServer() { - const t = await getI18n(); - - return ( -
-

{t("activity.title")}

- - -
- ); -} diff --git a/apps/web/src/components/activity.tsx b/apps/web/src/components/activity.tsx index 67fa029e..966e4741 100644 --- a/apps/web/src/components/activity.tsx +++ b/apps/web/src/components/activity.tsx @@ -5,6 +5,7 @@ import { useI18n } from "@/locales/client"; import { trpc } from "@/trpc/client"; import { useParams } from "next/navigation"; import { useEffect, useRef } from "react"; +import { Button } from "./ui/button"; import { Loader } from "./ui/loader"; export function Activity() { @@ -33,7 +34,12 @@ export function Activity() { useEffect(() => { const observer = new IntersectionObserver( (entries) => { - if (entries[0].isIntersecting && hasNextPage && !isFetchingNextPage) { + if ( + entries[0].isIntersecting && + hasNextPage && + !isFetchingNextPage && + pages.length > 1 + ) { fetchNextPage(); } }, @@ -45,7 +51,7 @@ export function Activity() { } return () => observer.disconnect(); - }, [fetchNextPage, hasNextPage, isFetchingNextPage]); + }, [fetchNextPage, hasNextPage, isFetchingNextPage, pages.length]); if (!pages) return ; @@ -74,9 +80,21 @@ export function Activity() { {isFetching && (
- Loading... + + {t("activity.loading")}... +
)} + + {hasNextPage && pages.length === 1 && !isFetching && ( + + )} diff --git a/apps/web/src/components/copy-input.tsx b/apps/web/src/components/copy-input.tsx index 8e5dc992..02e28bd3 100644 --- a/apps/web/src/components/copy-input.tsx +++ b/apps/web/src/components/copy-input.tsx @@ -9,20 +9,26 @@ import * as React from "react"; interface CopyInputProps extends React.InputHTMLAttributes { value: string; onUpdate?: () => void; + onCopy?: () => void; } export function CopyInput({ value, className, onUpdate, + onCopy, ...props }: CopyInputProps) { const [copied, setCopied] = React.useState(false); - const onCopy = async () => { + const handleCopy = async () => { await navigator.clipboard.writeText(value); setCopied(true); - setTimeout(() => setCopied(false), 2000); + + onCopy?.(); + setTimeout(() => { + setCopied(false); + }, 2000); }; return ( @@ -30,7 +36,7 @@ export function CopyInput({ @@ -49,7 +55,7 @@ export function CopyInput({ + + + + + Provider Settings + + +
+
+ +

+ Choose your preferred AI service for translations +

+ +
+ +
+ +

+ Select the AI model for translations +

+ +
+ +
+ +

+ Enter your API key to authenticate with your provider +

+ +
+ + + + + +
+
+
+ + ); +} diff --git a/apps/web/src/components/onboarding-steps.tsx b/apps/web/src/components/onboarding-steps.tsx new file mode 100644 index 00000000..b28701af --- /dev/null +++ b/apps/web/src/components/onboarding-steps.tsx @@ -0,0 +1,96 @@ +"use client"; + +import { CopyInput } from "@/components/copy-input"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Loader } from "@/components/ui/loader"; +import { cn } from "@/lib/utils"; +import { useI18n } from "@/locales/client"; +import { useParams } from "next/navigation"; +import { parseAsInteger, useQueryState } from "nuqs"; + +export function OnboardingSteps() { + const { project } = useParams(); + const t = useI18n(); + const [step, setStep] = useQueryState("step", parseAsInteger.withDefault(1)); + + return ( +
+
+
+
+ setStep(1)} + > + + + 1. {t("onboarding.steps.1.title")} + + + +

+ {t("onboarding.steps.1.description")} +

+ setStep(2)} + className="border-dashed text-xs" + /> +
+
+ +
= 2 ? "border-primary" : "border-border", + )} + /> +
+ + setStep(2)} + > + + + 2. {t("onboarding.steps.2.title")} + + + +
+ {step === 2 && } + +

+ {t("onboarding.steps.2.description")} +

+
+ +
+
+ +

+ {t("onboarding.info.description")}{" "} + + {t("onboarding.info.link")} + {" "} + {t("onboarding.info.description_2")} +

+
+
+
+ ); +} diff --git a/apps/web/src/components/settings-card.tsx b/apps/web/src/components/settings-card.tsx index 325964ad..13c618f8 100644 --- a/apps/web/src/components/settings-card.tsx +++ b/apps/web/src/components/settings-card.tsx @@ -53,7 +53,7 @@ export function SettingsCard({ onSave?: (value: string) => void; checked?: boolean; onCheckedChange?: (checked: boolean) => void; - options?: { label: string; value: string }[]; + options?: { label: string; value: string; icon?: () => JSX.Element }[]; placeholder?: string; isLoading?: boolean; validate?: "email" | "url" | "number" | "password" | "text"; @@ -92,6 +92,64 @@ export function SettingsCard({ } }; + const handleCheckedChange = async (checked: boolean) => { + try { + setIsSaving(true); + await onCheckedChange?.(checked); + + toast.success(t("settings.saved"), { + description: t("settings.savedDescription"), + }); + } catch (error) { + if (error instanceof TRPCClientError) { + if (error.data?.code === "FORBIDDEN") { + toast.error(t("settings.permissionDenied"), { + description: t("settings.permissionDeniedDescription"), + }); + } else { + toast.error(t("settings.error"), { + description: t("settings.errorDescription"), + }); + } + } else { + toast.error(t("settings.error"), { + description: t("settings.errorDescription"), + }); + } + } finally { + setIsSaving(false); + } + }; + + const handleSelectChange = async (value: string) => { + try { + setIsSaving(true); + await onChange?.(value); + + toast.success(t("settings.saved"), { + description: t("settings.savedDescription"), + }); + } catch (error) { + if (error instanceof TRPCClientError) { + if (error.data?.code === "FORBIDDEN") { + toast.error(t("settings.permissionDenied"), { + description: t("settings.permissionDeniedDescription"), + }); + } else { + toast.error(t("settings.error"), { + description: t("settings.errorDescription"), + }); + } + } else { + toast.error(t("settings.error"), { + description: t("settings.errorDescription"), + }); + } + } finally { + setIsSaving(false); + } + }; + if (isLoading) { return (
@@ -128,25 +186,38 @@ export function SettingsCard({ {type === "switch" && ( { - onCheckedChange?.(!!checked); - toast.success(t("settings.saved"), { - description: t("settings.savedDescription"), - }); + onCheckedChange={(value) => { + handleCheckedChange?.(!!value); }} /> )} {type === "select" && options && ( -
- + + +
+ {options.find((opt) => opt.value === value)?.icon && ( + + {options + .find((opt) => opt.value === value) + ?.icon?.()} + + )} + + {options.find((opt) => opt.value === value)?.label} + +
+
{options.map((option) => ( - {option.label} +
+ {option.icon && {option.icon()}} + {option.label} +
))}
@@ -182,12 +253,29 @@ export function SettingsCard({ )} {type === "textarea" && ( -