chore(publish): locale 决胜键;confirm 清单输出;并发窗口注释

- 候选查询 orderBy 第三键 entry_locales.locale(同 typeKey+slug 多 locale 决胜,
  清单呈现稳定);mini 单 locale,既有测试期望三元组已含 locale 列、无需改
- CLI confirm 输出发布清单(result.candidates,与 dry-run 同行格式
  published→current;>20 行截断为 …and M more——CONFIRM_LIST_CAP)
- PublishSiteContentResult.candidates 注释钉死:confirm 期 candidates 是事务前
  快照,权威数以 publishedCount 为准(并发窗口)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-22 07:21:34 +08:00
parent c35f10835a
commit 6a1d9a383b
2 changed files with 20 additions and 3 deletions
@@ -107,7 +107,11 @@ export interface PublishSiteContentResult {
dryRun: boolean
/** dry-run = 随机 token(输出给操作者);confirm = 实际传入值 */
confirmToken: string | null
/** 候选清单(查询起点:current 非空且 published≠current) */
/**
* 候选清单(查询起点:current 非空且 published≠current;typeKey/slug/locale 三键
* 排序稳定呈现)。confirm 期 candidates 是**事务前快照**,权威数以 publishedCount
* 为准(并发窗口下两者可能不一致)。
*/
candidates: PublishCandidate[]
/** 实际发布条数(dry-run 恒 0;confirm = 事务内 UPDATE 实际行数) */
publishedCount: number
@@ -143,7 +147,7 @@ function upToDatePredicate(siteId: string) {
)
}
/** 候选清单查询(entry_locales ⋈ content_entries;typeKey/slug 排序钉死清单呈现稳定) */
/** 候选清单查询(entry_locales ⋈ content_entries;typeKey/slug/locale 排序钉死清单呈现稳定——locale 决胜同 slug 多 locale 场景) */
async function queryCandidates(db: PublishDb, siteId: string): Promise<PublishCandidate[]> {
const rows = await db
.select({
@@ -157,7 +161,7 @@ async function queryCandidates(db: PublishDb, siteId: string): Promise<PublishCa
.from(entryLocales)
.innerJoin(contentEntries, eq(entryLocales.contentEntryId, contentEntries.id))
.where(pendingPublishPredicate(siteId))
.orderBy(contentEntries.typeKey, entryLocales.slug)
.orderBy(contentEntries.typeKey, entryLocales.slug, entryLocales.locale)
// currentRevisionId 非 null:谓词保证(drizzle 谓词不细化 select 类型)
return rows.map((r) => ({
contentEntryId: r.contentEntryId,