diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 000000000000..fb4ac66b07a2 --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,20 @@ +.git +**/.git + +node_modules +**/node_modules + +.next +**/.next + +dist +**/dist + +coverage +**/coverage + +*.log +**/*.log + +.DS_Store +**/.DS_Store diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 42aeea322047..1a4efa482827 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -63,6 +63,14 @@ RUN if [ "$name" = "desktop" ]; then \ cp -r ./desktop/prisma/region/migrations desktop/.next/standalone/desktop/prisma/region/migrations; \ fi RUN if [ "$name" = "devbox" ]; then \ + if [ -d "./providers/devbox/prisma/cockroach/migrations" ]; then \ + mkdir -p ./providers/devbox/.next/standalone/providers/devbox/prisma/cockroach && \ + cp -r ./providers/devbox/prisma/cockroach/migrations ./providers/devbox/.next/standalone/providers/devbox/prisma/cockroach/; \ + fi; \ + if [ -d "./providers/devbox/prisma/postgresql/migrations" ]; then \ + mkdir -p ./providers/devbox/.next/standalone/providers/devbox/prisma/postgresql && \ + cp -r ./providers/devbox/prisma/postgresql/migrations ./providers/devbox/.next/standalone/providers/devbox/prisma/postgresql/; \ + fi; \ if [ -d "./providers/devbox/prisma/migrations" ]; then \ mkdir -p ./providers/devbox/.next/standalone/providers/devbox/prisma && \ cp -r ./providers/devbox/prisma/migrations ./providers/devbox/.next/standalone/providers/devbox/prisma/; \ diff --git a/frontend/providers/devbox/.env.template b/frontend/providers/devbox/.env.template index 38597709c782..1ce83c25fc7f 100644 --- a/frontend/providers/devbox/.env.template +++ b/frontend/providers/devbox/.env.template @@ -44,6 +44,9 @@ ACCOUNT_URL= # in dev: postgresql://username:password@127.0.0.1:26257/devboxdb?connection_limit=50&pool_timeout=20 # in prod: postgresql://username:password@cockroachdb-global.cockroach-operator-system:26257/devboxdb?connection_limit=50&pool_timeout=20 DATABASE_URL= +# database provider for prisma runtime/migration routing +# values: cockroachdb (default) | postgresql +DATABASE_PROVIDER="cockroachdb" # url for template retag # in dev: http://127.0.0.1:8092 # in prod: http://devbox-service.devbox-system.svc.cluster.local:8092 diff --git a/frontend/providers/devbox/Dockerfile b/frontend/providers/devbox/Dockerfile index f56dfb909525..79ea3b0e4c06 100644 --- a/frontend/providers/devbox/Dockerfile +++ b/frontend/providers/devbox/Dockerfile @@ -54,6 +54,10 @@ COPY --from=builder /app/package.json ./package.json # https://nextjs.org/docs/advanced-features/output-file-tracing COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +# Next standalone includes prisma schemas/clients but not migrations. +# Keep both providers' migrations for initContainer migrate deploy. +COPY --from=builder --chown=nextjs:nodejs /app/prisma/cockroach/migrations ./providers/devbox/prisma/cockroach/migrations +COPY --from=builder --chown=nextjs:nodejs /app/prisma/postgresql/migrations ./providers/devbox/prisma/postgresql/migrations USER nextjs diff --git a/frontend/providers/devbox/deploy/manifests/deploy.yaml.tmpl b/frontend/providers/devbox/deploy/manifests/deploy.yaml.tmpl index 827800b75333..7d8c354d9a61 100644 --- a/frontend/providers/devbox/deploy/manifests/deploy.yaml.tmpl +++ b/frontend/providers/devbox/deploy/manifests/deploy.yaml.tmpl @@ -41,23 +41,34 @@ spec: env: - name: DATABASE_URL value: {{ .databaseUrl }} # -nsealos cm desktop-frontend-config ->database->global + devbox + - name: DATABASE_PROVIDER + value: "{{ default "cockroachdb" .databaseProvider }}" command: - sh - -c args: - |- cd /app/providers/devbox - MIGRATION="20260125094114_add_template_repository_kind" - HAS_MIGRATION=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM _prisma_migrations WHERE migration_name='${MIGRATION}' AND rolled_back_at IS NULL LIMIT 1;") - if [ "$HAS_MIGRATION" = "1" ]; then - prisma migrate deploy - exit 0 + DB_PROVIDER="${DATABASE_PROVIDER:-cockroachdb}" + SCHEMA_PATH="./prisma/cockroach/schema.prisma" + if [ "$DB_PROVIDER" = "postgresql" ] || [ "$DB_PROVIDER" = "postgres" ] || [ "$DB_PROVIDER" = "pg" ]; then + SCHEMA_PATH="./prisma/postgresql/schema.prisma" + HAS_UUID_FN=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM pg_proc WHERE proname='gen_random_uuid' LIMIT 1;") + if [ "$HAS_UUID_FN" != "1" ]; then + psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -c 'CREATE OR REPLACE FUNCTION public.gen_random_uuid() RETURNS uuid LANGUAGE SQL VOLATILE AS $func$ SELECT md5(random()::text || clock_timestamp()::text || txid_current()::text)::uuid; $func$;' + fi + MIGRATION="20260125094114_add_template_repository_kind" + HAS_MIGRATION=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM _prisma_migrations WHERE migration_name='${MIGRATION}' AND rolled_back_at IS NULL LIMIT 1;") + if [ "$HAS_MIGRATION" = "1" ]; then + prisma migrate deploy --schema "$SCHEMA_PATH" + exit 0 + fi + HAS_ENUM=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM pg_enum e JOIN pg_type t ON t.oid = e.enumtypid WHERE t.typname IN ('TemplateRepositoryKind','template_repository_kind') AND e.enumlabel = 'SERVICE' LIMIT 1;") + if [ "$HAS_ENUM" = "1" ]; then + prisma migrate resolve --schema "$SCHEMA_PATH" --applied "$MIGRATION" + fi fi - HAS_ENUM=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM pg_enum e JOIN pg_type t ON t.oid = e.enumtypid WHERE t.typname IN ('TemplateRepositoryKind','template_repository_kind') AND e.enumlabel = 'SERVICE' LIMIT 1;") - if [ "$HAS_ENUM" = "1" ]; then - prisma migrate resolve --applied "$MIGRATION" - fi - prisma migrate deploy + prisma migrate deploy --schema "$SCHEMA_PATH" containers: - name: devbox-frontend env: @@ -103,6 +114,8 @@ spec: value: {{ .regionUid }} # -nsealos cm desktop-frontend-config ->regionUid - name: DATABASE_URL value: {{ .databaseUrl }} # -nsealos cm desktop-frontend-config ->database->global + devbox + - name: DATABASE_PROVIDER + value: "{{ default "cockroachdb" .databaseProvider }}" - name: ENABLE_IMPORT_FEATURE value: 'false' - name: ENABLE_WEBIDE_FEATURE diff --git a/frontend/providers/devbox/package.json b/frontend/providers/devbox/package.json index 018877b363a0..6f33dea00a1d 100644 --- a/frontend/providers/devbox/package.json +++ b/frontend/providers/devbox/package.json @@ -10,7 +10,10 @@ "ts-lint": "tsc --noEmit", "link-sdk": "rm -rf node_modules/sealos-desktop-sdk && yalc link sealos-desktop-sdk", "unlink-sdk": "yalc remove --all && pnpm install sealos-desktop-sdk", - "gen-client": "prisma generate --schema ./prisma/schema.prisma", + "gen-client": "prisma generate --schema ./prisma/cockroach/schema.prisma && prisma generate --schema ./prisma/postgresql/schema.prisma", + "migrate:deploy:cockroach": "prisma migrate deploy --schema ./prisma/cockroach/schema.prisma", + "migrate:deploy:postgresql": "prisma migrate deploy --schema ./prisma/postgresql/schema.prisma", + "migrate:resolve:postgresql": "prisma migrate resolve --schema ./prisma/postgresql/schema.prisma", "postinstall": "pnpm gen-client", "ui": "pnpm dlx shadcn@latest add" }, diff --git a/frontend/providers/devbox/prisma/README.md b/frontend/providers/devbox/prisma/README.md new file mode 100644 index 000000000000..3bdd54c862b2 --- /dev/null +++ b/frontend/providers/devbox/prisma/README.md @@ -0,0 +1,20 @@ +# Prisma Layout (No Default Entry) + +To avoid accidental misuse, this repo intentionally does **not** keep: + +- `prisma/schema.prisma` +- `prisma/migrations/*` + +Always use an explicit schema: + +- CockroachDB + - schema: `prisma/cockroach/schema.prisma` + - deploy: `pnpm migrate:deploy:cockroach` +- PostgreSQL + - schema: `prisma/postgresql/schema.prisma` + - deploy: `pnpm migrate:deploy:postgresql` + +Runtime client routing is controlled by `DATABASE_PROVIDER`: + +- `cockroachdb` (default) +- `postgresql` diff --git a/frontend/providers/devbox/prisma/migrations/20241211022109_init/migration.sql b/frontend/providers/devbox/prisma/cockroach/migrations/20241211022109_init/migration.sql similarity index 100% rename from frontend/providers/devbox/prisma/migrations/20241211022109_init/migration.sql rename to frontend/providers/devbox/prisma/cockroach/migrations/20241211022109_init/migration.sql diff --git a/frontend/providers/devbox/prisma/migrations/20241217050230_update_tag/migration.sql b/frontend/providers/devbox/prisma/cockroach/migrations/20241217050230_update_tag/migration.sql similarity index 100% rename from frontend/providers/devbox/prisma/migrations/20241217050230_update_tag/migration.sql rename to frontend/providers/devbox/prisma/cockroach/migrations/20241217050230_update_tag/migration.sql diff --git a/frontend/providers/devbox/prisma/migrations/20250103095011_region_update/migration.sql b/frontend/providers/devbox/prisma/cockroach/migrations/20250103095011_region_update/migration.sql similarity index 100% rename from frontend/providers/devbox/prisma/migrations/20250103095011_region_update/migration.sql rename to frontend/providers/devbox/prisma/cockroach/migrations/20250103095011_region_update/migration.sql diff --git a/frontend/providers/devbox/prisma/migrations/20250120175753_add_usage_count/migration.sql b/frontend/providers/devbox/prisma/cockroach/migrations/20250120175753_add_usage_count/migration.sql similarity index 100% rename from frontend/providers/devbox/prisma/migrations/20250120175753_add_usage_count/migration.sql rename to frontend/providers/devbox/prisma/cockroach/migrations/20250120175753_add_usage_count/migration.sql diff --git a/frontend/providers/devbox/prisma/migrations/20260125094114_add_template_repository_kind/migration.sql b/frontend/providers/devbox/prisma/cockroach/migrations/20260125094114_add_template_repository_kind/migration.sql similarity index 100% rename from frontend/providers/devbox/prisma/migrations/20260125094114_add_template_repository_kind/migration.sql rename to frontend/providers/devbox/prisma/cockroach/migrations/20260125094114_add_template_repository_kind/migration.sql diff --git a/frontend/providers/devbox/prisma/migrations/migration_lock.toml b/frontend/providers/devbox/prisma/cockroach/migrations/migration_lock.toml similarity index 100% rename from frontend/providers/devbox/prisma/migrations/migration_lock.toml rename to frontend/providers/devbox/prisma/cockroach/migrations/migration_lock.toml diff --git a/frontend/providers/devbox/prisma/schema.prisma b/frontend/providers/devbox/prisma/cockroach/schema.prisma similarity index 99% rename from frontend/providers/devbox/prisma/schema.prisma rename to frontend/providers/devbox/prisma/cockroach/schema.prisma index 5801ccf649a3..28f3dfa7a8ad 100644 --- a/frontend/providers/devbox/prisma/schema.prisma +++ b/frontend/providers/devbox/prisma/cockroach/schema.prisma @@ -1,6 +1,6 @@ generator globalClient { provider = "prisma-client-js" - output = "./generated/client" + output = "../generated/client" binaryTargets = ["native", "linux-musl-openssl-3.0.x"] } diff --git a/frontend/providers/devbox/prisma/postgresql/migrations/20241211022109_init/migration.sql b/frontend/providers/devbox/prisma/postgresql/migrations/20241211022109_init/migration.sql new file mode 100644 index 000000000000..e1ee140700ae --- /dev/null +++ b/frontend/providers/devbox/prisma/postgresql/migrations/20241211022109_init/migration.sql @@ -0,0 +1,123 @@ +-- CreateEnum +CREATE TYPE "TemplateRepositoryKind" AS ENUM ('FRAMEWORK', 'OS', 'LANGUAGE', 'CUSTOM'); + +-- Ensure gen_random_uuid() exists on PostgreSQL variants (e.g. KingbaseES) +CREATE OR REPLACE FUNCTION public.gen_random_uuid() +RETURNS uuid +LANGUAGE SQL +VOLATILE +AS $func$ + SELECT md5(random()::text || clock_timestamp()::text || txid_current()::text)::uuid; +$func$; + +-- CreateTable +CREATE TABLE "User" ( + "uid" UUID NOT NULL DEFAULT gen_random_uuid(), + "regionUid" TEXT NOT NULL, + "namespaceId" TEXT NOT NULL, + "deletedAt" TIMESTAMPTZ(3), + "createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMPTZ(3) NOT NULL, + "isDeleted" BOOL DEFAULT false, + + CONSTRAINT "User_pkey" PRIMARY KEY ("uid") +); + +-- CreateTable +CREATE TABLE "Organization" ( + "uid" UUID NOT NULL DEFAULT gen_random_uuid(), + "id" TEXT NOT NULL, + "createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMPTZ(3) NOT NULL, + "deletedAt" TIMESTAMPTZ(3), + "isDeleted" BOOL DEFAULT false, + "name" TEXT NOT NULL, + + CONSTRAINT "Organization_pkey" PRIMARY KEY ("uid") +); + +-- CreateTable +CREATE TABLE "UserOrganization" ( + "createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMPTZ(3) NOT NULL, + "userUid" UUID NOT NULL, + "organizationUid" UUID NOT NULL, + + CONSTRAINT "UserOrganization_pkey" PRIMARY KEY ("organizationUid","userUid") +); + +-- CreateTable +CREATE TABLE "TemplateRepository" ( + "uid" UUID NOT NULL DEFAULT gen_random_uuid(), + "deletedAt" TIMESTAMPTZ(3), + "createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMPTZ(3) NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "kind" "TemplateRepositoryKind" NOT NULL, + "organizationUid" TEXT NOT NULL, + "isPublic" BOOL NOT NULL DEFAULT false, + "iconId" TEXT, + "isDeleted" BOOL DEFAULT false, + + CONSTRAINT "TemplateRepository_pkey" PRIMARY KEY ("uid") +); + +-- CreateTable +CREATE TABLE "Template" ( + "uid" UUID NOT NULL DEFAULT gen_random_uuid(), + "name" TEXT NOT NULL, + "templateRepositoryUid" TEXT NOT NULL, + "devboxReleaseImage" TEXT, + "image" TEXT NOT NULL, + "config" TEXT NOT NULL, + "deletedAt" TIMESTAMPTZ(3), + "createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMPTZ(3) NOT NULL, + "parentUid" UUID, + "isDeleted" BOOL DEFAULT false, + + CONSTRAINT "Template_pkey" PRIMARY KEY ("uid") +); + +-- CreateTable +CREATE TABLE "Tag" ( + "uid" UUID NOT NULL DEFAULT gen_random_uuid(), + "name" TEXT NOT NULL, + "zhName" TEXT, + "enName" TEXT, + + CONSTRAINT "Tag_pkey" PRIMARY KEY ("uid") +); + +-- CreateTable +CREATE TABLE "TemplateRepositoryTag" ( + "templateRepositoryUid" UUID NOT NULL, + "tagUid" UUID NOT NULL, + + CONSTRAINT "TemplateRepositoryTag_pkey" PRIMARY KEY ("templateRepositoryUid","tagUid") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_isDeleted_regionUid_namespaceId_key" ON "User"("isDeleted", "regionUid", "namespaceId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Organization_id_key" ON "Organization"("id"); + +-- CreateIndex +CREATE INDEX "UserOrganization_userUid_idx" ON "UserOrganization"("userUid"); + +-- CreateIndex +CREATE INDEX "UserOrganization_createdAt_idx" ON "UserOrganization"("createdAt"); + +-- CreateIndex +CREATE INDEX "TemplateRepository_isDeleted_isPublic_idx" ON "TemplateRepository"("isDeleted", "isPublic"); + +-- CreateIndex +CREATE UNIQUE INDEX "TemplateRepository_isDeleted_name_key" ON "TemplateRepository"("isDeleted", "name"); + +-- CreateIndex +CREATE UNIQUE INDEX "Template_isDeleted_templateRepositoryUid_name_key" ON "Template"("isDeleted", "templateRepositoryUid", "name"); + +-- CreateIndex +CREATE INDEX "TemplateRepositoryTag_tagUid_idx" ON "TemplateRepositoryTag"("tagUid"); diff --git a/frontend/providers/devbox/prisma/postgresql/migrations/20241217050230_update_tag/migration.sql b/frontend/providers/devbox/prisma/postgresql/migrations/20241217050230_update_tag/migration.sql new file mode 100644 index 000000000000..4be0a8b48595 --- /dev/null +++ b/frontend/providers/devbox/prisma/postgresql/migrations/20241217050230_update_tag/migration.sql @@ -0,0 +1,5 @@ +-- CreateEnum +CREATE TYPE "TagType" AS ENUM ('PROGRAMMING_LANGUAGE', 'USE_CASE', 'OFFICIAL_CONTENT'); + +-- AlterTable +ALTER TABLE "Tag" ADD COLUMN "type" "TagType" NOT NULL DEFAULT 'OFFICIAL_CONTENT'; diff --git a/frontend/providers/devbox/prisma/postgresql/migrations/20250103095011_region_update/migration.sql b/frontend/providers/devbox/prisma/postgresql/migrations/20250103095011_region_update/migration.sql new file mode 100644 index 000000000000..144ebe5989aa --- /dev/null +++ b/frontend/providers/devbox/prisma/postgresql/migrations/20250103095011_region_update/migration.sql @@ -0,0 +1,22 @@ +-- upgrade region +-- DropIndex +DROP INDEX "TemplateRepository_isDeleted_name_key"; + +-- add regionUid column +ALTER TABLE "TemplateRepository" + ADD COLUMN "regionUid" TEXT NOT NULL default '00000000-0000-0000-0000-000000000000'; +ALTER TABLE "TemplateRepository" + ALTER COLUMN "regionUid" DROP DEFAULT; + +-- CreateIndex +CREATE INDEX "TemplateRepository_isDeleted_createdAt_idx" ON "TemplateRepository" ("isDeleted", "createdAt"); + +-- CreateIndex +CREATE UNIQUE INDEX "TemplateRepository_isDeleted_regionUid_name_key" ON "TemplateRepository" ("isDeleted", "regionUid", "name"); + +-- AlterTable +ALTER TABLE public."TemplateRepository" alter column "organizationUid" type uuid using "organizationUid"::uuid; +-- AlterTable +DROP INDEX "Template_isDeleted_templateRepositoryUid_name_key"; +ALTER TABLE "Template" ALTER COLUMN "templateRepositoryUid" type uuid using "templateRepositoryUid"::uuid; +CREATE UNIQUE INDEX "Template_isDeleted_templateRepositoryUid_name_key" ON "Template" ("isDeleted", "templateRepositoryUid", "name"); diff --git a/frontend/providers/devbox/prisma/postgresql/migrations/20250120175753_add_usage_count/migration.sql b/frontend/providers/devbox/prisma/postgresql/migrations/20250120175753_add_usage_count/migration.sql new file mode 100644 index 000000000000..1807d0e3f39d --- /dev/null +++ b/frontend/providers/devbox/prisma/postgresql/migrations/20250120175753_add_usage_count/migration.sql @@ -0,0 +1,5 @@ +-- Add usage count field to TemplateRepository +ALTER TABLE "TemplateRepository" ADD COLUMN "usageCount" INT4 NOT NULL DEFAULT 0; + +-- Create index on usageCount for better query performance +CREATE INDEX "TemplateRepository_isDeleted_usageCount_idx" ON "TemplateRepository"("isDeleted", "usageCount"); diff --git a/frontend/providers/devbox/prisma/postgresql/migrations/20260125094114_add_template_repository_kind/migration.sql b/frontend/providers/devbox/prisma/postgresql/migrations/20260125094114_add_template_repository_kind/migration.sql new file mode 100644 index 000000000000..a7a10c3b513b --- /dev/null +++ b/frontend/providers/devbox/prisma/postgresql/migrations/20260125094114_add_template_repository_kind/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "TemplateRepositoryKind" ADD VALUE 'SERVICE'; diff --git a/frontend/providers/devbox/prisma/postgresql/migrations/migration_lock.toml b/frontend/providers/devbox/prisma/postgresql/migrations/migration_lock.toml new file mode 100644 index 000000000000..99e4f2009079 --- /dev/null +++ b/frontend/providers/devbox/prisma/postgresql/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" diff --git a/frontend/providers/devbox/prisma/postgresql/schema.prisma b/frontend/providers/devbox/prisma/postgresql/schema.prisma new file mode 100644 index 000000000000..3e766feb07e3 --- /dev/null +++ b/frontend/providers/devbox/prisma/postgresql/schema.prisma @@ -0,0 +1,128 @@ +generator globalClient { + provider = "prisma-client-js" + output = "../generated/postgresql-client" + binaryTargets = ["native", "linux-musl-openssl-3.0.x"] +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") + relationMode = "prisma" +} + +model User { + uid String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + regionUid String + namespaceId String + deletedAt DateTime? @db.Timestamptz(3) + createdAt DateTime @default(now()) @db.Timestamptz(3) + updatedAt DateTime @updatedAt @db.Timestamptz(3) + isDeleted Boolean? @default(false) + userOrganizations UserOrganization[] + + @@unique([isDeleted, regionUid, namespaceId]) +} + +model Organization { + uid String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + id String @unique //nanoid + createdAt DateTime @default(now()) @db.Timestamptz(3) + updatedAt DateTime @updatedAt @db.Timestamptz(3) + deletedAt DateTime? @db.Timestamptz(3) + isDeleted Boolean? @default(false) + name String + userOrganizations UserOrganization[] + templateRepositories TemplateRepository[] +} + +model UserOrganization { + createdAt DateTime @default(now()) @db.Timestamptz(3) + updatedAt DateTime @updatedAt @db.Timestamptz(3) + userUid String @db.Uuid + organizationUid String @db.Uuid + organization Organization @relation(fields: [organizationUid], references: [uid]) + user User @relation(fields: [userUid], references: [uid]) + // role OrganizationRole // rbac + + @@id([organizationUid, userUid]) + @@index([userUid]) + @@index([createdAt]) +} + +model TemplateRepository { + uid String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + deletedAt DateTime? @db.Timestamptz(3) + createdAt DateTime @default(now()) @db.Timestamptz(3) + updatedAt DateTime @updatedAt @db.Timestamptz(3) + name String + // hzh.hub.sealos.run/orgNanoid/templateRepositoryName:templateName + description String? + kind TemplateRepositoryKind + organizationUid String @db.Uuid + isPublic Boolean @default(false) + templates Template[] + iconId String? + organization Organization @relation(fields: [organizationUid], references: [uid]) + isDeleted Boolean? @default(false) + regionUid String + templateRepositoryTags TemplateRepositoryTag[] + usageCount Int @default(0) + + @@unique([isDeleted, regionUid, name]) + @@index([isDeleted, isPublic]) + @@index([isDeleted, createdAt]) + @@index([isDeleted, usageCount]) +} + +model Template { + uid String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + name String + templateRepositoryUid String @db.Uuid + devboxReleaseImage String? + image String + config String // json + deletedAt DateTime? @db.Timestamptz(3) + createdAt DateTime @default(now()) @db.Timestamptz(3) + updatedAt DateTime @updatedAt @db.Timestamptz(3) + parentUid String? @db.Uuid + isDeleted Boolean? @default(false) + parent Template? @relation("Template", fields: [parentUid], references: [uid], onDelete: Restrict, onUpdate: Restrict) + children Template[] @relation("Template") + + templateRepository TemplateRepository @relation(fields: [templateRepositoryUid], references: [uid]) + + @@unique([isDeleted, templateRepositoryUid, name]) +} + +model Tag { + uid String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + type TagType @default(OFFICIAL_CONTENT) + name String + zhName String? + enName String? + templateRepositoryTags TemplateRepositoryTag[] +} + +model TemplateRepositoryTag { + templateRepositoryUid String @db.Uuid + tagUid String @db.Uuid + templateRepository TemplateRepository @relation(fields: [templateRepositoryUid], references: [uid]) + tag Tag @relation(fields: [tagUid], references: [uid]) + + @@id([templateRepositoryUid, tagUid]) + @@index([tagUid]) +} + +enum TemplateRepositoryKind { + FRAMEWORK + OS + LANGUAGE + SERVICE + CUSTOM +} + +enum TagType { + OFFICIAL_CONTENT + PROGRAMMING_LANGUAGE + USE_CASE +} diff --git a/frontend/providers/devbox/services/db/init.ts b/frontend/providers/devbox/services/db/init.ts index 100bd278bc05..36f9bf6b6842 100644 --- a/frontend/providers/devbox/services/db/init.ts +++ b/frontend/providers/devbox/services/db/init.ts @@ -1,11 +1,23 @@ -import { PrismaClient } from 'prisma/generated/client'; +import { PrismaClient as CockroachPrismaClient } from 'prisma/generated/client'; +import type { PrismaClient as PrismaClientType } from 'prisma/generated/client'; +import { PrismaClient as PostgreSQLPrismaClient } from 'prisma/generated/postgresql-client'; -const createPrismaClient = () => - new PrismaClient({ +const provider = (process.env.DATABASE_PROVIDER || 'cockroachdb').toLowerCase(); +const isPostgreSQLProvider = ['postgresql', 'postgres', 'pg'].includes(provider); + +const createPrismaClient = (): PrismaClientType => { + if (isPostgreSQLProvider) { + return new PostgreSQLPrismaClient({ + // log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'] + }) as unknown as PrismaClientType; + } + + return new CockroachPrismaClient({ // log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'] }); +}; const globalForPrisma = globalThis as unknown as { - prisma: ReturnType | undefined; + prisma: PrismaClientType | undefined; }; export const devboxDB = globalForPrisma.prisma ?? createPrismaClient();