Conversation
Dokploy Preview Deployment
|
There was a problem hiding this comment.
Pull request overview
重構 Pretalx 相關資料取得與解析流程,將型別定義集中到 shared 並以 Zod 強化型別安全與資料驗證,並新增輸出 OPass JSON 的 API。
Changes:
- 新增
shared/types/pretalx.ts、shared/types/session.ts以 Zod 統一定義 Pretalx 與 Session 型別/Schema - 抽出
fetchPretalxTable,改為並行抓取 Pretalx tables,並更新 parser 與 API 使用新 shared types - 新增
/api/opass.json並更新 prerender 目標;調整 CI/Deploy env 變數名稱為NUXT_PRETALX_*
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| shared/types/session.ts | 新增 Session/Speaker Zod schema 與型別推導 |
| shared/types/pretalx.ts | 新增 Pretalx tables 的 Zod schema、型別與回應結構定義 |
| server/utils/pretalx/type.ts | 移除舊的 Pretalx interface 型別檔 |
| server/utils/pretalx/parser.ts | 更新解析函式型別與錯誤處理,改用 shared types |
| server/utils/pretalx/index.ts | 以 fetchPretalxTable 並行取得各表資料並回傳 PretalxResult |
| server/utils/pretalx/fetch.ts | 新增單表抓取 + Zod 驗證 + map 建立 |
| server/utils/opass/pretalxToOpass.ts | 改用 shared types,調整 slot/room 取值方式 |
| server/api/session/index.get.ts | 改用 shared types,配合 parseSlot 回傳型別調整欄位取值 |
| server/api/session/[id]/index.get.ts | 同上,並調整 slot 取值方式 |
| server/api/opass.json.get.ts | 新增輸出 OPass JSON 的 API endpoint |
| app/app.vue | prerender route 改為 /api/opass.json |
| .github/workflows/deploy.yaml | CI/CD 環境變數改為 NUXT_PRETALX_* |
| .github/workflows/ci.yaml | CI 環境變數改為 NUXT_PRETALX_* |
Comments suppressed due to low confidence (1)
server/utils/pretalx/parser.ts:35
- In the
reduce, the accumulator is typed asRecord<Answer['id'], Answer>, but it’s populated viaacc[ans.question] = ans(question id, not answer id). Align the accumulator type with the actual key (question) to keep type-checking accurate.
const questionMap = answers.reduce((acc: Record<Answer['id'], Answer>, cur: Answer['id']) => {
const ans = answerMap[cur]
if (!ans) {
console.warn('answer not found', cur)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const answers = parseAnswer(submission.answers, data) | ||
| const slot = parseSlot(submission.slots[0], data) | ||
| const slot = parseSlot(submission.slots[0]!, data) | ||
| const speakers = parseSpeaker(submission.speakers, data) | ||
| const type = parseType(submission.submission_type, data) |
There was a problem hiding this comment.
Using submission.slots[0]! can pass undefined at runtime when slots is an empty array (the type number[] doesn’t guarantee a first element). Add a guard before calling parseSlot so the API returns a controlled 404/500 (with a clear message) rather than failing inside the parser.
There was a problem hiding this comment.
一起把同邏輯的檔案 server/api/session/index.get.ts 也處理了
| const roomId = slot.room | ||
|
|
||
| if (!roomId) { | ||
| return null | ||
| } |
There was a problem hiding this comment.
parseSlot returns null when slot.room is null/undefined, which drops start/end even though the slot exists. Consider returning the slot regardless and making only room optional, so schedule times remain available even when room is missing.
There was a problem hiding this comment.
這邊應該直接 throw error
| } | ||
|
|
||
| const room = roomMap[roomId] | ||
|
|
There was a problem hiding this comment.
If roomId is set but roomMap[roomId] is missing, this currently returns a slot with room: undefined silently. Consider throwing a 500 with the missing roomId (consistent with the missing slot/type/speaker handling) to make data issues easier to debug.
| if (!room) { | |
| throw createError({ | |
| statusCode: 500, | |
| statusMessage: `Room not found: ${roomId}`, | |
| }) | |
| } |
| type QuestionKey = keyof typeof QUESTION_MAP | ||
| type ParsedAnswer = Partial<Record<QuestionKey, string>> | ||
|
|
There was a problem hiding this comment.
QuestionKey = keyof typeof QUESTION_MAP won’t become a precise union of keys while QUESTION_MAP is typed as Record<string, number | null> (that annotation erases literal keys and makes keyof effectively string). Consider declaring QUESTION_MAP as a const object (e.g. as const satisfies Record<string, number | null>) so QuestionKey stays strongly typed.
…ons for better null safety
…ng and organization
…allow nullable room
…ooms in pretalxToOpass function
ee123f0 to
ab3a87a
Compare
重構 Pretalx API,改善型別安全