Skip to content

Commit ffce93b

Browse files
waleedlatif1claude
andcommitted
refactor(types): use drizzle $inferSelect for row types
Replace hand-written interfaces that duplicated schema shape with typeof table.$inferSelect aliases for webhook, workflow, and workspaceFiles rows. Also simplify metadata insert/update to use .returning() instead of field-by-field copies. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 2e3a341 commit ffce93b

5 files changed

Lines changed: 37 additions & 144 deletions

File tree

apps/sim/lib/uploads/server/metadata.ts

Lines changed: 24 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,7 @@ import type { StorageContext } from '../shared/types'
66

77
const logger = createLogger('FileMetadata')
88

9-
export interface FileMetadataRecord {
10-
id: string
11-
key: string
12-
userId: string
13-
workspaceId: string | null
14-
context: string
15-
originalName: string
16-
contentType: string
17-
size: number
18-
deletedAt?: Date | null
19-
uploadedAt: Date
20-
}
9+
export type FileMetadataRecord = typeof workspaceFiles.$inferSelect
2110

2211
export interface FileMetadataInsertOptions {
2312
key: string
@@ -52,7 +41,7 @@ export async function insertFileMetadata(
5241
.limit(1)
5342

5443
if (existingDeleted.length > 0 && existingDeleted[0].deletedAt) {
55-
await db
44+
const [restored] = await db
5645
.update(workspaceFiles)
5746
.set({
5847
userId,
@@ -65,19 +54,9 @@ export async function insertFileMetadata(
6554
uploadedAt: new Date(),
6655
})
6756
.where(eq(workspaceFiles.id, existingDeleted[0].id))
57+
.returning()
6858

69-
return {
70-
id: existingDeleted[0].id,
71-
key,
72-
userId,
73-
workspaceId: workspaceId || null,
74-
context,
75-
originalName,
76-
contentType,
77-
size,
78-
deletedAt: null,
79-
uploadedAt: new Date(),
80-
}
59+
return restored
8160
}
8261

8362
const existing = await db
@@ -87,48 +66,29 @@ export async function insertFileMetadata(
8766
.limit(1)
8867

8968
if (existing.length > 0) {
90-
return {
91-
id: existing[0].id,
92-
key: existing[0].key,
93-
userId: existing[0].userId,
94-
workspaceId: existing[0].workspaceId,
95-
context: existing[0].context,
96-
originalName: existing[0].originalName,
97-
contentType: existing[0].contentType,
98-
size: existing[0].size,
99-
deletedAt: existing[0].deletedAt,
100-
uploadedAt: existing[0].uploadedAt,
101-
}
69+
return existing[0]
10270
}
10371

10472
const fileId = id || (await import('uuid')).v4()
10573

10674
try {
107-
await db.insert(workspaceFiles).values({
108-
id: fileId,
109-
key,
110-
userId,
111-
workspaceId: workspaceId || null,
112-
context,
113-
originalName,
114-
contentType,
115-
size,
116-
deletedAt: null,
117-
uploadedAt: new Date(),
118-
})
75+
const [inserted] = await db
76+
.insert(workspaceFiles)
77+
.values({
78+
id: fileId,
79+
key,
80+
userId,
81+
workspaceId: workspaceId || null,
82+
context,
83+
originalName,
84+
contentType,
85+
size,
86+
deletedAt: null,
87+
uploadedAt: new Date(),
88+
})
89+
.returning()
11990

120-
return {
121-
id: fileId,
122-
key,
123-
userId,
124-
workspaceId: workspaceId || null,
125-
context,
126-
originalName,
127-
contentType,
128-
size,
129-
deletedAt: null,
130-
uploadedAt: new Date(),
131-
}
91+
return inserted
13292
} catch (error) {
13393
if (
13494
(error as any)?.code === '23505' ||
@@ -141,18 +101,7 @@ export async function insertFileMetadata(
141101
.limit(1)
142102

143103
if (existingAfterError.length > 0) {
144-
return {
145-
id: existingAfterError[0].id,
146-
key: existingAfterError[0].key,
147-
userId: existingAfterError[0].userId,
148-
workspaceId: existingAfterError[0].workspaceId,
149-
context: existingAfterError[0].context,
150-
originalName: existingAfterError[0].originalName,
151-
contentType: existingAfterError[0].contentType,
152-
size: existingAfterError[0].size,
153-
deletedAt: existingAfterError[0].deletedAt,
154-
uploadedAt: existingAfterError[0].uploadedAt,
155-
}
104+
return existingAfterError[0]
156105
}
157106
}
158107

@@ -186,22 +135,7 @@ export async function getFileMetadataByKey(
186135
.where(conditions.length > 1 ? and(...conditions) : conditions[0])
187136
.limit(1)
188137

189-
if (!record) {
190-
return null
191-
}
192-
193-
return {
194-
id: record.id,
195-
key: record.key,
196-
userId: record.userId,
197-
workspaceId: record.workspaceId,
198-
context: record.context,
199-
originalName: record.originalName,
200-
contentType: record.contentType,
201-
size: record.size,
202-
deletedAt: record.deletedAt,
203-
uploadedAt: record.uploadedAt,
204-
}
138+
return record ?? null
205139
}
206140

207141
/**
@@ -225,24 +159,11 @@ export async function getFileMetadataByContext(
225159
conditions.push(isNull(workspaceFiles.deletedAt))
226160
}
227161

228-
const records = await db
162+
return db
229163
.select()
230164
.from(workspaceFiles)
231165
.where(conditions.length > 1 ? and(...conditions) : conditions[0])
232166
.orderBy(workspaceFiles.uploadedAt)
233-
234-
return records.map((record) => ({
235-
id: record.id,
236-
key: record.key,
237-
userId: record.userId,
238-
workspaceId: record.workspaceId,
239-
context: record.context,
240-
originalName: record.originalName,
241-
contentType: record.contentType,
242-
size: record.size,
243-
deletedAt: record.deletedAt,
244-
uploadedAt: record.uploadedAt,
245-
}))
246167
}
247168

248169
/**

apps/sim/lib/webhooks/polling/orchestrator.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createLogger } from '@sim/logger'
22
import { generateShortId } from '@sim/utils/id'
33
import { getPollingHandler } from '@/lib/webhooks/polling/registry'
4-
import type { PollSummary, WebhookRecord, WorkflowRecord } from '@/lib/webhooks/polling/types'
4+
import type { PollSummary } from '@/lib/webhooks/polling/types'
55
import { fetchActiveWebhooks, runWithConcurrency } from '@/lib/webhooks/polling/utils'
66

77
/** Poll all active webhooks for a given provider. */
@@ -27,8 +27,8 @@ export async function pollProvider(providerName: string): Promise<PollSummary> {
2727
async (entry) => {
2828
const requestId = generateShortId()
2929
return handler.pollWebhook({
30-
webhookData: entry.webhook as WebhookRecord,
31-
workflowData: entry.workflow as WorkflowRecord,
30+
webhookData: entry.webhook,
31+
workflowData: entry.workflow,
3232
requestId,
3333
logger,
3434
})

apps/sim/lib/webhooks/polling/types.ts

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { webhook, workflow } from '@sim/db/schema'
12
import type { Logger } from '@sim/logger'
23

34
/** Summary returned after polling all webhooks for a provider. */
@@ -15,25 +16,8 @@ export interface PollWebhookContext {
1516
logger: Logger
1617
}
1718

18-
/** DB row shape for the webhook table. */
19-
export interface WebhookRecord {
20-
id: string
21-
path: string
22-
provider: string | null
23-
blockId: string | null
24-
providerConfig: unknown
25-
credentialSetId: string | null
26-
workflowId: string
27-
[key: string]: unknown
28-
}
29-
30-
/** DB row shape for the workflow table. */
31-
export interface WorkflowRecord {
32-
id: string
33-
userId: string
34-
workspaceId: string
35-
[key: string]: unknown
36-
}
19+
export type WebhookRecord = typeof webhook.$inferSelect
20+
export type WorkflowRecord = typeof workflow.$inferSelect
3721

3822
/**
3923
* Strategy interface for provider-specific polling behavior.

apps/sim/lib/webhooks/polling/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export async function fetchActiveWebhooks(
9696
)
9797
)
9898

99-
return rows as unknown as { webhook: WebhookRecord; workflow: WorkflowRecord }[]
99+
return rows
100100
}
101101

102102
/**

apps/sim/lib/webhooks/processor.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -642,21 +642,8 @@ export interface PolledWebhookEventResult {
642642
statusCode?: number
643643
}
644644

645-
interface PolledWebhookRecord {
646-
id: string
647-
path: string
648-
provider: string | null
649-
blockId: string | null
650-
providerConfig: unknown
651-
credentialSetId: string | null
652-
workflowId: string
653-
}
654-
655-
interface PolledWorkflowRecord {
656-
id: string
657-
userId: string
658-
workspaceId: string
659-
}
645+
type PolledWebhookRecord = typeof webhook.$inferSelect
646+
type PolledWorkflowRecord = typeof workflow.$inferSelect
660647

661648
/**
662649
* Processes a polled webhook event directly, bypassing the HTTP trigger route.
@@ -739,6 +726,7 @@ export async function processPolledWebhookEvent(
739726
triggerType: 'webhook',
740727
} satisfies AsyncExecutionCorrelation)
741728

729+
const workspaceId = foundWorkflow.workspaceId ?? undefined
742730
const payload = {
743731
webhookId: foundWebhook.id,
744732
workflowId: foundWorkflow.id,
@@ -751,15 +739,15 @@ export async function processPolledWebhookEvent(
751739
headers: { 'content-type': 'application/json' } as Record<string, string>,
752740
path: foundWebhook.path,
753741
blockId: foundWebhook.blockId ?? undefined,
754-
workspaceId: foundWorkflow.workspaceId,
742+
workspaceId,
755743
...(credentialId ? { credentialId } : {}),
756744
}
757745

758746
if (isPollingWebhookProvider(payload.provider) && !shouldExecuteInline()) {
759747
const jobId = await (await getJobQueue()).enqueue('webhook-execution', payload, {
760748
metadata: {
761749
workflowId: foundWorkflow.id,
762-
workspaceId: foundWorkflow.workspaceId,
750+
workspaceId,
763751
userId: actorUserId,
764752
correlation,
765753
},
@@ -772,7 +760,7 @@ export async function processPolledWebhookEvent(
772760
const jobId = await jobQueue.enqueue('webhook-execution', payload, {
773761
metadata: {
774762
workflowId: foundWorkflow.id,
775-
workspaceId: foundWorkflow.workspaceId,
763+
workspaceId,
776764
userId: actorUserId,
777765
correlation,
778766
},

0 commit comments

Comments
 (0)