Merge pull request #21 from Yiling-J/feature-expression-customize-12480180928928972950
Add Expression Customization Feature
No files matched your search
@@ -0,0 +1,12 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "generations" ADD COLUMN "expression" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "expressions" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"name" TEXT NOT NULL,
|
||||
"image_id" TEXT NOT NULL,
|
||||
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" DATETIME NOT NULL,
|
||||
CONSTRAINT "expressions_image_id_fkey" FOREIGN KEY ("image_id") REFERENCES "assets" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
@@ -25,6 +25,7 @@ model Asset {
|
||||
equipments Equipment[]
|
||||
generations Generation[]
|
||||
poses Pose[]
|
||||
expressions Expression[]
|
||||
|
||||
@@map("assets")
|
||||
}
|
||||
@@ -69,6 +70,7 @@ model Generation {
|
||||
imageId String @map("image_id")
|
||||
userPrompt String? @map("user_prompt")
|
||||
pose String?
|
||||
expression String?
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@ -137,3 +139,16 @@ model Pose {
|
||||
|
||||
@@map("poses")
|
||||
}
|
||||
|
||||
model Expression {
|
||||
id String @id
|
||||
name String
|
||||
imageId String @map("image_id")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
// Relations
|
||||
image Asset @relation(fields: [imageId], references: [id])
|
||||
|
||||
@@map("expressions")
|
||||
}
|
||||
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
@@ -0,0 +1,39 @@
|
||||
import { zValidator } from '@hono/zod-validator'
|
||||
import { Hono } from 'hono'
|
||||
import { z } from 'zod'
|
||||
import { expressionService } from '../service/expression'
|
||||
|
||||
const app = new Hono()
|
||||
|
||||
// Zod schema for validation
|
||||
const createSchema = z.object({
|
||||
name: z.string().min(1),
|
||||
image: z.instanceof(File),
|
||||
})
|
||||
|
||||
const route = app
|
||||
.get('/', async (c) => {
|
||||
const expressions = await expressionService.listExpressions()
|
||||
return c.json(expressions)
|
||||
})
|
||||
.post('/', zValidator('form', createSchema), async (c) => {
|
||||
const { name, image } = c.req.valid('form')
|
||||
try {
|
||||
const expression = await expressionService.createExpression(name, image)
|
||||
return c.json(expression, 201)
|
||||
} catch (e) {
|
||||
console.error('Failed to create expression', e)
|
||||
return c.json({ error: e instanceof Error ? e.message : 'Unknown error' }, 500)
|
||||
}
|
||||
})
|
||||
.delete('/:id', async (c) => {
|
||||
const id = c.req.param('id')
|
||||
try {
|
||||
await expressionService.deleteExpression(id)
|
||||
return c.json({ success: true })
|
||||
} catch (e) {
|
||||
return c.json({ error: e instanceof Error ? e.message : 'Unknown error' }, 500)
|
||||
}
|
||||
})
|
||||
|
||||
export default route
|
||||
@@ -47,6 +47,7 @@ describe('Generation API', () => {
|
||||
['eq1', 'eq2'],
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
)
|
||||
})
|
||||
|
||||
@@ -71,6 +72,7 @@ describe('Generation API', () => {
|
||||
['eq1', 'eq2'],
|
||||
'test prompt',
|
||||
undefined,
|
||||
undefined,
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -17,6 +17,7 @@ const createSchema = z.object({
|
||||
equipmentIds: z.array(z.string()),
|
||||
userPrompt: z.string().optional(),
|
||||
poseId: z.string().optional(),
|
||||
expressionId: z.string().optional(),
|
||||
})
|
||||
|
||||
const route = app
|
||||
@@ -30,13 +31,14 @@ const route = app
|
||||
return c.json(result)
|
||||
})
|
||||
.post('/', zValidator('json', createSchema), async (c) => {
|
||||
const { characterId, equipmentIds, userPrompt, poseId } = c.req.valid('json')
|
||||
const { characterId, equipmentIds, userPrompt, poseId, expressionId } = c.req.valid('json')
|
||||
try {
|
||||
const result = await generationService.createGeneration(
|
||||
characterId,
|
||||
equipmentIds,
|
||||
userPrompt,
|
||||
poseId,
|
||||
expressionId,
|
||||
)
|
||||
return c.json(result, 201)
|
||||
} catch (e) {
|
||||
|
||||
@@ -62,3 +62,8 @@ export type Setting = Prisma.SettingModel
|
||||
*
|
||||
*/
|
||||
export type Pose = Prisma.PoseModel
|
||||
/**
|
||||
* Model Expression
|
||||
*
|
||||
*/
|
||||
export type Expression = Prisma.ExpressionModel
|
||||
@@ -84,3 +84,8 @@ export type Setting = Prisma.SettingModel
|
||||
*
|
||||
*/
|
||||
export type Pose = Prisma.PoseModel
|
||||
/**
|
||||
* Model Expression
|
||||
*
|
||||
*/
|
||||
export type Expression = Prisma.ExpressionModel
|
||||
@@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = {
|
||||
"clientVersion": "7.3.0",
|
||||
"engineVersion": "9d6ad21cbbceab97458517b147a6a09ff43aa735",
|
||||
"activeProvider": "sqlite",
|
||||
"inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../src/generated/prisma\"\n engineType = \"client\"\n runtime = \"bun\"\n}\n\ndatasource db {\n provider = \"sqlite\"\n}\n\nmodel Asset {\n id String @id\n name String\n type String\n path String\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n characters Character[]\n equipments Equipment[]\n generations Generation[]\n poses Pose[]\n\n @@map(\"assets\")\n}\n\nmodel Character {\n id String @id\n name String\n description String?\n imageId String @map(\"image_id\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n image Asset @relation(fields: [imageId], references: [id])\n generations Generation[]\n\n @@map(\"characters\")\n}\n\nmodel Equipment {\n id String @id\n name String\n description String\n category String\n subCategory String? @map(\"sub_category\")\n imageId String @map(\"image_id\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n image Asset @relation(fields: [imageId], references: [id])\n generations GenerationEquipment[]\n outfits OutfitEquipment[]\n\n @@index([category, subCategory])\n @@map(\"equipments\")\n}\n\nmodel Generation {\n id String @id\n characterId String @map(\"character_id\")\n imageId String @map(\"image_id\")\n userPrompt String? @map(\"user_prompt\")\n pose String?\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n character Character @relation(fields: [characterId], references: [id])\n image Asset @relation(fields: [imageId], references: [id])\n equipments GenerationEquipment[]\n\n @@map(\"generations\")\n}\n\nmodel GenerationEquipment {\n generationId String @map(\"generation_id\")\n equipmentId String @map(\"equipment_id\")\n\n generation Generation @relation(fields: [generationId], references: [id])\n equipment Equipment @relation(fields: [equipmentId], references: [id])\n\n @@id([generationId, equipmentId])\n @@map(\"generation_equipments\")\n}\n\nmodel Outfit {\n id String @id\n name String\n prompt String?\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n equipments OutfitEquipment[]\n\n @@map(\"outfits\")\n}\n\nmodel OutfitEquipment {\n outfitId String @map(\"outfit_id\")\n equipmentId String @map(\"equipment_id\")\n\n outfit Outfit @relation(fields: [outfitId], references: [id], onDelete: Cascade)\n equipment Equipment @relation(fields: [equipmentId], references: [id], onDelete: Cascade)\n\n @@id([outfitId, equipmentId])\n @@map(\"outfit_equipments\")\n}\n\nmodel Setting {\n key String @id\n value String\n\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n @@map(\"settings\")\n}\n\nmodel Pose {\n id String @id\n name String\n imageId String @map(\"image_id\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n image Asset @relation(fields: [imageId], references: [id])\n\n @@map(\"poses\")\n}\n",
|
||||
"inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../src/generated/prisma\"\n engineType = \"client\"\n runtime = \"bun\"\n}\n\ndatasource db {\n provider = \"sqlite\"\n}\n\nmodel Asset {\n id String @id\n name String\n type String\n path String\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n characters Character[]\n equipments Equipment[]\n generations Generation[]\n poses Pose[]\n expressions Expression[]\n\n @@map(\"assets\")\n}\n\nmodel Character {\n id String @id\n name String\n description String?\n imageId String @map(\"image_id\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n image Asset @relation(fields: [imageId], references: [id])\n generations Generation[]\n\n @@map(\"characters\")\n}\n\nmodel Equipment {\n id String @id\n name String\n description String\n category String\n subCategory String? @map(\"sub_category\")\n imageId String @map(\"image_id\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n image Asset @relation(fields: [imageId], references: [id])\n generations GenerationEquipment[]\n outfits OutfitEquipment[]\n\n @@index([category, subCategory])\n @@map(\"equipments\")\n}\n\nmodel Generation {\n id String @id\n characterId String @map(\"character_id\")\n imageId String @map(\"image_id\")\n userPrompt String? @map(\"user_prompt\")\n pose String?\n expression String?\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n character Character @relation(fields: [characterId], references: [id])\n image Asset @relation(fields: [imageId], references: [id])\n equipments GenerationEquipment[]\n\n @@map(\"generations\")\n}\n\nmodel GenerationEquipment {\n generationId String @map(\"generation_id\")\n equipmentId String @map(\"equipment_id\")\n\n generation Generation @relation(fields: [generationId], references: [id])\n equipment Equipment @relation(fields: [equipmentId], references: [id])\n\n @@id([generationId, equipmentId])\n @@map(\"generation_equipments\")\n}\n\nmodel Outfit {\n id String @id\n name String\n prompt String?\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n equipments OutfitEquipment[]\n\n @@map(\"outfits\")\n}\n\nmodel OutfitEquipment {\n outfitId String @map(\"outfit_id\")\n equipmentId String @map(\"equipment_id\")\n\n outfit Outfit @relation(fields: [outfitId], references: [id], onDelete: Cascade)\n equipment Equipment @relation(fields: [equipmentId], references: [id], onDelete: Cascade)\n\n @@id([outfitId, equipmentId])\n @@map(\"outfit_equipments\")\n}\n\nmodel Setting {\n key String @id\n value String\n\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n @@map(\"settings\")\n}\n\nmodel Pose {\n id String @id\n name String\n imageId String @map(\"image_id\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n image Asset @relation(fields: [imageId], references: [id])\n\n @@map(\"poses\")\n}\n\nmodel Expression {\n id String @id\n name String\n imageId String @map(\"image_id\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n // Relations\n image Asset @relation(fields: [imageId], references: [id])\n\n @@map(\"expressions\")\n}\n",
|
||||
"runtimeDataModel": {
|
||||
"models": {},
|
||||
"enums": {},
|
||||
@@ -28,7 +28,7 @@ const config: runtime.GetPrismaClientConfig = {
|
||||
}
|
||||
}
|
||||
|
||||
config.runtimeDataModel = JSON.parse("{\"models\":{\"Asset\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"path\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"characters\",\"kind\":\"object\",\"type\":\"Character\",\"relationName\":\"AssetToCharacter\"},{\"name\":\"equipments\",\"kind\":\"object\",\"type\":\"Equipment\",\"relationName\":\"AssetToEquipment\"},{\"name\":\"generations\",\"kind\":\"object\",\"type\":\"Generation\",\"relationName\":\"AssetToGeneration\"},{\"name\":\"poses\",\"kind\":\"object\",\"type\":\"Pose\",\"relationName\":\"AssetToPose\"}],\"dbName\":\"assets\"},\"Character\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"imageId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"image_id\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"image\",\"kind\":\"object\",\"type\":\"Asset\",\"relationName\":\"AssetToCharacter\"},{\"name\":\"generations\",\"kind\":\"object\",\"type\":\"Generation\",\"relationName\":\"CharacterToGeneration\"}],\"dbName\":\"characters\"},\"Equipment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"category\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"subCategory\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"sub_category\"},{\"name\":\"imageId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"image_id\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"image\",\"kind\":\"object\",\"type\":\"Asset\",\"relationName\":\"AssetToEquipment\"},{\"name\":\"generations\",\"kind\":\"object\",\"type\":\"GenerationEquipment\",\"relationName\":\"EquipmentToGenerationEquipment\"},{\"name\":\"outfits\",\"kind\":\"object\",\"type\":\"OutfitEquipment\",\"relationName\":\"EquipmentToOutfitEquipment\"}],\"dbName\":\"equipments\"},\"Generation\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"characterId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"character_id\"},{\"name\":\"imageId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"image_id\"},{\"name\":\"userPrompt\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"user_prompt\"},{\"name\":\"pose\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"character\",\"kind\":\"object\",\"type\":\"Character\",\"relationName\":\"CharacterToGeneration\"},{\"name\":\"image\",\"kind\":\"object\",\"type\":\"Asset\",\"relationName\":\"AssetToGeneration\"},{\"name\":\"equipments\",\"kind\":\"object\",\"type\":\"GenerationEquipment\",\"relationName\":\"GenerationToGenerationEquipment\"}],\"dbName\":\"generations\"},\"GenerationEquipment\":{\"fields\":[{\"name\":\"generationId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"generation_id\"},{\"name\":\"equipmentId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"equipment_id\"},{\"name\":\"generation\",\"kind\":\"object\",\"type\":\"Generation\",\"relationName\":\"GenerationToGenerationEquipment\"},{\"name\":\"equipment\",\"kind\":\"object\",\"type\":\"Equipment\",\"relationName\":\"EquipmentToGenerationEquipment\"}],\"dbName\":\"generation_equipments\"},\"Outfit\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"prompt\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"equipments\",\"kind\":\"object\",\"type\":\"OutfitEquipment\",\"relationName\":\"OutfitToOutfitEquipment\"}],\"dbName\":\"outfits\"},\"OutfitEquipment\":{\"fields\":[{\"name\":\"outfitId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"outfit_id\"},{\"name\":\"equipmentId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"equipment_id\"},{\"name\":\"outfit\",\"kind\":\"object\",\"type\":\"Outfit\",\"relationNaLine truncated
|
||||
config.runtimeDataModel = JSON.parse("{\"models\":{\"Asset\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"path\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"characters\",\"kind\":\"object\",\"type\":\"Character\",\"relationName\":\"AssetToCharacter\"},{\"name\":\"equipments\",\"kind\":\"object\",\"type\":\"Equipment\",\"relationName\":\"AssetToEquipment\"},{\"name\":\"generations\",\"kind\":\"object\",\"type\":\"Generation\",\"relationName\":\"AssetToGeneration\"},{\"name\":\"poses\",\"kind\":\"object\",\"type\":\"Pose\",\"relationName\":\"AssetToPose\"},{\"name\":\"expressions\",\"kind\":\"object\",\"type\":\"Expression\",\"relationName\":\"AssetToExpression\"}],\"dbName\":\"assets\"},\"Character\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"imageId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"image_id\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"image\",\"kind\":\"object\",\"type\":\"Asset\",\"relationName\":\"AssetToCharacter\"},{\"name\":\"generations\",\"kind\":\"object\",\"type\":\"Generation\",\"relationName\":\"CharacterToGeneration\"}],\"dbName\":\"characters\"},\"Equipment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"category\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"subCategory\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"sub_category\"},{\"name\":\"imageId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"image_id\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"image\",\"kind\":\"object\",\"type\":\"Asset\",\"relationName\":\"AssetToEquipment\"},{\"name\":\"generations\",\"kind\":\"object\",\"type\":\"GenerationEquipment\",\"relationName\":\"EquipmentToGenerationEquipment\"},{\"name\":\"outfits\",\"kind\":\"object\",\"type\":\"OutfitEquipment\",\"relationName\":\"EquipmentToOutfitEquipment\"}],\"dbName\":\"equipments\"},\"Generation\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"characterId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"character_id\"},{\"name\":\"imageId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"image_id\"},{\"name\":\"userPrompt\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"user_prompt\"},{\"name\":\"pose\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expression\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"character\",\"kind\":\"object\",\"type\":\"Character\",\"relationName\":\"CharacterToGeneration\"},{\"name\":\"image\",\"kind\":\"object\",\"type\":\"Asset\",\"relationName\":\"AssetToGeneration\"},{\"name\":\"equipments\",\"kind\":\"object\",\"type\":\"GenerationEquipment\",\"relationName\":\"GenerationToGenerationEquipment\"}],\"dbName\":\"generations\"},\"GenerationEquipment\":{\"fields\":[{\"name\":\"generationId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"generation_id\"},{\"name\":\"equipmentId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"equipment_id\"},{\"name\":\"generation\",\"kind\":\"object\",\"type\":\"Generation\",\"relationName\":\"GenerationToGenerationEquipment\"},{\"name\":\"equipment\",\"kind\":\"object\",\"type\":\"Equipment\",\"relationName\":\"EquipmentToGenerationEquipment\"}],\"dbName\":\"generation_equipments\"},\"Outfit\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"prompt\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"equipments\",\"kind\":\"object\",\"type\":\"OutfitEquipment\",\"relationName\":\"OutfitToOutfitEquipment\"}],\"dbName\":\"outfits\"},\"OutfitEquipment\":{\"fields\":[{\"name\":\"outfitId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"outfiLine truncated
|
||||
|
||||
async function decodeBase64AsWasm(wasmBase64: string): Promise<WebAssembly.Module> {
|
||||
const { Buffer } = await import('node:buffer')
|
||||
@@ -265,6 +265,16 @@ export interface PrismaClient<
|
||||
* ```
|
||||
*/
|
||||
get pose(): Prisma.PoseDelegate<ExtArgs, { omit: OmitOpts }>;
|
||||
|
||||
/**
|
||||
* `prisma.expression`: Exposes CRUD operations for the **Expression** model.
|
||||
* Example usage:
|
||||
* ```ts
|
||||
* // Fetch zero or more Expressions
|
||||
* const expressions = await prisma.expression.findMany()
|
||||
* ```
|
||||
*/
|
||||
get expression(): Prisma.ExpressionDelegate<ExtArgs, { omit: OmitOpts }>;
|
||||
}
|
||||
|
||||
export function getPrismaClientClass(): PrismaClientConstructor {
|
||||
|
||||
@@ -392,7 +392,8 @@ export const ModelName = {
|
||||
Outfit: 'Outfit',
|
||||
OutfitEquipment: 'OutfitEquipment',
|
||||
Setting: 'Setting',
|
||||
Pose: 'Pose'
|
||||
Pose: 'Pose',
|
||||
Expression: 'Expression'
|
||||
} as const
|
||||
|
||||
export type ModelName = (typeof ModelName)[keyof typeof ModelName]
|
||||
@@ -408,7 +409,7 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
|
||||
omit: GlobalOmitOptions
|
||||
}
|
||||
meta: {
|
||||
modelProps: "asset" | "character" | "equipment" | "generation" | "generationEquipment" | "outfit" | "outfitEquipment" | "setting" | "pose"
|
||||
modelProps: "asset" | "character" | "equipment" | "generation" | "generationEquipment" | "outfit" | "outfitEquipment" | "setting" | "pose" | "expression"
|
||||
txIsolationLevel: TransactionIsolationLevel
|
||||
}
|
||||
model: {
|
||||
@@ -1078,6 +1079,80 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
|
||||
}
|
||||
}
|
||||
}
|
||||
Expression: {
|
||||
payload: Prisma.$ExpressionPayload<ExtArgs>
|
||||
fields: Prisma.ExpressionFieldRefs
|
||||
operations: {
|
||||
findUnique: {
|
||||
args: Prisma.ExpressionFindUniqueArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload> | null
|
||||
}
|
||||
findUniqueOrThrow: {
|
||||
args: Prisma.ExpressionFindUniqueOrThrowArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload>
|
||||
}
|
||||
findFirst: {
|
||||
args: Prisma.ExpressionFindFirstArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload> | null
|
||||
}
|
||||
findFirstOrThrow: {
|
||||
args: Prisma.ExpressionFindFirstOrThrowArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload>
|
||||
}
|
||||
findMany: {
|
||||
args: Prisma.ExpressionFindManyArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload>[]
|
||||
}
|
||||
create: {
|
||||
args: Prisma.ExpressionCreateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload>
|
||||
}
|
||||
createMany: {
|
||||
args: Prisma.ExpressionCreateManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
createManyAndReturn: {
|
||||
args: Prisma.ExpressionCreateManyAndReturnArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload>[]
|
||||
}
|
||||
delete: {
|
||||
args: Prisma.ExpressionDeleteArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload>
|
||||
}
|
||||
update: {
|
||||
args: Prisma.ExpressionUpdateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload>
|
||||
}
|
||||
deleteMany: {
|
||||
args: Prisma.ExpressionDeleteManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
updateMany: {
|
||||
args: Prisma.ExpressionUpdateManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
updateManyAndReturn: {
|
||||
args: Prisma.ExpressionUpdateManyAndReturnArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload>[]
|
||||
}
|
||||
upsert: {
|
||||
args: Prisma.ExpressionUpsertArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$ExpressionPayload>
|
||||
}
|
||||
aggregate: {
|
||||
args: Prisma.ExpressionAggregateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.AggregateExpression>
|
||||
}
|
||||
groupBy: {
|
||||
args: Prisma.ExpressionGroupByArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.ExpressionGroupByOutputType>[]
|
||||
}
|
||||
count: {
|
||||
args: Prisma.ExpressionCountArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.ExpressionCountAggregateOutputType> | number
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} & {
|
||||
other: {
|
||||
@@ -1158,6 +1233,7 @@ export const GenerationScalarFieldEnum = {
|
||||
imageId: 'imageId',
|
||||
userPrompt: 'userPrompt',
|
||||
pose: 'pose',
|
||||
expression: 'expression',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
@@ -1213,6 +1289,17 @@ export const PoseScalarFieldEnum = {
|
||||
export type PoseScalarFieldEnum = (typeof PoseScalarFieldEnum)[keyof typeof PoseScalarFieldEnum]
|
||||
|
||||
|
||||
export const ExpressionScalarFieldEnum = {
|
||||
id: 'id',
|
||||
name: 'name',
|
||||
imageId: 'imageId',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
|
||||
export type ExpressionScalarFieldEnum = (typeof ExpressionScalarFieldEnum)[keyof typeof ExpressionScalarFieldEnum]
|
||||
|
||||
|
||||
export const SortOrder = {
|
||||
asc: 'asc',
|
||||
desc: 'desc'
|
||||
@@ -1359,6 +1446,7 @@ export type GlobalOmitConfig = {
|
||||
outfitEquipment?: Prisma.OutfitEquipmentOmit
|
||||
setting?: Prisma.SettingOmit
|
||||
pose?: Prisma.PoseOmit
|
||||
expression?: Prisma.ExpressionOmit
|
||||
}
|
||||
|
||||
/* Types for Logging */
|
||||
|
||||
@@ -59,7 +59,8 @@ export const ModelName = {
|
||||
Outfit: 'Outfit',
|
||||
OutfitEquipment: 'OutfitEquipment',
|
||||
Setting: 'Setting',
|
||||
Pose: 'Pose'
|
||||
Pose: 'Pose',
|
||||
Expression: 'Expression'
|
||||
} as const
|
||||
|
||||
export type ModelName = (typeof ModelName)[keyof typeof ModelName]
|
||||
@@ -119,6 +120,7 @@ export const GenerationScalarFieldEnum = {
|
||||
imageId: 'imageId',
|
||||
userPrompt: 'userPrompt',
|
||||
pose: 'pose',
|
||||
expression: 'expression',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
@@ -174,6 +176,17 @@ export const PoseScalarFieldEnum = {
|
||||
export type PoseScalarFieldEnum = (typeof PoseScalarFieldEnum)[keyof typeof PoseScalarFieldEnum]
|
||||
|
||||
|
||||
export const ExpressionScalarFieldEnum = {
|
||||
id: 'id',
|
||||
name: 'name',
|
||||
imageId: 'imageId',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
|
||||
export type ExpressionScalarFieldEnum = (typeof ExpressionScalarFieldEnum)[keyof typeof ExpressionScalarFieldEnum]
|
||||
|
||||
|
||||
export const SortOrder = {
|
||||
asc: 'asc',
|
||||
desc: 'desc'
|
||||
|
||||
@@ -17,4 +17,5 @@ export type * from './models/Outfit.ts'
|
||||
export type * from './models/OutfitEquipment.ts'
|
||||
export type * from './models/Setting.ts'
|
||||
export type * from './models/Pose.ts'
|
||||
export type * from './models/Expression.ts'
|
||||
export type * from './commonInputTypes.ts'
|
||||
@@ -194,6 +194,7 @@ export type AssetWhereInput = {
|
||||
equipments?: Prisma.EquipmentListRelationFilter
|
||||
generations?: Prisma.GenerationListRelationFilter
|
||||
poses?: Prisma.PoseListRelationFilter
|
||||
expressions?: Prisma.ExpressionListRelationFilter
|
||||
}
|
||||
|
||||
export type AssetOrderByWithRelationInput = {
|
||||
@@ -207,6 +208,7 @@ export type AssetOrderByWithRelationInput = {
|
||||
equipments?: Prisma.EquipmentOrderByRelationAggregateInput
|
||||
generations?: Prisma.GenerationOrderByRelationAggregateInput
|
||||
poses?: Prisma.PoseOrderByRelationAggregateInput
|
||||
expressions?: Prisma.ExpressionOrderByRelationAggregateInput
|
||||
}
|
||||
|
||||
export type AssetWhereUniqueInput = Prisma.AtLeast<{
|
||||
@@ -223,6 +225,7 @@ export type AssetWhereUniqueInput = Prisma.AtLeast<{
|
||||
equipments?: Prisma.EquipmentListRelationFilter
|
||||
generations?: Prisma.GenerationListRelationFilter
|
||||
poses?: Prisma.PoseListRelationFilter
|
||||
expressions?: Prisma.ExpressionListRelationFilter
|
||||
}, "id">
|
||||
|
||||
export type AssetOrderByWithAggregationInput = {
|
||||
@@ -260,6 +263,7 @@ export type AssetCreateInput = {
|
||||
equipments?: Prisma.EquipmentCreateNestedManyWithoutImageInput
|
||||
generations?: Prisma.GenerationCreateNestedManyWithoutImageInput
|
||||
poses?: Prisma.PoseCreateNestedManyWithoutImageInput
|
||||
expressions?: Prisma.ExpressionCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedCreateInput = {
|
||||
@@ -273,6 +277,7 @@ export type AssetUncheckedCreateInput = {
|
||||
equipments?: Prisma.EquipmentUncheckedCreateNestedManyWithoutImageInput
|
||||
generations?: Prisma.GenerationUncheckedCreateNestedManyWithoutImageInput
|
||||
poses?: Prisma.PoseUncheckedCreateNestedManyWithoutImageInput
|
||||
expressions?: Prisma.ExpressionUncheckedCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetUpdateInput = {
|
||||
@@ -286,6 +291,7 @@ export type AssetUpdateInput = {
|
||||
equipments?: Prisma.EquipmentUpdateManyWithoutImageNestedInput
|
||||
generations?: Prisma.GenerationUpdateManyWithoutImageNestedInput
|
||||
poses?: Prisma.PoseUpdateManyWithoutImageNestedInput
|
||||
expressions?: Prisma.ExpressionUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedUpdateInput = {
|
||||
@@ -299,6 +305,7 @@ export type AssetUncheckedUpdateInput = {
|
||||
equipments?: Prisma.EquipmentUncheckedUpdateManyWithoutImageNestedInput
|
||||
generations?: Prisma.GenerationUncheckedUpdateManyWithoutImageNestedInput
|
||||
poses?: Prisma.PoseUncheckedUpdateManyWithoutImageNestedInput
|
||||
expressions?: Prisma.ExpressionUncheckedUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetCreateManyInput = {
|
||||
@@ -424,6 +431,20 @@ export type AssetUpdateOneRequiredWithoutPosesNestedInput = {
|
||||
update?: Prisma.XOR<Prisma.XOR<Prisma.AssetUpdateToOneWithWhereWithoutPosesInput, Prisma.AssetUpdateWithoutPosesInput>, Prisma.AssetUncheckedUpdateWithoutPosesInput>
|
||||
}
|
||||
|
||||
export type AssetCreateNestedOneWithoutExpressionsInput = {
|
||||
create?: Prisma.XOR<Prisma.AssetCreateWithoutExpressionsInput, Prisma.AssetUncheckedCreateWithoutExpressionsInput>
|
||||
connectOrCreate?: Prisma.AssetCreateOrConnectWithoutExpressionsInput
|
||||
connect?: Prisma.AssetWhereUniqueInput
|
||||
}
|
||||
|
||||
export type AssetUpdateOneRequiredWithoutExpressionsNestedInput = {
|
||||
create?: Prisma.XOR<Prisma.AssetCreateWithoutExpressionsInput, Prisma.AssetUncheckedCreateWithoutExpressionsInput>
|
||||
connectOrCreate?: Prisma.AssetCreateOrConnectWithoutExpressionsInput
|
||||
upsert?: Prisma.AssetUpsertWithoutExpressionsInput
|
||||
connect?: Prisma.AssetWhereUniqueInput
|
||||
update?: Prisma.XOR<Prisma.XOR<Prisma.AssetUpdateToOneWithWhereWithoutExpressionsInput, Prisma.AssetUpdateWithoutExpressionsInput>, Prisma.AssetUncheckedUpdateWithoutExpressionsInput>
|
||||
}
|
||||
|
||||
export type AssetCreateWithoutCharactersInput = {
|
||||
id: string
|
||||
name: string
|
||||
@@ -434,6 +455,7 @@ export type AssetCreateWithoutCharactersInput = {
|
||||
equipments?: Prisma.EquipmentCreateNestedManyWithoutImageInput
|
||||
generations?: Prisma.GenerationCreateNestedManyWithoutImageInput
|
||||
poses?: Prisma.PoseCreateNestedManyWithoutImageInput
|
||||
expressions?: Prisma.ExpressionCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedCreateWithoutCharactersInput = {
|
||||
@@ -446,6 +468,7 @@ export type AssetUncheckedCreateWithoutCharactersInput = {
|
||||
equipments?: Prisma.EquipmentUncheckedCreateNestedManyWithoutImageInput
|
||||
generations?: Prisma.GenerationUncheckedCreateNestedManyWithoutImageInput
|
||||
poses?: Prisma.PoseUncheckedCreateNestedManyWithoutImageInput
|
||||
expressions?: Prisma.ExpressionUncheckedCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetCreateOrConnectWithoutCharactersInput = {
|
||||
@@ -474,6 +497,7 @@ export type AssetUpdateWithoutCharactersInput = {
|
||||
equipments?: Prisma.EquipmentUpdateManyWithoutImageNestedInput
|
||||
generations?: Prisma.GenerationUpdateManyWithoutImageNestedInput
|
||||
poses?: Prisma.PoseUpdateManyWithoutImageNestedInput
|
||||
expressions?: Prisma.ExpressionUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedUpdateWithoutCharactersInput = {
|
||||
@@ -486,6 +510,7 @@ export type AssetUncheckedUpdateWithoutCharactersInput = {
|
||||
equipments?: Prisma.EquipmentUncheckedUpdateManyWithoutImageNestedInput
|
||||
generations?: Prisma.GenerationUncheckedUpdateManyWithoutImageNestedInput
|
||||
poses?: Prisma.PoseUncheckedUpdateManyWithoutImageNestedInput
|
||||
expressions?: Prisma.ExpressionUncheckedUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetCreateWithoutEquipmentsInput = {
|
||||
@@ -498,6 +523,7 @@ export type AssetCreateWithoutEquipmentsInput = {
|
||||
characters?: Prisma.CharacterCreateNestedManyWithoutImageInput
|
||||
generations?: Prisma.GenerationCreateNestedManyWithoutImageInput
|
||||
poses?: Prisma.PoseCreateNestedManyWithoutImageInput
|
||||
expressions?: Prisma.ExpressionCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedCreateWithoutEquipmentsInput = {
|
||||
@@ -510,6 +536,7 @@ export type AssetUncheckedCreateWithoutEquipmentsInput = {
|
||||
characters?: Prisma.CharacterUncheckedCreateNestedManyWithoutImageInput
|
||||
generations?: Prisma.GenerationUncheckedCreateNestedManyWithoutImageInput
|
||||
poses?: Prisma.PoseUncheckedCreateNestedManyWithoutImageInput
|
||||
expressions?: Prisma.ExpressionUncheckedCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetCreateOrConnectWithoutEquipmentsInput = {
|
||||
@@ -538,6 +565,7 @@ export type AssetUpdateWithoutEquipmentsInput = {
|
||||
characters?: Prisma.CharacterUpdateManyWithoutImageNestedInput
|
||||
generations?: Prisma.GenerationUpdateManyWithoutImageNestedInput
|
||||
poses?: Prisma.PoseUpdateManyWithoutImageNestedInput
|
||||
expressions?: Prisma.ExpressionUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedUpdateWithoutEquipmentsInput = {
|
||||
@@ -550,6 +578,7 @@ export type AssetUncheckedUpdateWithoutEquipmentsInput = {
|
||||
characters?: Prisma.CharacterUncheckedUpdateManyWithoutImageNestedInput
|
||||
generations?: Prisma.GenerationUncheckedUpdateManyWithoutImageNestedInput
|
||||
poses?: Prisma.PoseUncheckedUpdateManyWithoutImageNestedInput
|
||||
expressions?: Prisma.ExpressionUncheckedUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetCreateWithoutGenerationsInput = {
|
||||
@@ -562,6 +591,7 @@ export type AssetCreateWithoutGenerationsInput = {
|
||||
characters?: Prisma.CharacterCreateNestedManyWithoutImageInput
|
||||
equipments?: Prisma.EquipmentCreateNestedManyWithoutImageInput
|
||||
poses?: Prisma.PoseCreateNestedManyWithoutImageInput
|
||||
expressions?: Prisma.ExpressionCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedCreateWithoutGenerationsInput = {
|
||||
@@ -574,6 +604,7 @@ export type AssetUncheckedCreateWithoutGenerationsInput = {
|
||||
characters?: Prisma.CharacterUncheckedCreateNestedManyWithoutImageInput
|
||||
equipments?: Prisma.EquipmentUncheckedCreateNestedManyWithoutImageInput
|
||||
poses?: Prisma.PoseUncheckedCreateNestedManyWithoutImageInput
|
||||
expressions?: Prisma.ExpressionUncheckedCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetCreateOrConnectWithoutGenerationsInput = {
|
||||
@@ -602,6 +633,7 @@ export type AssetUpdateWithoutGenerationsInput = {
|
||||
characters?: Prisma.CharacterUpdateManyWithoutImageNestedInput
|
||||
equipments?: Prisma.EquipmentUpdateManyWithoutImageNestedInput
|
||||
poses?: Prisma.PoseUpdateManyWithoutImageNestedInput
|
||||
expressions?: Prisma.ExpressionUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedUpdateWithoutGenerationsInput = {
|
||||
@@ -614,6 +646,7 @@ export type AssetUncheckedUpdateWithoutGenerationsInput = {
|
||||
characters?: Prisma.CharacterUncheckedUpdateManyWithoutImageNestedInput
|
||||
equipments?: Prisma.EquipmentUncheckedUpdateManyWithoutImageNestedInput
|
||||
poses?: Prisma.PoseUncheckedUpdateManyWithoutImageNestedInput
|
||||
expressions?: Prisma.ExpressionUncheckedUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetCreateWithoutPosesInput = {
|
||||
@@ -626,6 +659,7 @@ export type AssetCreateWithoutPosesInput = {
|
||||
characters?: Prisma.CharacterCreateNestedManyWithoutImageInput
|
||||
equipments?: Prisma.EquipmentCreateNestedManyWithoutImageInput
|
||||
generations?: Prisma.GenerationCreateNestedManyWithoutImageInput
|
||||
expressions?: Prisma.ExpressionCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedCreateWithoutPosesInput = {
|
||||
@@ -638,6 +672,7 @@ export type AssetUncheckedCreateWithoutPosesInput = {
|
||||
characters?: Prisma.CharacterUncheckedCreateNestedManyWithoutImageInput
|
||||
equipments?: Prisma.EquipmentUncheckedCreateNestedManyWithoutImageInput
|
||||
generations?: Prisma.GenerationUncheckedCreateNestedManyWithoutImageInput
|
||||
expressions?: Prisma.ExpressionUncheckedCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetCreateOrConnectWithoutPosesInput = {
|
||||
@@ -666,6 +701,7 @@ export type AssetUpdateWithoutPosesInput = {
|
||||
characters?: Prisma.CharacterUpdateManyWithoutImageNestedInput
|
||||
equipments?: Prisma.EquipmentUpdateManyWithoutImageNestedInput
|
||||
generations?: Prisma.GenerationUpdateManyWithoutImageNestedInput
|
||||
expressions?: Prisma.ExpressionUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedUpdateWithoutPosesInput = {
|
||||
@@ -678,6 +714,75 @@ export type AssetUncheckedUpdateWithoutPosesInput = {
|
||||
characters?: Prisma.CharacterUncheckedUpdateManyWithoutImageNestedInput
|
||||
equipments?: Prisma.EquipmentUncheckedUpdateManyWithoutImageNestedInput
|
||||
generations?: Prisma.GenerationUncheckedUpdateManyWithoutImageNestedInput
|
||||
expressions?: Prisma.ExpressionUncheckedUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetCreateWithoutExpressionsInput = {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
path: string
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
characters?: Prisma.CharacterCreateNestedManyWithoutImageInput
|
||||
equipments?: Prisma.EquipmentCreateNestedManyWithoutImageInput
|
||||
generations?: Prisma.GenerationCreateNestedManyWithoutImageInput
|
||||
poses?: Prisma.PoseCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedCreateWithoutExpressionsInput = {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
path: string
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
characters?: Prisma.CharacterUncheckedCreateNestedManyWithoutImageInput
|
||||
equipments?: Prisma.EquipmentUncheckedCreateNestedManyWithoutImageInput
|
||||
generations?: Prisma.GenerationUncheckedCreateNestedManyWithoutImageInput
|
||||
poses?: Prisma.PoseUncheckedCreateNestedManyWithoutImageInput
|
||||
}
|
||||
|
||||
export type AssetCreateOrConnectWithoutExpressionsInput = {
|
||||
where: Prisma.AssetWhereUniqueInput
|
||||
create: Prisma.XOR<Prisma.AssetCreateWithoutExpressionsInput, Prisma.AssetUncheckedCreateWithoutExpressionsInput>
|
||||
}
|
||||
|
||||
export type AssetUpsertWithoutExpressionsInput = {
|
||||
update: Prisma.XOR<Prisma.AssetUpdateWithoutExpressionsInput, Prisma.AssetUncheckedUpdateWithoutExpressionsInput>
|
||||
create: Prisma.XOR<Prisma.AssetCreateWithoutExpressionsInput, Prisma.AssetUncheckedCreateWithoutExpressionsInput>
|
||||
where?: Prisma.AssetWhereInput
|
||||
}
|
||||
|
||||
export type AssetUpdateToOneWithWhereWithoutExpressionsInput = {
|
||||
where?: Prisma.AssetWhereInput
|
||||
data: Prisma.XOR<Prisma.AssetUpdateWithoutExpressionsInput, Prisma.AssetUncheckedUpdateWithoutExpressionsInput>
|
||||
}
|
||||
|
||||
export type AssetUpdateWithoutExpressionsInput = {
|
||||
id?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
name?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
type?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
path?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
characters?: Prisma.CharacterUpdateManyWithoutImageNestedInput
|
||||
equipments?: Prisma.EquipmentUpdateManyWithoutImageNestedInput
|
||||
generations?: Prisma.GenerationUpdateManyWithoutImageNestedInput
|
||||
poses?: Prisma.PoseUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
export type AssetUncheckedUpdateWithoutExpressionsInput = {
|
||||
id?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
name?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
type?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
path?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
characters?: Prisma.CharacterUncheckedUpdateManyWithoutImageNestedInput
|
||||
equipments?: Prisma.EquipmentUncheckedUpdateManyWithoutImageNestedInput
|
||||
generations?: Prisma.GenerationUncheckedUpdateManyWithoutImageNestedInput
|
||||
poses?: Prisma.PoseUncheckedUpdateManyWithoutImageNestedInput
|
||||
}
|
||||
|
||||
|
||||
@@ -690,6 +795,7 @@ export type AssetCountOutputType = {
|
||||
equipments: number
|
||||
generations: number
|
||||
poses: number
|
||||
expressions: number
|
||||
}
|
||||
|
||||
export type AssetCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||
@@ -697,6 +803,7 @@ export type AssetCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.
|
||||
equipments?: boolean | AssetCountOutputTypeCountEquipmentsArgs
|
||||
generations?: boolean | AssetCountOutputTypeCountGenerationsArgs
|
||||
poses?: boolean | AssetCountOutputTypeCountPosesArgs
|
||||
expressions?: boolean | AssetCountOutputTypeCountExpressionsArgs
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -737,6 +844,13 @@ export type AssetCountOutputTypeCountPosesArgs<ExtArgs extends runtime.Types.Ext
|
||||
where?: Prisma.PoseWhereInput
|
||||
}
|
||||
|
||||
/**
|
||||
* AssetCountOutputType without action
|
||||
*/
|
||||
export type AssetCountOutputTypeCountExpressionsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||
where?: Prisma.ExpressionWhereInput
|
||||
}
|
||||
|
||||
|
||||
export type AssetSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
||||
id?: boolean
|
||||
@@ -749,6 +863,7 @@ export type AssetSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs =
|
||||
equipments?: boolean | Prisma.Asset$equipmentsArgs<ExtArgs>
|
||||
generations?: boolean | Prisma.Asset$generationsArgs<ExtArgs>
|
||||
poses?: boolean | Prisma.Asset$posesArgs<ExtArgs>
|
||||
expressions?: boolean | Prisma.Asset$expressionsArgs<ExtArgs>
|
||||
_count?: boolean | Prisma.AssetCountOutputTypeDefaultArgs<ExtArgs>
|
||||
}, ExtArgs["result"]["asset"]>
|
||||
|
||||
@@ -785,6 +900,7 @@ export type AssetInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs =
|
||||
equipments?: boolean | Prisma.Asset$equipmentsArgs<ExtArgs>
|
||||
generations?: boolean | Prisma.Asset$generationsArgs<ExtArgs>
|
||||
poses?: boolean | Prisma.Asset$posesArgs<ExtArgs>
|
||||
expressions?: boolean | Prisma.Asset$expressionsArgs<ExtArgs>
|
||||
_count?: boolean | Prisma.AssetCountOutputTypeDefaultArgs<ExtArgs>
|
||||
}
|
||||
export type AssetIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {}
|
||||
@@ -797,6 +913,7 @@ export type $AssetPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs
|
||||
equipments: Prisma.$EquipmentPayload<ExtArgs>[]
|
||||
generations: Prisma.$GenerationPayload<ExtArgs>[]
|
||||
poses: Prisma.$PosePayload<ExtArgs>[]
|
||||
expressions: Prisma.$ExpressionPayload<ExtArgs>[]
|
||||
}
|
||||
scalars: runtime.Types.Extensions.GetPayloadResult<{
|
||||
id: string
|
||||
@@ -1203,6 +1320,7 @@ export interface Prisma__AssetClient<T, Null = never, ExtArgs extends runtime.Ty
|
||||
equipments<T extends Prisma.Asset$equipmentsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Asset$equipmentsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$EquipmentPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
|
||||
generations<T extends Prisma.Asset$generationsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Asset$generationsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$GenerationPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
|
||||
poses<T extends Prisma.Asset$posesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Asset$posesArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$PosePayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
|
||||
expressions<T extends Prisma.Asset$expressionsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Asset$expressionsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$ExpressionPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
@@ -1719,6 +1837,30 @@ export type Asset$posesArgs<ExtArgs extends runtime.Types.Extensions.InternalArg
|
||||
distinct?: Prisma.PoseScalarFieldEnum | Prisma.PoseScalarFieldEnum[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Asset.expressions
|
||||
*/
|
||||
export type Asset$expressionsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||
/**
|
||||
* Select specific fields to fetch from the Expression
|
||||
*/
|
||||
select?: Prisma.ExpressionSelect<ExtArgs> | null
|
||||
/**
|
||||
* Omit specific fields from the Expression
|
||||
*/
|
||||
omit?: Prisma.ExpressionOmit<ExtArgs> | null
|
||||
/**
|
||||
* Choose, which related nodes to fetch as well
|
||||
*/
|
||||
include?: Prisma.ExpressionInclude<ExtArgs> | null
|
||||
where?: Prisma.ExpressionWhereInput
|
||||
orderBy?: Prisma.ExpressionOrderByWithRelationInput | Prisma.ExpressionOrderByWithRelationInput[]
|
||||
cursor?: Prisma.ExpressionWhereUniqueInput
|
||||
take?: number
|
||||
skip?: number
|
||||
distinct?: Prisma.ExpressionScalarFieldEnum | Prisma.ExpressionScalarFieldEnum[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Asset without action
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,7 @@ export type GenerationMinAggregateOutputType = {
|
||||
imageId: string | null
|
||||
userPrompt: string | null
|
||||
pose: string | null
|
||||
expression: string | null
|
||||
createdAt: Date | null
|
||||
updatedAt: Date | null
|
||||
}
|
||||
@@ -40,6 +41,7 @@ export type GenerationMaxAggregateOutputType = {
|
||||
imageId: string | null
|
||||
userPrompt: string | null
|
||||
pose: string | null
|
||||
expression: string | null
|
||||
createdAt: Date | null
|
||||
updatedAt: Date | null
|
||||
}
|
||||
@@ -50,6 +52,7 @@ export type GenerationCountAggregateOutputType = {
|
||||
imageId: number
|
||||
userPrompt: number
|
||||
pose: number
|
||||
expression: number
|
||||
createdAt: number
|
||||
updatedAt: number
|
||||
_all: number
|
||||
@@ -62,6 +65,7 @@ export type GenerationMinAggregateInputType = {
|
||||
imageId?: true
|
||||
userPrompt?: true
|
||||
pose?: true
|
||||
expression?: true
|
||||
createdAt?: true
|
||||
updatedAt?: true
|
||||
}
|
||||
@@ -72,6 +76,7 @@ export type GenerationMaxAggregateInputType = {
|
||||
imageId?: true
|
||||
userPrompt?: true
|
||||
pose?: true
|
||||
expression?: true
|
||||
createdAt?: true
|
||||
updatedAt?: true
|
||||
}
|
||||
@@ -82,6 +87,7 @@ export type GenerationCountAggregateInputType = {
|
||||
imageId?: true
|
||||
userPrompt?: true
|
||||
pose?: true
|
||||
expression?: true
|
||||
createdAt?: true
|
||||
updatedAt?: true
|
||||
_all?: true
|
||||
@@ -165,6 +171,7 @@ export type GenerationGroupByOutputType = {
|
||||
imageId: string
|
||||
userPrompt: string | null
|
||||
pose: string | null
|
||||
expression: string | null
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
_count: GenerationCountAggregateOutputType | null
|
||||
@@ -196,6 +203,7 @@ export type GenerationWhereInput = {
|
||||
imageId?: Prisma.StringFilter<"Generation"> | string
|
||||
userPrompt?: Prisma.StringNullableFilter<"Generation"> | string | null
|
||||
pose?: Prisma.StringNullableFilter<"Generation"> | string | null
|
||||
expression?: Prisma.StringNullableFilter<"Generation"> | string | null
|
||||
createdAt?: Prisma.DateTimeFilter<"Generation"> | Date | string
|
||||
updatedAt?: Prisma.DateTimeFilter<"Generation"> | Date | string
|
||||
character?: Prisma.XOR<Prisma.CharacterScalarRelationFilter, Prisma.CharacterWhereInput>
|
||||
@@ -209,6 +217,7 @@ export type GenerationOrderByWithRelationInput = {
|
||||
imageId?: Prisma.SortOrder
|
||||
userPrompt?: Prisma.SortOrderInput | Prisma.SortOrder
|
||||
pose?: Prisma.SortOrderInput | Prisma.SortOrder
|
||||
expression?: Prisma.SortOrderInput | Prisma.SortOrder
|
||||
createdAt?: Prisma.SortOrder
|
||||
updatedAt?: Prisma.SortOrder
|
||||
character?: Prisma.CharacterOrderByWithRelationInput
|
||||
@@ -225,6 +234,7 @@ export type GenerationWhereUniqueInput = Prisma.AtLeast<{
|
||||
imageId?: Prisma.StringFilter<"Generation"> | string
|
||||
userPrompt?: Prisma.StringNullableFilter<"Generation"> | string | null
|
||||
pose?: Prisma.StringNullableFilter<"Generation"> | string | null
|
||||
expression?: Prisma.StringNullableFilter<"Generation"> | string | null
|
||||
createdAt?: Prisma.DateTimeFilter<"Generation"> | Date | string
|
||||
updatedAt?: Prisma.DateTimeFilter<"Generation"> | Date | string
|
||||
character?: Prisma.XOR<Prisma.CharacterScalarRelationFilter, Prisma.CharacterWhereInput>
|
||||
@@ -238,6 +248,7 @@ export type GenerationOrderByWithAggregationInput = {
|
||||
imageId?: Prisma.SortOrder
|
||||
userPrompt?: Prisma.SortOrderInput | Prisma.SortOrder
|
||||
pose?: Prisma.SortOrderInput | Prisma.SortOrder
|
||||
expression?: Prisma.SortOrderInput | Prisma.SortOrder
|
||||
createdAt?: Prisma.SortOrder
|
||||
updatedAt?: Prisma.SortOrder
|
||||
_count?: Prisma.GenerationCountOrderByAggregateInput
|
||||
@@ -254,6 +265,7 @@ export type GenerationScalarWhereWithAggregatesInput = {
|
||||
imageId?: Prisma.StringWithAggregatesFilter<"Generation"> | string
|
||||
userPrompt?: Prisma.StringNullableWithAggregatesFilter<"Generation"> | string | null
|
||||
pose?: Prisma.StringNullableWithAggregatesFilter<"Generation"> | string | null
|
||||
expression?: Prisma.StringNullableWithAggregatesFilter<"Generation"> | string | null
|
||||
createdAt?: Prisma.DateTimeWithAggregatesFilter<"Generation"> | Date | string
|
||||
updatedAt?: Prisma.DateTimeWithAggregatesFilter<"Generation"> | Date | string
|
||||
}
|
||||
@@ -262,6 +274,7 @@ export type GenerationCreateInput = {
|
||||
id: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
character: Prisma.CharacterCreateNestedOneWithoutGenerationsInput
|
||||
@@ -275,6 +288,7 @@ export type GenerationUncheckedCreateInput = {
|
||||
imageId: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
equipments?: Prisma.GenerationEquipmentUncheckedCreateNestedManyWithoutGenerationInput
|
||||
@@ -284,6 +298,7 @@ export type GenerationUpdateInput = {
|
||||
id?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
character?: Prisma.CharacterUpdateOneRequiredWithoutGenerationsNestedInput
|
||||
@@ -297,6 +312,7 @@ export type GenerationUncheckedUpdateInput = {
|
||||
imageId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
equipments?: Prisma.GenerationEquipmentUncheckedUpdateManyWithoutGenerationNestedInput
|
||||
@@ -308,6 +324,7 @@ export type GenerationCreateManyInput = {
|
||||
imageId: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
}
|
||||
@@ -316,6 +333,7 @@ export type GenerationUpdateManyMutationInput = {
|
||||
id?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
}
|
||||
@@ -326,6 +344,7 @@ export type GenerationUncheckedUpdateManyInput = {
|
||||
imageId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
}
|
||||
@@ -346,6 +365,7 @@ export type GenerationCountOrderByAggregateInput = {
|
||||
imageId?: Prisma.SortOrder
|
||||
userPrompt?: Prisma.SortOrder
|
||||
pose?: Prisma.SortOrder
|
||||
expression?: Prisma.SortOrder
|
||||
createdAt?: Prisma.SortOrder
|
||||
updatedAt?: Prisma.SortOrder
|
||||
}
|
||||
@@ -356,6 +376,7 @@ export type GenerationMaxOrderByAggregateInput = {
|
||||
imageId?: Prisma.SortOrder
|
||||
userPrompt?: Prisma.SortOrder
|
||||
pose?: Prisma.SortOrder
|
||||
expression?: Prisma.SortOrder
|
||||
createdAt?: Prisma.SortOrder
|
||||
updatedAt?: Prisma.SortOrder
|
||||
}
|
||||
@@ -366,6 +387,7 @@ export type GenerationMinOrderByAggregateInput = {
|
||||
imageId?: Prisma.SortOrder
|
||||
userPrompt?: Prisma.SortOrder
|
||||
pose?: Prisma.SortOrder
|
||||
expression?: Prisma.SortOrder
|
||||
createdAt?: Prisma.SortOrder
|
||||
updatedAt?: Prisma.SortOrder
|
||||
}
|
||||
@@ -477,6 +499,7 @@ export type GenerationCreateWithoutImageInput = {
|
||||
id: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
character: Prisma.CharacterCreateNestedOneWithoutGenerationsInput
|
||||
@@ -488,6 +511,7 @@ export type GenerationUncheckedCreateWithoutImageInput = {
|
||||
characterId: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
equipments?: Prisma.GenerationEquipmentUncheckedCreateNestedManyWithoutGenerationInput
|
||||
@@ -527,6 +551,7 @@ export type GenerationScalarWhereInput = {
|
||||
imageId?: Prisma.StringFilter<"Generation"> | string
|
||||
userPrompt?: Prisma.StringNullableFilter<"Generation"> | string | null
|
||||
pose?: Prisma.StringNullableFilter<"Generation"> | string | null
|
||||
expression?: Prisma.StringNullableFilter<"Generation"> | string | null
|
||||
createdAt?: Prisma.DateTimeFilter<"Generation"> | Date | string
|
||||
updatedAt?: Prisma.DateTimeFilter<"Generation"> | Date | string
|
||||
}
|
||||
@@ -535,6 +560,7 @@ export type GenerationCreateWithoutCharacterInput = {
|
||||
id: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
image: Prisma.AssetCreateNestedOneWithoutGenerationsInput
|
||||
@@ -546,6 +572,7 @@ export type GenerationUncheckedCreateWithoutCharacterInput = {
|
||||
imageId: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
equipments?: Prisma.GenerationEquipmentUncheckedCreateNestedManyWithoutGenerationInput
|
||||
@@ -580,6 +607,7 @@ export type GenerationCreateWithoutEquipmentsInput = {
|
||||
id: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
character: Prisma.CharacterCreateNestedOneWithoutGenerationsInput
|
||||
@@ -592,6 +620,7 @@ export type GenerationUncheckedCreateWithoutEquipmentsInput = {
|
||||
imageId: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
}
|
||||
@@ -616,6 +645,7 @@ export type GenerationUpdateWithoutEquipmentsInput = {
|
||||
id?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
character?: Prisma.CharacterUpdateOneRequiredWithoutGenerationsNestedInput
|
||||
@@ -628,6 +658,7 @@ export type GenerationUncheckedUpdateWithoutEquipmentsInput = {
|
||||
imageId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
}
|
||||
@@ -637,6 +668,7 @@ export type GenerationCreateManyImageInput = {
|
||||
characterId: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
}
|
||||
@@ -645,6 +677,7 @@ export type GenerationUpdateWithoutImageInput = {
|
||||
id?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
character?: Prisma.CharacterUpdateOneRequiredWithoutGenerationsNestedInput
|
||||
@@ -656,6 +689,7 @@ export type GenerationUncheckedUpdateWithoutImageInput = {
|
||||
characterId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
equipments?: Prisma.GenerationEquipmentUncheckedUpdateManyWithoutGenerationNestedInput
|
||||
@@ -666,6 +700,7 @@ export type GenerationUncheckedUpdateManyWithoutImageInput = {
|
||||
characterId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
}
|
||||
@@ -675,6 +710,7 @@ export type GenerationCreateManyCharacterInput = {
|
||||
imageId: string
|
||||
userPrompt?: string | null
|
||||
pose?: string | null
|
||||
expression?: string | null
|
||||
createdAt?: Date | string
|
||||
updatedAt?: Date | string
|
||||
}
|
||||
@@ -683,6 +719,7 @@ export type GenerationUpdateWithoutCharacterInput = {
|
||||
id?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
image?: Prisma.AssetUpdateOneRequiredWithoutGenerationsNestedInput
|
||||
@@ -694,6 +731,7 @@ export type GenerationUncheckedUpdateWithoutCharacterInput = {
|
||||
imageId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
equipments?: Prisma.GenerationEquipmentUncheckedUpdateManyWithoutGenerationNestedInput
|
||||
@@ -704,6 +742,7 @@ export type GenerationUncheckedUpdateManyWithoutCharacterInput = {
|
||||
imageId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||
userPrompt?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
pose?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
expression?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
|
||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||
}
|
||||
@@ -745,6 +784,7 @@ export type GenerationSelect<ExtArgs extends runtime.Types.Extensions.InternalAr
|
||||
imageId?: boolean
|
||||
userPrompt?: boolean
|
||||
pose?: boolean
|
||||
expression?: boolean
|
||||
createdAt?: boolean
|
||||
updatedAt?: boolean
|
||||
character?: boolean | Prisma.CharacterDefaultArgs<ExtArgs>
|
||||
@@ -759,6 +799,7 @@ export type GenerationSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Ex
|
||||
imageId?: boolean
|
||||
userPrompt?: boolean
|
||||
pose?: boolean
|
||||
expression?: boolean
|
||||
createdAt?: boolean
|
||||
updatedAt?: boolean
|
||||
character?: boolean | Prisma.CharacterDefaultArgs<ExtArgs>
|
||||
@@ -771,6 +812,7 @@ export type GenerationSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Ex
|
||||
imageId?: boolean
|
||||
userPrompt?: boolean
|
||||
pose?: boolean
|
||||
expression?: boolean
|
||||
createdAt?: boolean
|
||||
updatedAt?: boolean
|
||||
character?: boolean | Prisma.CharacterDefaultArgs<ExtArgs>
|
||||
@@ -783,11 +825,12 @@ export type GenerationSelectScalar = {
|
||||
imageId?: boolean
|
||||
userPrompt?: boolean
|
||||
pose?: boolean
|
||||
expression?: boolean
|
||||
createdAt?: boolean
|
||||
updatedAt?: boolean
|
||||
}
|
||||
|
||||
export type GenerationOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "characterId" | "imageId" | "userPrompt" | "pose" | "createdAt" | "updatedAt", ExtArgs["result"]["generation"]>
|
||||
export type GenerationOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "characterId" | "imageId" | "userPrompt" | "pose" | "expression" | "createdAt" | "updatedAt", ExtArgs["result"]["generation"]>
|
||||
export type GenerationInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||
character?: boolean | Prisma.CharacterDefaultArgs<ExtArgs>
|
||||
image?: boolean | Prisma.AssetDefaultArgs<ExtArgs>
|
||||
@@ -816,6 +859,7 @@ export type $GenerationPayload<ExtArgs extends runtime.Types.Extensions.Internal
|
||||
imageId: string
|
||||
userPrompt: string | null
|
||||
pose: string | null
|
||||
expression: string | null
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}, ExtArgs["result"]["generation"]>
|
||||
@@ -1249,6 +1293,7 @@ export interface GenerationFieldRefs {
|
||||
readonly imageId: Prisma.FieldRef<"Generation", 'String'>
|
||||
readonly userPrompt: Prisma.FieldRef<"Generation", 'String'>
|
||||
readonly pose: Prisma.FieldRef<"Generation", 'String'>
|
||||
readonly expression: Prisma.FieldRef<"Generation", 'String'>
|
||||
readonly createdAt: Prisma.FieldRef<"Generation", 'DateTime'>
|
||||
readonly updatedAt: Prisma.FieldRef<"Generation", 'DateTime'>
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import asset from './api/asset'
|
||||
import character from './api/character'
|
||||
import equipment from './api/equipment'
|
||||
import extract from './api/extract'
|
||||
import expression from './api/expression'
|
||||
import generation from './api/generation'
|
||||
import outfit from './api/outfit'
|
||||
import pose from './api/pose'
|
||||
@@ -27,6 +28,7 @@ const route = api
|
||||
.route('/extract', extract)
|
||||
.route('/outfits', outfit)
|
||||
.route('/poses', pose)
|
||||
.route('/expressions', expression)
|
||||
.route('/settings', setting)
|
||||
|
||||
// Mount API
|
||||
@@ -38,6 +40,9 @@ app.use('/files/*', serveStatic({ root: './data' }))
|
||||
// Serve static files from public/poses under /poses path
|
||||
app.use('/poses/*', serveStatic({ root: './public' }))
|
||||
|
||||
// Serve static files from public/expressions under /expressions path
|
||||
app.use('/expressions/*', serveStatic({ root: './public' }))
|
||||
|
||||
// Export type for RPC
|
||||
export type AppType = typeof route
|
||||
|
||||
@@ -52,6 +57,7 @@ const server = Bun.serve({
|
||||
'/api/*': app.fetch,
|
||||
'/files/*': app.fetch,
|
||||
'/poses/*': app.fetch,
|
||||
'/expressions/*': app.fetch,
|
||||
|
||||
// Catch-all for SPA routing (fallback to index.html)
|
||||
'/*': index,
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { ulid } from 'ulidx'
|
||||
import { prisma } from '../db'
|
||||
import { assetService } from './asset'
|
||||
|
||||
export interface ExpressionItem {
|
||||
id: string
|
||||
name: string
|
||||
type: 'builtin' | 'custom'
|
||||
imageUrl: string
|
||||
}
|
||||
|
||||
export const BUILTIN_EXPRESSIONS: ExpressionItem[] = Array.from({ length: 9 }, (_, i) => i + 1).map(
|
||||
(i) => ({
|
||||
id: `expression_${i}.webp`,
|
||||
name: `Expression ${i}`,
|
||||
type: 'builtin',
|
||||
imageUrl: `/expressions/expression_${i}.webp`,
|
||||
}),
|
||||
)
|
||||
|
||||
export class ExpressionService {
|
||||
async listExpressions(): Promise<ExpressionItem[]> {
|
||||
const customExpressions = await prisma.expression.findMany({
|
||||
include: { image: true },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
})
|
||||
|
||||
const formattedCustomExpressions: ExpressionItem[] = customExpressions.map((e) => ({
|
||||
id: e.id,
|
||||
name: e.name,
|
||||
type: 'custom',
|
||||
imageUrl: `/files/${e.image.path}`,
|
||||
}))
|
||||
|
||||
return [...BUILTIN_EXPRESSIONS, ...formattedCustomExpressions]
|
||||
}
|
||||
|
||||
async createExpression(name: string, file: File) {
|
||||
const asset = await assetService.createAsset(file, {
|
||||
name: name,
|
||||
type: file.type,
|
||||
})
|
||||
|
||||
const expression = await prisma.expression.create({
|
||||
data: {
|
||||
id: ulid(),
|
||||
name,
|
||||
imageId: asset.id,
|
||||
},
|
||||
include: { image: true },
|
||||
})
|
||||
|
||||
return {
|
||||
id: expression.id,
|
||||
name: expression.name,
|
||||
type: 'custom',
|
||||
imageUrl: `/files/${expression.image.path}`,
|
||||
} as ExpressionItem
|
||||
}
|
||||
|
||||
async deleteExpression(id: string) {
|
||||
if (BUILTIN_EXPRESSIONS.some((e) => e.id === id)) {
|
||||
throw new Error('Cannot delete builtin expression')
|
||||
}
|
||||
|
||||
const expression = await prisma.expression.findUnique({
|
||||
where: { id },
|
||||
})
|
||||
|
||||
if (!expression) {
|
||||
throw new Error('Expression not found')
|
||||
}
|
||||
|
||||
await prisma.expression.delete({
|
||||
where: { id },
|
||||
})
|
||||
}
|
||||
|
||||
getBuiltinExpression(id: string) {
|
||||
return BUILTIN_EXPRESSIONS.find((e) => e.id === id)
|
||||
}
|
||||
}
|
||||
|
||||
export const expressionService = new ExpressionService()
|
||||
@@ -4,6 +4,7 @@ import { prisma } from '../db'
|
||||
import { Prisma } from '../generated/prisma/client'
|
||||
import { aiService, type AIPart } from './ai'
|
||||
import { assetService } from './asset'
|
||||
import { expressionService } from './expression'
|
||||
import { poseService } from './pose'
|
||||
|
||||
export class GenerationService {
|
||||
@@ -12,6 +13,7 @@ export class GenerationService {
|
||||
equipmentIds: string[],
|
||||
userPrompt?: string,
|
||||
poseId?: string,
|
||||
expressionId?: string,
|
||||
) {
|
||||
// 1. Fetch character and its image
|
||||
const character = await prisma.character.findUnique({
|
||||
@@ -112,6 +114,48 @@ category: ${eq.category}
|
||||
"6. Use the 'Target Pose Reference' image for the character's pose and angle."
|
||||
}
|
||||
|
||||
// Handle Expression
|
||||
let expressionInstruction = '7. Maintain the facial expression of the Base Character.'
|
||||
|
||||
if (expressionId) {
|
||||
let expressionBuffer: ArrayBuffer
|
||||
let expressionMimeType: string
|
||||
|
||||
const builtinExpression = expressionService.getBuiltinExpression(expressionId)
|
||||
if (builtinExpression) {
|
||||
const expressionPath = join('public/expressions', expressionId)
|
||||
const file = Bun.file(expressionPath)
|
||||
expressionBuffer = await file.arrayBuffer()
|
||||
expressionMimeType = file.type || 'image/webp'
|
||||
} else {
|
||||
const customExpression = await prisma.expression.findUnique({
|
||||
where: { id: expressionId },
|
||||
include: { image: true },
|
||||
})
|
||||
|
||||
if (!customExpression) {
|
||||
throw new Error(`Expression not found: ${expressionId}`)
|
||||
}
|
||||
|
||||
const expressionPath = join('data/files', customExpression.image.path)
|
||||
const file = Bun.file(expressionPath)
|
||||
expressionBuffer = await file.arrayBuffer()
|
||||
expressionMimeType = customExpression.image.type
|
||||
}
|
||||
|
||||
const expressionBase64 = Buffer.from(expressionBuffer).toString('base64')
|
||||
parts.push({
|
||||
inlineData: {
|
||||
mimeType: expressionMimeType,
|
||||
data: expressionBase64,
|
||||
},
|
||||
})
|
||||
parts.push({ text: 'Target Expression Reference' })
|
||||
|
||||
expressionInstruction =
|
||||
"7. Use the 'Target Expression Reference' image for the character's facial expression."
|
||||
}
|
||||
|
||||
let prompt = `
|
||||
Task: Character Synthesis and Equipment Modification.
|
||||
|
||||
@@ -121,7 +165,8 @@ category: ${eq.category}
|
||||
4. The items should replace existing clothing/armor in that slot (e.g. new helmet replaces old hat, armor replaces shirt).
|
||||
5. Seamlessly blend the items into the character's style.
|
||||
${poseInstruction}
|
||||
7. High quality, detailed, game art style.
|
||||
${expressionInstruction}
|
||||
8. High quality, detailed, game art style.
|
||||
`
|
||||
|
||||
if (userPrompt) {
|
||||
@@ -167,6 +212,7 @@ category: ${eq.category}
|
||||
imageId: asset.id,
|
||||
userPrompt: userPrompt,
|
||||
pose: poseId,
|
||||
expression: expressionId,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import Characters from './pages/Characters'
|
||||
import Equipments from './pages/Equipments'
|
||||
import FittingRoom from './pages/FittingRoom'
|
||||
import Poses from './pages/Poses'
|
||||
import Expressions from './pages/Expressions'
|
||||
import Settings from './pages/Settings'
|
||||
|
||||
export default function App() {
|
||||
@@ -17,6 +18,7 @@ export default function App() {
|
||||
<Route path="characters/:id/looks" element={<FittingRoom />} />
|
||||
<Route path="equipments" element={<Equipments />} />
|
||||
<Route path="poses" element={<Poses />} />
|
||||
<Route path="expressions" element={<Expressions />} />
|
||||
<Route path="settings" element={<Settings />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Backpack, Frame, Settings, Users } from 'lucide-react'
|
||||
import { Backpack, Frame, Settings, Smile, Users } from 'lucide-react'
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
import {
|
||||
Sidebar,
|
||||
@@ -27,6 +27,11 @@ const items = [
|
||||
url: '/poses',
|
||||
icon: Frame,
|
||||
},
|
||||
{
|
||||
title: 'Expressions',
|
||||
url: '/expressions',
|
||||
icon: Smile,
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
url: '/settings',
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
import { Loader2, Upload } from 'lucide-react'
|
||||
import React, { useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { client } from '../client'
|
||||
import { Button } from './ui/button'
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from './ui/dialog'
|
||||
import { Input } from './ui/input'
|
||||
import { Label } from './ui/label'
|
||||
|
||||
interface CreateExpressionDialogProps {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
onSuccess: () => void
|
||||
}
|
||||
|
||||
export const CreateExpressionDialog: React.FC<CreateExpressionDialogProps> = ({
|
||||
open,
|
||||
onOpenChange,
|
||||
onSuccess,
|
||||
}) => {
|
||||
const [name, setName] = useState('')
|
||||
const [file, setFile] = useState<File | null>(null)
|
||||
const [preview, setPreview] = useState<string | null>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.files && e.target.files[0]) {
|
||||
const f = e.target.files[0]
|
||||
setFile(f)
|
||||
setPreview(URL.createObjectURL(f))
|
||||
if (!name) {
|
||||
setName(f.name.replace(/\.[^/.]+$/, ''))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
if (!file || !name) return
|
||||
|
||||
setLoading(true)
|
||||
|
||||
try {
|
||||
const res = await client.expressions.$post({
|
||||
form: {
|
||||
name,
|
||||
image: file,
|
||||
},
|
||||
})
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error('Failed to create expression')
|
||||
}
|
||||
|
||||
toast.success('Expression created successfully')
|
||||
onSuccess()
|
||||
handleReset()
|
||||
onOpenChange(false)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
toast.error('Failed to create expression')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
setName('')
|
||||
setFile(null)
|
||||
if (preview) URL.revokeObjectURL(preview)
|
||||
setPreview(null)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add Custom Expression</DialogTitle>
|
||||
<DialogDescription>Upload a reference image for a new expression.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="expression-image">Expression Image</Label>
|
||||
<div className="flex items-center justify-center w-full">
|
||||
{!preview ? (
|
||||
<label
|
||||
htmlFor="expression-dropzone"
|
||||
className="flex flex-col items-center justify-center w-full h-48 border-2 border-dashed rounded-lg cursor-pointer bg-stone-50 hover:bg-stone-100 border-stone-300 hover:border-stone-400 transition-colors"
|
||||
>
|
||||
<div className="flex flex-col items-center justify-center pt-5 pb-6">
|
||||
<Upload className="w-8 h-8 mb-2 text-stone-400" />
|
||||
<p className="text-sm text-stone-500">
|
||||
<span className="font-semibold">Click to upload</span>
|
||||
</p>
|
||||
</div>
|
||||
<input
|
||||
id="expression-dropzone"
|
||||
type="file"
|
||||
className="hidden"
|
||||
accept="image/*"
|
||||
onChange={handleFileChange}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
) : (
|
||||
<div className="relative w-full h-48 bg-stone-100 rounded-lg overflow-hidden group border border-stone-200">
|
||||
<img src={preview} alt="Preview" className="w-full h-full object-contain" />
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setFile(null)
|
||||
URL.revokeObjectURL(preview)
|
||||
setPreview(null)
|
||||
}}
|
||||
className="absolute inset-0 bg-black/40 text-white opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center font-medium"
|
||||
>
|
||||
Change Image
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="expression-name">Name</Label>
|
||||
<Input
|
||||
id="expression-name"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="Expression Name"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end pt-4">
|
||||
<Button type="submit" disabled={loading || !file || !name}>
|
||||
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||
Add Expression
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { InferResponseType } from 'hono/client'
|
||||
import { Check, Download, Loader2, Save, User, X } from 'lucide-react'
|
||||
import { Check, Download, Loader2, Save, Smile, User, X } from 'lucide-react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { EQUIPMENT_CATEGORIES } from '../../lib/categories'
|
||||
@@ -19,6 +19,8 @@ type EquipmentItem = EquipmentResponse['items'][number]
|
||||
type OutfitItem = InferResponseType<typeof client.outfits.$get>[number]
|
||||
type PoseResponse = InferResponseType<typeof client.poses.$get>
|
||||
type PoseItem = PoseResponse[number]
|
||||
type ExpressionResponse = InferResponseType<typeof client.expressions.$get>
|
||||
type ExpressionItem = ExpressionResponse[number]
|
||||
|
||||
interface CreateLookDialogProps {
|
||||
open: boolean
|
||||
@@ -39,6 +41,8 @@ export const CreateLookDialog: React.FC<CreateLookDialogProps> = ({
|
||||
const [selectedEquipments, setSelectedEquipments] = useState<EquipmentItem[]>([])
|
||||
const [poses, setPoses] = useState<PoseItem[]>([])
|
||||
const [selectedPoseId, setSelectedPoseId] = useState<string | null>(null)
|
||||
const [expressions, setExpressions] = useState<ExpressionItem[]>([])
|
||||
const [selectedExpressionId, setSelectedExpressionId] = useState<string | null>(null)
|
||||
const [userPrompt, setUserPrompt] = useState('')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
@@ -50,6 +54,7 @@ export const CreateLookDialog: React.FC<CreateLookDialogProps> = ({
|
||||
if (open) {
|
||||
fetchItems()
|
||||
fetchPoses()
|
||||
fetchExpressions()
|
||||
}
|
||||
}, [open, selectedCategories])
|
||||
|
||||
@@ -87,6 +92,18 @@ export const CreateLookDialog: React.FC<CreateLookDialogProps> = ({
|
||||
}
|
||||
}
|
||||
|
||||
const fetchExpressions = async () => {
|
||||
try {
|
||||
const res = await client.expressions.$get()
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
setExpressions(data)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to load expressions', e)
|
||||
}
|
||||
}
|
||||
|
||||
const toggleCategory = (category: string) => {
|
||||
setSelectedCategories((prev) =>
|
||||
prev.includes(category) ? prev.filter((c) => c !== category) : [...prev, category],
|
||||
@@ -115,6 +132,7 @@ export const CreateLookDialog: React.FC<CreateLookDialogProps> = ({
|
||||
equipmentIds: selectedEquipments.map((e) => e.id),
|
||||
userPrompt: userPrompt.trim() || undefined,
|
||||
poseId: selectedPoseId || undefined,
|
||||
expressionId: selectedExpressionId || undefined,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -223,6 +241,59 @@ export const CreateLookDialog: React.FC<CreateLookDialogProps> = ({
|
||||
</ScrollArea>
|
||||
</div>
|
||||
|
||||
{/* Expression Selection */}
|
||||
<div className="px-6 py-3 border-b border-stone-200 bg-white shrink-0">
|
||||
<div className="mb-2 text-xs font-bold text-stone-700 uppercase">Select Expression</div>
|
||||
<ScrollArea className="w-full whitespace-nowrap">
|
||||
<div className="flex w-max space-x-2 pb-2">
|
||||
<div
|
||||
className={cn(
|
||||
'w-16 h-20 border rounded-lg cursor-pointer flex flex-col items-center justify-center bg-stone-50 shrink-0 transition-all',
|
||||
selectedExpressionId === null
|
||||
? 'border-emerald-500 ring-2 ring-emerald-500/20 bg-emerald-50'
|
||||
: 'border-stone-200 hover:border-stone-400',
|
||||
)}
|
||||
onClick={() => setSelectedExpressionId(null)}
|
||||
>
|
||||
<Smile className="w-6 h-6 text-stone-400 mb-1" />
|
||||
<span className="text-[10px] font-medium text-stone-600">Default</span>
|
||||
</div>
|
||||
{expressions.map((expression) => {
|
||||
const isSelected = selectedExpressionId === expression.id
|
||||
return (
|
||||
<div
|
||||
key={expression.id}
|
||||
className={cn(
|
||||
'w-16 h-20 border rounded-lg cursor-pointer overflow-hidden shrink-0 transition-all relative',
|
||||
isSelected
|
||||
? 'border-emerald-500 ring-2 ring-emerald-500/20 shadow-md'
|
||||
: 'border-stone-200 hover:border-stone-400',
|
||||
)}
|
||||
onClick={() => setSelectedExpressionId(expression.id)}
|
||||
>
|
||||
<img
|
||||
src={expression.imageUrl}
|
||||
alt={expression.name}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
{isSelected && (
|
||||
<div className="absolute inset-0 bg-emerald-500/10 flex items-center justify-center">
|
||||
<Check className="w-6 h-6 text-emerald-500 drop-shadow-md" />
|
||||
</div>
|
||||
)}
|
||||
<div className="absolute bottom-0 inset-x-0 bg-black/50 p-0.5 text-center">
|
||||
<span className="text-[8px] text-white font-medium truncate block">
|
||||
{expression.name}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<ScrollBar orientation="horizontal" />
|
||||
</ScrollArea>
|
||||
</div>
|
||||
|
||||
{/* Categories */}
|
||||
<div className="px-6 py-3 border-b border-stone-200 bg-white shrink-0">
|
||||
<ScrollArea className="w-full whitespace-nowrap">
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
import { InferResponseType } from 'hono/client'
|
||||
import { Plus, Trash2 } from 'lucide-react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { client } from '../client'
|
||||
import { CreateExpressionDialog } from '../components/CreateExpressionDialog'
|
||||
import { PageHeader } from '../components/PageHeader'
|
||||
import { VibeCard } from '../components/VibeCard'
|
||||
import { Button } from '../components/ui/button'
|
||||
|
||||
type ExpressionResponse = InferResponseType<typeof client.expressions.$get>
|
||||
type ExpressionItem = ExpressionResponse[number]
|
||||
|
||||
export default function Expressions() {
|
||||
const [expressions, setExpressions] = useState<ExpressionItem[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [createOpen, setCreateOpen] = useState(false)
|
||||
|
||||
const fetchExpressions = async () => {
|
||||
try {
|
||||
const res = await client.expressions.$get()
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
setExpressions(data)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to load expressions', e)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchExpressions()
|
||||
}, [])
|
||||
|
||||
const handleDelete = async (id: string) => {
|
||||
if (!confirm('Are you sure you want to delete this expression?')) return
|
||||
|
||||
try {
|
||||
const res = await client.expressions[':id'].$delete({ param: { id } })
|
||||
if (res.ok) {
|
||||
toast.success('Expression deleted')
|
||||
fetchExpressions()
|
||||
} else {
|
||||
const err = await res.json()
|
||||
// @ts-ignore
|
||||
toast.error('Failed to delete: ' + (err.error || 'Unknown error'))
|
||||
}
|
||||
} catch {
|
||||
toast.error('Failed to delete expression')
|
||||
}
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="p-8 text-slate-400 font-mono tracking-widest animate-pulse">
|
||||
INITIALIZING...
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full h-full p-4 pt-2 flex flex-col text-slate-900 relative">
|
||||
<PageHeader
|
||||
title="Expressions"
|
||||
subtitle="System // Expression_Library"
|
||||
actions={
|
||||
<Button onClick={() => setCreateOpen(true)}>
|
||||
<Plus className="mr-2 h-4 w-4" /> Add Expression
|
||||
</Button>
|
||||
}
|
||||
className="mb-8"
|
||||
/>
|
||||
|
||||
{expressions.length === 0 ? (
|
||||
<div className="text-center p-12 bg-white clip-path-slant border border-slate-200">
|
||||
<p className="text-slate-500 font-mono">No expressions found.</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 gap-6 max-w-[1920px] mx-auto w-full pb-10">
|
||||
{expressions.map((expression, index) => (
|
||||
<div key={expression.id} className="relative group/container">
|
||||
<VibeCard
|
||||
index={index}
|
||||
name={expression.name}
|
||||
subtitle={expression.type === 'builtin' ? 'SYSTEM' : 'CUSTOM'}
|
||||
image={expression.imageUrl}
|
||||
color={expression.type === 'builtin' ? '#10b981' : '#f59e0b'}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
{expression.type === 'custom' && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleDelete(expression.id)
|
||||
}}
|
||||
className="absolute top-2 right-2 p-2 bg-red-500 text-white rounded-full opacity-0 group-hover/container:opacity-100 transition-opacity z-10 hover:bg-red-600 shadow-md"
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<CreateExpressionDialog
|
||||
open={createOpen}
|
||||
onOpenChange={setCreateOpen}
|
||||
onSuccess={fetchExpressions}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||