feat(media): scaffold mvp1 media and portfolio foundation
This commit is contained in:
@@ -0,0 +1,235 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "MediaAsset" (
|
||||
"id" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"altText" TEXT,
|
||||
"source" TEXT,
|
||||
"copyright" TEXT,
|
||||
"author" TEXT,
|
||||
"tags" TEXT[],
|
||||
"storageKey" TEXT,
|
||||
"mimeType" TEXT,
|
||||
"width" INTEGER,
|
||||
"height" INTEGER,
|
||||
"sizeBytes" INTEGER,
|
||||
"isPublished" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "MediaAsset_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Artwork" (
|
||||
"id" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"medium" TEXT,
|
||||
"dimensions" TEXT,
|
||||
"year" INTEGER,
|
||||
"framing" TEXT,
|
||||
"availability" TEXT,
|
||||
"isPublished" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Artwork_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ArtworkRendition" (
|
||||
"id" TEXT NOT NULL,
|
||||
"artworkId" TEXT NOT NULL,
|
||||
"mediaAssetId" TEXT NOT NULL,
|
||||
"slot" TEXT NOT NULL,
|
||||
"width" INTEGER,
|
||||
"height" INTEGER,
|
||||
"isPrimary" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "ArtworkRendition_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Gallery" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"isVisible" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Gallery_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Album" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"isVisible" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Album_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Category" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"isVisible" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Category_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Tag" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Tag_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ArtworkGallery" (
|
||||
"id" TEXT NOT NULL,
|
||||
"artworkId" TEXT NOT NULL,
|
||||
"galleryId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ArtworkGallery_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ArtworkAlbum" (
|
||||
"id" TEXT NOT NULL,
|
||||
"artworkId" TEXT NOT NULL,
|
||||
"albumId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ArtworkAlbum_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ArtworkCategory" (
|
||||
"id" TEXT NOT NULL,
|
||||
"artworkId" TEXT NOT NULL,
|
||||
"categoryId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ArtworkCategory_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ArtworkTag" (
|
||||
"id" TEXT NOT NULL,
|
||||
"artworkId" TEXT NOT NULL,
|
||||
"tagId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ArtworkTag_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "MediaAsset_storageKey_key" ON "MediaAsset"("storageKey");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "MediaAsset_type_idx" ON "MediaAsset"("type");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "MediaAsset_isPublished_idx" ON "MediaAsset"("isPublished");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Artwork_slug_key" ON "Artwork"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Artwork_isPublished_idx" ON "Artwork"("isPublished");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ArtworkRendition_mediaAssetId_idx" ON "ArtworkRendition"("mediaAssetId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ArtworkRendition_artworkId_slot_key" ON "ArtworkRendition"("artworkId", "slot");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Gallery_slug_key" ON "Gallery"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Album_slug_key" ON "Album"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Category_slug_key" ON "Category"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Tag_slug_key" ON "Tag"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ArtworkGallery_galleryId_idx" ON "ArtworkGallery"("galleryId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ArtworkGallery_artworkId_galleryId_key" ON "ArtworkGallery"("artworkId", "galleryId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ArtworkAlbum_albumId_idx" ON "ArtworkAlbum"("albumId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ArtworkAlbum_artworkId_albumId_key" ON "ArtworkAlbum"("artworkId", "albumId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ArtworkCategory_categoryId_idx" ON "ArtworkCategory"("categoryId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ArtworkCategory_artworkId_categoryId_key" ON "ArtworkCategory"("artworkId", "categoryId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ArtworkTag_tagId_idx" ON "ArtworkTag"("tagId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ArtworkTag_artworkId_tagId_key" ON "ArtworkTag"("artworkId", "tagId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtworkRendition" ADD CONSTRAINT "ArtworkRendition_artworkId_fkey" FOREIGN KEY ("artworkId") REFERENCES "Artwork"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtworkRendition" ADD CONSTRAINT "ArtworkRendition_mediaAssetId_fkey" FOREIGN KEY ("mediaAssetId") REFERENCES "MediaAsset"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtworkGallery" ADD CONSTRAINT "ArtworkGallery_artworkId_fkey" FOREIGN KEY ("artworkId") REFERENCES "Artwork"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtworkGallery" ADD CONSTRAINT "ArtworkGallery_galleryId_fkey" FOREIGN KEY ("galleryId") REFERENCES "Gallery"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtworkAlbum" ADD CONSTRAINT "ArtworkAlbum_artworkId_fkey" FOREIGN KEY ("artworkId") REFERENCES "Artwork"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtworkAlbum" ADD CONSTRAINT "ArtworkAlbum_albumId_fkey" FOREIGN KEY ("albumId") REFERENCES "Album"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtworkCategory" ADD CONSTRAINT "ArtworkCategory_artworkId_fkey" FOREIGN KEY ("artworkId") REFERENCES "Artwork"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtworkCategory" ADD CONSTRAINT "ArtworkCategory_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "Category"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtworkTag" ADD CONSTRAINT "ArtworkTag_artworkId_fkey" FOREIGN KEY ("artworkId") REFERENCES "Artwork"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtworkTag" ADD CONSTRAINT "ArtworkTag_tagId_fkey" FOREIGN KEY ("tagId") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -1,5 +1,6 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
provider = "prisma-client"
|
||||
output = "./generated/client"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
@@ -95,3 +96,159 @@ model SystemSetting {
|
||||
|
||||
@@map("system_setting")
|
||||
}
|
||||
|
||||
model MediaAsset {
|
||||
id String @id @default(uuid())
|
||||
type String
|
||||
title String
|
||||
description String?
|
||||
altText String?
|
||||
source String?
|
||||
copyright String?
|
||||
author String?
|
||||
tags String[]
|
||||
storageKey String? @unique
|
||||
mimeType String?
|
||||
width Int?
|
||||
height Int?
|
||||
sizeBytes Int?
|
||||
isPublished Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
artworkLinks ArtworkRendition[]
|
||||
|
||||
@@index([type])
|
||||
@@index([isPublished])
|
||||
}
|
||||
|
||||
model Artwork {
|
||||
id String @id @default(uuid())
|
||||
title String
|
||||
slug String @unique
|
||||
description String?
|
||||
medium String?
|
||||
dimensions String?
|
||||
year Int?
|
||||
framing String?
|
||||
availability String?
|
||||
isPublished Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
renditions ArtworkRendition[]
|
||||
galleryLinks ArtworkGallery[]
|
||||
albumLinks ArtworkAlbum[]
|
||||
categoryLinks ArtworkCategory[]
|
||||
tagLinks ArtworkTag[]
|
||||
|
||||
@@index([isPublished])
|
||||
}
|
||||
|
||||
model ArtworkRendition {
|
||||
id String @id @default(uuid())
|
||||
artworkId String
|
||||
mediaAssetId String
|
||||
slot String
|
||||
width Int?
|
||||
height Int?
|
||||
isPrimary Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
artwork Artwork @relation(fields: [artworkId], references: [id], onDelete: Cascade)
|
||||
mediaAsset MediaAsset @relation(fields: [mediaAssetId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([artworkId, slot])
|
||||
@@index([mediaAssetId])
|
||||
}
|
||||
|
||||
model Gallery {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
slug String @unique
|
||||
description String?
|
||||
sortOrder Int @default(0)
|
||||
isVisible Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
artworkLinks ArtworkGallery[]
|
||||
}
|
||||
|
||||
model Album {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
slug String @unique
|
||||
description String?
|
||||
sortOrder Int @default(0)
|
||||
isVisible Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
artworkLinks ArtworkAlbum[]
|
||||
}
|
||||
|
||||
model Category {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
slug String @unique
|
||||
description String?
|
||||
sortOrder Int @default(0)
|
||||
isVisible Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
artworkLinks ArtworkCategory[]
|
||||
}
|
||||
|
||||
model Tag {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
slug String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
artworkLinks ArtworkTag[]
|
||||
}
|
||||
|
||||
model ArtworkGallery {
|
||||
id String @id @default(uuid())
|
||||
artworkId String
|
||||
galleryId String
|
||||
createdAt DateTime @default(now())
|
||||
artwork Artwork @relation(fields: [artworkId], references: [id], onDelete: Cascade)
|
||||
gallery Gallery @relation(fields: [galleryId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([artworkId, galleryId])
|
||||
@@index([galleryId])
|
||||
}
|
||||
|
||||
model ArtworkAlbum {
|
||||
id String @id @default(uuid())
|
||||
artworkId String
|
||||
albumId String
|
||||
createdAt DateTime @default(now())
|
||||
artwork Artwork @relation(fields: [artworkId], references: [id], onDelete: Cascade)
|
||||
album Album @relation(fields: [albumId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([artworkId, albumId])
|
||||
@@index([albumId])
|
||||
}
|
||||
|
||||
model ArtworkCategory {
|
||||
id String @id @default(uuid())
|
||||
artworkId String
|
||||
categoryId String
|
||||
createdAt DateTime @default(now())
|
||||
artwork Artwork @relation(fields: [artworkId], references: [id], onDelete: Cascade)
|
||||
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([artworkId, categoryId])
|
||||
@@index([categoryId])
|
||||
}
|
||||
|
||||
model ArtworkTag {
|
||||
id String @id @default(uuid())
|
||||
artworkId String
|
||||
tagId String
|
||||
createdAt DateTime @default(now())
|
||||
artwork Artwork @relation(fields: [artworkId], references: [id], onDelete: Cascade)
|
||||
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([artworkId, tagId])
|
||||
@@index([tagId])
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PrismaPg } from "@prisma/adapter-pg"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import { Pool } from "pg"
|
||||
import { PrismaClient } from "../prisma/generated/client/client"
|
||||
|
||||
const connectionString = process.env.DATABASE_URL
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export { db } from "./client"
|
||||
export { getMediaFoundationSummary, listArtworks, listMediaAssets } from "./media-foundation"
|
||||
export {
|
||||
createPost,
|
||||
deletePost,
|
||||
|
||||
88
packages/db/src/media-foundation.ts
Normal file
88
packages/db/src/media-foundation.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { db } from "./client"
|
||||
|
||||
export async function listMediaAssets(limit = 24) {
|
||||
return db.mediaAsset.findMany({
|
||||
orderBy: { updatedAt: "desc" },
|
||||
take: limit,
|
||||
})
|
||||
}
|
||||
|
||||
export async function listArtworks(limit = 24) {
|
||||
return db.artwork.findMany({
|
||||
orderBy: { updatedAt: "desc" },
|
||||
take: limit,
|
||||
include: {
|
||||
renditions: {
|
||||
select: {
|
||||
id: true,
|
||||
slot: true,
|
||||
mediaAssetId: true,
|
||||
},
|
||||
},
|
||||
galleryLinks: {
|
||||
include: {
|
||||
gallery: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
albumLinks: {
|
||||
include: {
|
||||
album: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
categoryLinks: {
|
||||
include: {
|
||||
category: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
tagLinks: {
|
||||
include: {
|
||||
tag: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export async function getMediaFoundationSummary() {
|
||||
const [mediaAssets, artworks, galleries, albums, categories, tags] = await Promise.all([
|
||||
db.mediaAsset.count(),
|
||||
db.artwork.count(),
|
||||
db.gallery.count(),
|
||||
db.album.count(),
|
||||
db.category.count(),
|
||||
db.tag.count(),
|
||||
])
|
||||
|
||||
return {
|
||||
mediaAssets,
|
||||
artworks,
|
||||
galleries,
|
||||
albums,
|
||||
categories,
|
||||
tags,
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
updatePostInputSchema,
|
||||
} from "@cms/content"
|
||||
import { type CrudAuditHook, type CrudMutationContext, createCrudService } from "@cms/crud"
|
||||
import type { Post } from "@prisma/client"
|
||||
import type { Post } from "../prisma/generated/client/client"
|
||||
|
||||
import { db } from "./client"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user