import { randomUUID } from "node:crypto"; import type { MediaSourceItem } from "@rakazo/adapter-kit"; import type { BrandKit, TeaserWeights } from "@rakazo/contracts"; import { TEASER_FEATURES } from "@rakazo/contracts"; import { bootstrapUserSpace } from "./bootstrap-user.js"; import type { PrismaClient } from "./client.js"; import { createDb } from "./client.js"; import type { MediaRepos } from "./media.js"; /* * Synthetic fixtures for the Media Studio Postgres tests. Nothing here describes a * real person, place, or file. */ const signupEnv = { signupsEnabled: "true", signupAllowlist: "" }; export interface MediaTestDb { prisma: PrismaClient; newUser(): Promise<{ userId: string; spaceId: string }>; cleanup(): Promise; } export function openMediaTestDb(databaseUrl: string): MediaTestDb { const db = createDb(databaseUrl, { poolMax: 8 }); const userIds: string[] = []; return { prisma: db.prisma, async newUser() { // bootstrapUserSpace derives the organization slug from the first 12 characters. const id = `md${randomUUID().replaceAll("-", "")}`; userIds.push(id); await db.prisma.user.create({ data: { id, name: "Test", email: `${id}@rakazo.test` } }); const { spaceId } = await bootstrapUserSpace(db.prisma, { id }, signupEnv, { claimDeploymentOwner: false, }); return { userId: id, spaceId }; }, async cleanup() { const memberships = await db.prisma.member.findMany({ where: { userId: { in: userIds } }, select: { organizationId: true }, }); await db.prisma.organization.deleteMany({ where: { id: { in: memberships.map((member) => member.organizationId) } }, }); await db.prisma.user.deleteMany({ where: { id: { in: userIds } } }); await db.prisma.$disconnect(); await db.pool.end(); }, }; } export const BASE_TIME = Date.UTC(2026, 0, 1, 8, 0, 0); export function sourceItem( index: number, overrides: Partial = {}, ): MediaSourceItem { return { externalId: `clip-${String(index).padStart(5, "0")}.mp4`, kind: index % 3 === 0 ? "photo" : "video", capturedAt: new Date(BASE_TIME + index * 60_000), durationMs: index % 3 === 0 ? null : 10_000, width: 1920, height: 1080, fps: 30, gpsLat: null, gpsLon: null, deviceModel: "Test Camera", albumNames: [], isFavorite: false, fileName: `clip-${index}.mp4`, sizeBytes: 1000 + index, revision: "r1", ...overrides, }; } export function testEdl(assetId: string, profileId = "example-short-vertical") { return { edlVersion: 1, output: { profileId, width: 1080, height: 1920, fps: 30, durationTargetMs: 5000, durationHardMinMs: 1000, durationHardMaxMs: 60_000, }, tracks: { video: [{ id: "c1", assetId, inMs: 0, outMs: 5000, atMs: 0, reframe: "auto" }], }, metadata: {}, }; } export const testBrandKit: BrandKit = { name: "Test Kit", colors: { primary: "#101010", secondary: "#202020", accent: "#303030", text: "#f0f0f0", background: "#000000", }, fonts: [], logoArtifactIds: [], captionPresets: [], musicBeds: [], }; export const testTeaserWeights = Object.fromEntries( TEASER_FEATURES.map((feature) => [feature, 1]), ) as TeaserWeights; export function vectorBytes(values: number[]): Uint8Array { return new Uint8Array(new Float32Array(values).buffer); } /** One of every media record in a space, linked the way the product links them. */ export async function seedMediaSpace(media: MediaRepos, spaceId: string, userId: string) { const source = await media.createSource(spaceId, { kind: "folder", label: "Footage", ownerUserId: userId, config: { path: "/media/footage" }, }); const synced = await media.upsertSourceItems(spaceId, source.id, [ sourceItem(1, { albumNames: ["Holiday"] }), sourceItem(2), ]); const [assetId, secondAssetId] = synced.changedAssetIds as [string, string]; const analysis = await media.upsertAnalysis(spaceId, assetId, { kind: "embeddings", modelId: "test-embedder", modelVersion: "1", vectors: vectorBytes([1, 0, 0]), }); await media.replaceSegments(spaceId, assetId, 1, [ { kind: "shot", startMs: 0, endMs: 4000, labels: ["beach"], transcriptExcerpt: "hello" }, ]); const segments = await media.listSegments(spaceId, [assetId]); const tracks = await media.replaceFaceTracks(spaceId, assetId, "faces-1", [ { startMs: 0, endMs: 3000, confidenceMin: 0.9, keyframesPath: `faces/${assetId}/t1.json`, embedding: vectorBytes([0.1, 0.2, 0.3]), }, ]); const [person] = await media.createPersonSuggestions(spaceId, [ { centroid: vectorBytes([0.1, 0.2, 0.3]), trackIds: tracks.map((track) => track.id) }, ]); const mark = await media.createMark(spaceId, { kind: "tattoo", label: "arm", personId: person?.id ?? null, assetId, prompt: { tMs: 1000, point: { x: 0.5, y: 0.5 } }, treatment: "blur", }); await media.replaceClusters(spaceId, "session", [ { key: "s1", title: "Morning", labelSource: "rule", startAt: new Date(BASE_TIME), endAt: new Date(BASE_TIME + 120_000), centroid: null, coverAssetId: assetId, assetIds: [assetId, secondAssetId], }, ]); const collection = (await media.listCollections(spaceId, {})).items[0]; const brandKit = await media.upsertBrandKit(spaceId, { kit: testBrandKit }); const project = await media.createProject(spaceId, userId, { title: "Teaser", goal: "teaser", profileIds: ["example-short-vertical"], collectionIds: collection ? [collection.id] : [], brandKitId: brandKit.id, }); const plan = await media.createPlanVersion(spaceId, { projectId: project.id, profileId: "example-short-vertical", edl: testEdl(assetId), createdBy: "agent", rationale: null, }); const render = await media.createRender(spaceId, { planId: plan.id, quality: "draft", createdBy: userId, }); await media.claimRender(spaceId, render.id); await media.updateRender(spaceId, render.id, { status: "done", progress: 1 }); const queuedRender = await media.createRender(spaceId, { planId: plan.id, quality: "final", createdBy: userId, }); const publication = await media.createPublication(spaceId, userId, { renderId: render.id, destination: "bundle", targetUrl: "https://example.com/offer", trackingUrl: "https://example.com/offer?utm_content=a", utm: { source: "shorts", medium: "video", campaign: "launch", content: "a" }, title: "Title", caption: "Caption", tags: ["test"], thumbnailVariant: "t1", scheduledAt: null, }); const metric = await media.recordMetric(spaceId, { publicationId: publication.id, observedAt: new Date(BASE_TIME).toISOString(), views: 100, clicks: 10, conversions: 1, revenueCents: 999, currency: "EUR", source: "manual", }); const mapping = await media.saveMetricMapping(spaceId, { name: "Default", delimiter: ",", columns: { publication: "id", observedAt: "date", views: "views" }, publicationKey: "id", revenueUnit: "major", defaultCurrency: "EUR", }); await media.putTeaserModel(spaceId, testTeaserWeights, 3); const upload = await media.beginUpload(spaceId, { assetId: secondAssetId, userId, sizeBytes: 10, sha256: "a".repeat(64), fileName: "clip.mp4", chunkBytes: 4, }); return { sourceId: source.id, assetId, secondAssetId, analysisId: analysis.id, segmentId: segments[0]?.id as string, trackId: tracks[0]?.id as string, personId: person?.id as string, markId: mark.id, collectionId: collection?.id as string, brandKitId: brandKit.id, projectId: project.id, planId: plan.id, renderId: render.id, queuedRenderId: queuedRender.id, publicationId: publication.id, metricId: metric.id, mappingId: mapping.id as string, uploadId: upload.id, }; } export type SeededMediaSpace = Awaited>;