返回 oh-my-ppt
page-merge-handlers.ts
根目录 / src / main / session / page-merge-handlers.ts
1 import { ipcMain } from 'electron'
2 import log from 'electron-log/main.js'
3 import type { IpcContext } from '../ipc/context'
4 import {
5 listMergeSourcePages,
6 listMergeSourceSessions,
7 listMergeSourceTemplatePages,
8 listMergeSourceTemplates,
9 mergeSessionPages
10 } from './page-merge-service'
11 import { PageMergeError, type PageMergeErrorCode } from '../../shared/page-merge'
12
13 const readString = (record: Record<string, unknown>, key: string): string =>
14 typeof record[key] === 'string' ? record[key].trim() : ''
15
16 const runPageMergeRequest = async <T>(
17 channel: string,
18 context: Record<string, unknown>,
19 task: () => Promise<T>
20 ): Promise<T> => {
21 const startedAt = Date.now()
22 log.info('[page-merge:ipc]', { channel, stage: 'start', ...context })
23 try {
24 const result = await task()
25 log.info('[page-merge:ipc]', {
26 channel,
27 stage: 'completed',
28 durationMs: Date.now() - startedAt,
29 ...context
30 })
31 return result
32 } catch (error) {
33 const code: PageMergeErrorCode =
34 error instanceof PageMergeError ? error.code : 'PAGE_MERGE_INTERNAL_ERROR'
35 log.warn('[page-merge:ipc]', {
36 channel,
37 stage: 'failed',
38 code,
39 durationMs: Date.now() - startedAt,
40 ...context,
41 error: error instanceof Error ? error.message : String(error)
42 })
43 throw new Error(code)
44 }
45 }
46
47 export function registerPageMergeHandlers(ctx: IpcContext): void {
48 ipcMain.handle('session:listMergeSources', async (_event, payload: unknown) => {
49 const record =
50 payload && typeof payload === 'object' ? (payload as Record<string, unknown>) : {}
51 const targetSessionId = readString(record, 'targetSessionId')
52 if (!targetSessionId) throw new Error('PAGE_MERGE_INVALID_REQUEST')
53 return runPageMergeRequest('session:listMergeSources', { targetSessionId }, () =>
54 listMergeSourceSessions(ctx, targetSessionId)
55 )
56 })
57
58 ipcMain.handle('session:listMergeSourceTemplates', async (_event, payload: unknown) => {
59 const record =
60 payload && typeof payload === 'object' ? (payload as Record<string, unknown>) : {}
61 const targetSessionId = readString(record, 'targetSessionId')
62 if (!targetSessionId) throw new Error('PAGE_MERGE_INVALID_REQUEST')
63 return runPageMergeRequest('session:listMergeSourceTemplates', { targetSessionId }, () =>
64 listMergeSourceTemplates(ctx, targetSessionId)
65 )
66 })
67
68 ipcMain.handle('session:listMergeSourcePages', async (_event, payload: unknown) => {
69 const record =
70 payload && typeof payload === 'object' ? (payload as Record<string, unknown>) : {}
71 const targetSessionId = readString(record, 'targetSessionId')
72 const sourceType = readString(record, 'sourceType') || 'session'
73 if (!targetSessionId) throw new Error('PAGE_MERGE_INVALID_REQUEST')
74 if (sourceType === 'template') {
75 const templateId = readString(record, 'templateId')
76 if (!templateId) throw new Error('PAGE_MERGE_INVALID_REQUEST')
77 return runPageMergeRequest(
78 'session:listMergeSourcePages',
79 { targetSessionId, sourceType, templateId },
80 () => listMergeSourceTemplatePages(ctx, targetSessionId, templateId)
81 )
82 }
83 const sourceSessionId = readString(record, 'sourceSessionId')
84 if (!sourceSessionId) throw new Error('PAGE_MERGE_INVALID_REQUEST')
85 if (targetSessionId === sourceSessionId) throw new Error('PAGE_MERGE_SAME_SESSION')
86 return runPageMergeRequest(
87 'session:listMergeSourcePages',
88 { targetSessionId, sourceSessionId },
89 () => listMergeSourcePages(ctx, sourceSessionId)
90 )
91 })
92
93 ipcMain.handle('session:mergePages', async (_event, payload: unknown) => {
94 const record =
95 payload && typeof payload === 'object' ? (payload as Record<string, unknown>) : {}
96 const targetSessionId = readString(record, 'targetSessionId')
97 const sourceType = readString(record, 'sourceType') || 'session'
98 const sourcePageIds = record.sourcePageIds
99 if (
100 !targetSessionId ||
101 !Array.isArray(sourcePageIds) ||
102 sourcePageIds.some((item) => typeof item !== 'string')
103 ) {
104 throw new Error('PAGE_MERGE_INVALID_REQUEST')
105 }
106 const selectedPageCount = sourcePageIds.length
107 if (sourceType === 'template') {
108 const sourceTemplateId = readString(record, 'templateId')
109 if (!sourceTemplateId) throw new Error('PAGE_MERGE_INVALID_REQUEST')
110 return runPageMergeRequest(
111 'session:mergePages',
112 { targetSessionId, sourceType, sourceTemplateId, selectedPageCount },
113 async () => {
114 const result = await mergeSessionPages(ctx, {
115 targetSessionId,
116 sourceType: 'template',
117 sourceTemplateId,
118 sourcePageIds: sourcePageIds as string[]
119 })
120 return { ok: true, ...result }
121 }
122 )
123 }
124 const sourceSessionId = readString(record, 'sourceSessionId')
125 if (!sourceSessionId) throw new Error('PAGE_MERGE_INVALID_REQUEST')
126 return runPageMergeRequest(
127 'session:mergePages',
128 { targetSessionId, sourceType, sourceSessionId, selectedPageCount },
129 async () => {
130 const result = await mergeSessionPages(ctx, {
131 targetSessionId,
132 sourceType: 'session',
133 sourceSessionId,
134 sourcePageIds: sourcePageIds as string[]
135 })
136 return { ok: true, ...result }
137 }
138 )
139 })
140 }
141
141 lines TYPESCRIPT