11 lines
1.6 KiB
TypeScript
11 lines
1.6 KiB
TypeScript
import {randomUUID} from 'node:crypto';
|
|
import {z} from 'zod';
|
|
import {db} from './db';
|
|
import {parameters,LayoutParameterError} from './layout-parameters';
|
|
import layouts from '../content/studio-layouts.json';
|
|
export const designInput=z.object({layoutId:z.string(),name:z.string().trim().min(1).max(120),parameters:z.unknown()}).strict();
|
|
export const updateDesignInput=designInput.omit({layoutId:true}).extend({revision:z.number().int().positive()}).strict();
|
|
export function designOutput(r:Record<string,unknown>){return {id:r.id,layoutId:r.layout_id,name:r.name,parameters:r.parameters,revision:r.revision,createdAt:r.created_at,updatedAt:r.updated_at,url:'/studio/designs/'+r.id,renderUrl:'/studio/api/layouts/'+r.layout_id};}
|
|
export async function validateDesign(layoutId:string,raw:unknown){const layout=layouts.find(l=>l.id===layoutId);if(!layout)throw new LayoutParameterError('排版不存在');const p=parameters(layout,raw),images=[...new Set(Object.values(p.images).flatMap(i=>i.assetId?[i.assetId]:[]))];if(images.length){const found=await db().query("SELECT id FROM assets WHERE kind='image' AND id=ANY($1::uuid[])",[images]);if(found.rowCount!==images.length)throw new LayoutParameterError('引用的图片素材不存在')}return p;}
|
|
export async function createDesign(input:z.infer<typeof designInput>){const p=await validateDesign(input.layoutId,input.parameters);const r=await db().query('INSERT INTO studio_designs(id,layout_id,name,parameters) VALUES($1,$2,$3,$4) RETURNING *',[randomUUID(),input.layoutId,input.name,JSON.stringify(p)]);return designOutput(r.rows[0]);}
|