feat(db,contracts): trash_item migration and file manager contract refinements
- 0024_trash: trash_item table + unique idempotency index on artifact(files_idem) - files.ts: TrashItemRow, delete planId/planExpiresAt, organize group warnings, scrape returns refreshMetadata taskId - registry tests list the new table/row schema Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
673cb3920a
commit
09f6e3a3e5
6 files changed
+98
-2
No files matched your search
@@ -350,6 +350,8 @@ export const FilesOrganizeGroup = z.object({
|
||||
truncated: z.boolean(),
|
||||
recordId: Id.nullable(),
|
||||
taskId: Id.nullable(),
|
||||
/** 暂未生效的逐项覆写(season/episodes/slotId 等待 planImport 扩 fileOverrides) */
|
||||
warnings: z.array(z.string()),
|
||||
/** 该组失败原因(plan_stale / 授权 / H&R 等),其他组不受影响 */
|
||||
error: z.object({ code: z.string(), message: z.string() }).nullable(),
|
||||
});
|
||||
@@ -376,6 +378,8 @@ export const FilesDeleteRequest = z.object({
|
||||
unbind: z.boolean().default(false),
|
||||
/** 永久删除二次确认:必须等于每项文件名(单项时) */
|
||||
confirmName: z.string().max(255).optional(),
|
||||
/** dryRun 返回的 planId;API Key 执行时必填(一次性审批绑定该计划),会话可省略 */
|
||||
planId: Id.optional(),
|
||||
});
|
||||
export type FilesDeleteRequest = z.infer<typeof FilesDeleteRequest>;
|
||||
|
||||
@@ -396,6 +400,25 @@ export const FileDeleteCheck = z.object({
|
||||
});
|
||||
export type FileDeleteCheck = z.infer<typeof FileDeleteCheck>;
|
||||
|
||||
/** trash_item 表行(db-sync 对照用;API 用下方 TrashItem 投影) */
|
||||
export const TrashItemRow = z.object({
|
||||
id: Id,
|
||||
rootId: z.string(),
|
||||
libraryRootId: Id.nullable(),
|
||||
rootHostPath: z.string(),
|
||||
originalPath: z.string(),
|
||||
trashPath: z.string(),
|
||||
isDir: z.boolean(),
|
||||
sizeBytes: NonNegInt,
|
||||
actor: z.string().nullable(),
|
||||
deletedAt: Timestamp,
|
||||
expiresAt: Timestamp,
|
||||
assetSnapshot: JsonObject.nullable(),
|
||||
createdAt: Timestamp,
|
||||
updatedAt: Timestamp,
|
||||
});
|
||||
export type TrashItemRow = z.infer<typeof TrashItemRow>;
|
||||
|
||||
export const TrashItem = z.object({
|
||||
id: Id,
|
||||
rootId: FileRootId,
|
||||
@@ -414,6 +437,9 @@ export type TrashItem = z.infer<typeof TrashItem>;
|
||||
|
||||
export const FilesDeleteResult = z.object({
|
||||
dryRun: z.boolean(),
|
||||
/** dryRun 生成的删除计划(执行时回传;审批绑定) */
|
||||
planId: Id.nullable(),
|
||||
planExpiresAt: Timestamp.nullable(),
|
||||
mode: z.enum(["trash", "permanent"]),
|
||||
checks: z.array(FileDeleteCheck),
|
||||
/** 执行后:进入回收站的项(permanent 为空) */
|
||||
@@ -527,9 +553,11 @@ export const FilesScrapeRequest = z.object({
|
||||
export type FilesScrapeRequest = z.infer<typeof FilesScrapeRequest>;
|
||||
export const FilesScrapeResult = z.object({
|
||||
mediaEntityId: Id,
|
||||
changedFields: z.array(z.string()),
|
||||
/** refreshMetadata 引擎 run id(异步;字段级刷新,用户锁优先,不动路径) */
|
||||
taskId: z.string(),
|
||||
/** 当前被用户锁定、刷新不会改动的字段 */
|
||||
lockedFields: z.array(z.string()),
|
||||
/** NFO/图片投影:W5 实现前恒为 not_implemented */
|
||||
/** NFO/图片投影:W5 实现前请求时为 not_implemented */
|
||||
nfo: z.enum(["written", "skipped", "not_requested", "not_implemented"]),
|
||||
images: z.enum(["written", "skipped", "not_requested", "not_implemented"]),
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user