26 lines
2.0 KiB
TypeScript
26 lines
2.0 KiB
TypeScript
import {randomUUID} from 'node:crypto';
|
|
import {z} from 'zod';
|
|
import {db,transaction} from './db';
|
|
import {series,pageParameters} from './series';
|
|
import layouts from '../content/studio-layouts.json';
|
|
import standard from '../content/standard-layout.json';
|
|
import {validateDesign,designOutput,DesignConflict} from './studio-designs';
|
|
import {ensureDesignPost} from './studio-design-posts';
|
|
const all=[...layouts,standard];
|
|
export const seriesInput=z.object({schemaVersion:z.literal(2),name:z.string().trim().min(1).max(120),document:z.unknown()}).strict();
|
|
export const seriesUpdate=seriesInput.extend({revision:z.number().int().positive()});
|
|
export async function saveSeries(input:z.infer<typeof seriesInput>,id?:string,revision?:number){
|
|
const document=series(input.document,all);
|
|
return transaction(async client=>{
|
|
const old=id?(await client.query('SELECT * FROM studio_designs WHERE id=$1 FOR UPDATE',[id])).rows[0]:null;
|
|
if(id&&!old)return null;
|
|
if(old&&(!old.document||old.archived||old.revision!==revision))throw new DesignConflict('作品类型、归档状态或修订号冲突');
|
|
for(const page of document.pages)await validateDesign(page.layoutId,page.parameters,client);
|
|
const cover=document.pages[0],layout=all.find(l=>l.id===cover.layoutId)!;
|
|
const p=pageParameters(document,cover,layout);
|
|
const row=id?(await client.query('UPDATE studio_designs SET name=$2,layout_id=$3,parameters=$4,document=$5,revision=revision+1,updated_at=now() WHERE id=$1 RETURNING *',[id,input.name,cover.layoutId,JSON.stringify(p),JSON.stringify(document)])).rows[0]:(await client.query('INSERT INTO studio_designs(id,name,layout_id,parameters,document) VALUES($1,$2,$3,$4,$5) RETURNING *',[randomUUID(),input.name,cover.layoutId,JSON.stringify(p),JSON.stringify(document)])).rows[0];
|
|
return designOutput(await ensureDesignPost(client,row));
|
|
});
|
|
}
|
|
export async function readSeries(id:string){const row=(await db().query('SELECT * FROM studio_designs WHERE id=$1 AND document IS NOT NULL',[id])).rows[0];return row?designOutput(row):null}
|