Skip to content

Commit d8e3c56

Browse files
committed
fix(gmail): use shared contract for edit-draft route
1 parent 8802be8 commit d8e3c56

3 files changed

Lines changed: 20 additions & 32 deletions

File tree

apps/sim/app/api/tools/gmail/edit-draft/route.ts

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { createLogger } from '@sim/logger'
22
import { type NextRequest, NextResponse } from 'next/server'
3-
import { z } from 'zod'
3+
import { gmailEditDraftContract } from '@/lib/api/contracts/google-tools'
4+
import { parseRequest } from '@/lib/api/server'
45
import { checkInternalAuth } from '@/lib/auth/hybrid'
56
import { generateRequestId } from '@/lib/core/utils/request'
67
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
7-
import { RawFileInputArraySchema } from '@/lib/uploads/utils/file-schemas'
88
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
99
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
1010
import {
@@ -19,20 +19,6 @@ export const dynamic = 'force-dynamic'
1919

2020
const logger = createLogger('GmailEditDraftAPI')
2121

22-
const GmailEditDraftSchema = z.object({
23-
accessToken: z.string().min(1, 'Access token is required'),
24-
draftId: z.string().min(1, 'Draft ID is required'),
25-
to: z.string().min(1, 'Recipient email is required'),
26-
subject: z.string().optional().nullable(),
27-
body: z.string().min(1, 'Email body is required'),
28-
contentType: z.enum(['text', 'html']).optional().nullable(),
29-
threadId: z.string().optional().nullable(),
30-
replyToMessageId: z.string().optional().nullable(),
31-
cc: z.string().optional().nullable(),
32-
bcc: z.string().optional().nullable(),
33-
attachments: RawFileInputArraySchema.optional().nullable(),
34-
})
35-
3622
export const POST = withRouteHandler(async (request: NextRequest) => {
3723
const requestId = generateRequestId()
3824

@@ -55,8 +41,9 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
5541
{ userId: authResult.userId }
5642
)
5743

58-
const body = await request.json()
59-
const validatedData = GmailEditDraftSchema.parse(body)
44+
const parsed = await parseRequest(gmailEditDraftContract, request, {})
45+
if (!parsed.success) return parsed.response
46+
const validatedData = parsed.data.body
6047

6148
logger.info(`[${requestId}] Updating Gmail draft`, {
6249
draftId: validatedData.draftId,
@@ -180,18 +167,6 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
180167
},
181168
})
182169
} catch (error) {
183-
if (error instanceof z.ZodError) {
184-
logger.warn(`[${requestId}] Invalid request data`, { errors: error.errors })
185-
return NextResponse.json(
186-
{
187-
success: false,
188-
error: 'Invalid request data',
189-
details: error.errors,
190-
},
191-
{ status: 400 }
192-
)
193-
}
194-
195170
logger.error(`[${requestId}] Error updating Gmail draft:`, error)
196171

197172
return NextResponse.json(

apps/sim/lib/api/contracts/google-tools.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ export const gmailMailBodySchema = z.object({
3333
attachments: RawFileInputArraySchema.optional().nullable(),
3434
})
3535

36+
export const gmailEditDraftBodySchema = gmailMailBodySchema.extend({
37+
draftId: z.string().min(1, 'Draft ID is required'),
38+
})
39+
3640
export const googleDriveUploadBodySchema = z.object({
3741
accessToken: googleAccessTokenSchema,
3842
fileName: z.string().min(1, 'File name is required'),
@@ -86,6 +90,13 @@ export const gmailDraftContract = defineRouteContract({
8690
response: { mode: 'json', schema: toolJsonResponseSchema },
8791
})
8892

93+
export const gmailEditDraftContract = defineRouteContract({
94+
method: 'POST',
95+
path: '/api/tools/gmail/edit-draft',
96+
body: gmailEditDraftBodySchema,
97+
response: { mode: 'json', schema: toolJsonResponseSchema },
98+
})
99+
89100
export const gmailMarkReadContract = defineRouteContract({
90101
method: 'POST',
91102
path: '/api/tools/gmail/mark-read',
@@ -153,6 +164,7 @@ export type GmailAddLabelBody = ContractBodyInput<typeof gmailAddLabelContract>
153164
export type GmailArchiveBody = ContractBodyInput<typeof gmailArchiveContract>
154165
export type GmailDeleteBody = ContractBodyInput<typeof gmailDeleteContract>
155166
export type GmailDraftBody = ContractBodyInput<typeof gmailDraftContract>
167+
export type GmailEditDraftBody = ContractBodyInput<typeof gmailEditDraftContract>
156168
export type GmailMarkReadBody = ContractBodyInput<typeof gmailMarkReadContract>
157169
export type GmailMarkUnreadBody = ContractBodyInput<typeof gmailMarkUnreadContract>
158170
export type GmailMoveBody = ContractBodyInput<typeof gmailMoveContract>
@@ -169,6 +181,7 @@ export type GmailAddLabelResponse = ContractJsonResponse<typeof gmailAddLabelCon
169181
export type GmailArchiveResponse = ContractJsonResponse<typeof gmailArchiveContract>
170182
export type GmailDeleteResponse = ContractJsonResponse<typeof gmailDeleteContract>
171183
export type GmailDraftResponse = ContractJsonResponse<typeof gmailDraftContract>
184+
export type GmailEditDraftResponse = ContractJsonResponse<typeof gmailEditDraftContract>
172185
export type GmailMarkReadResponse = ContractJsonResponse<typeof gmailMarkReadContract>
173186
export type GmailMarkUnreadResponse = ContractJsonResponse<typeof gmailMarkUnreadContract>
174187
export type GmailMoveResponse = ContractJsonResponse<typeof gmailMoveContract>

scripts/check-api-validation-contracts.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ const QUERY_HOOKS_DIR = path.join(ROOT, 'apps/sim/hooks/queries')
99
const SELECTOR_HOOKS_DIR = path.join(ROOT, 'apps/sim/hooks/selectors')
1010

1111
const BASELINE = {
12-
totalRoutes: 715,
13-
zodRoutes: 715,
12+
totalRoutes: 716,
13+
zodRoutes: 716,
1414
nonZodRoutes: 0,
1515
} as const
1616

0 commit comments

Comments
 (0)