Skip to content

Commit 6802bf7

Browse files
committed
address comments
1 parent de371f8 commit 6802bf7

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

apps/sim/app/api/table/import-csv/route.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ import { normalizeColumn } from '@/app/api/table/utils'
1414

1515
const logger = createLogger('TableImportCSV')
1616

17+
const MAX_CSV_FILE_SIZE = 50 * 1024 * 1024
1718
const MAX_BATCH_SIZE = 1000
1819
const SCHEMA_SAMPLE_SIZE = 100
1920

2021
type ColumnType = 'string' | 'number' | 'boolean' | 'date'
2122

2223
async function parseCsvBuffer(
23-
buffer: Buffer
24+
buffer: Buffer,
25+
delimiter = ','
2426
): Promise<{ headers: string[]; rows: Record<string, unknown>[] }> {
2527
const { parse } = await import('csv-parse/sync')
2628
const parsed = parse(buffer.toString('utf-8'), {
@@ -31,6 +33,7 @@ async function parseCsvBuffer(
3133
relax_quotes: true,
3234
skip_records_with_error: true,
3335
cast: false,
36+
delimiter,
3437
}) as Record<string, unknown>[]
3538

3639
if (parsed.length === 0) {
@@ -121,8 +124,10 @@ function coerceValue(value: unknown, colType: ColumnType): string | number | boo
121124
const s = String(value).toLowerCase()
122125
return s === 'true'
123126
}
124-
case 'date':
125-
return new Date(String(value)).toISOString()
127+
case 'date': {
128+
const d = new Date(String(value))
129+
return Number.isNaN(d.getTime()) ? String(value) : d.toISOString()
130+
}
126131
default:
127132
return String(value)
128133
}
@@ -164,6 +169,13 @@ export async function POST(request: NextRequest) {
164169
return NextResponse.json({ error: 'CSV file is required' }, { status: 400 })
165170
}
166171

172+
if (file.size > MAX_CSV_FILE_SIZE) {
173+
return NextResponse.json(
174+
{ error: `File exceeds maximum allowed size of ${MAX_CSV_FILE_SIZE / (1024 * 1024)} MB` },
175+
{ status: 400 }
176+
)
177+
}
178+
167179
if (!workspaceId) {
168180
return NextResponse.json({ error: 'Workspace ID is required' }, { status: 400 })
169181
}
@@ -179,7 +191,8 @@ export async function POST(request: NextRequest) {
179191
}
180192

181193
const buffer = Buffer.from(await file.arrayBuffer())
182-
const { headers, rows } = await parseCsvBuffer(buffer)
194+
const delimiter = ext === 'tsv' ? '\t' : ','
195+
const { headers, rows } = await parseCsvBuffer(buffer, delimiter)
183196

184197
const columns = inferSchema(headers, rows)
185198
const headerToColumn = new Map(headers.map((h, i) => [h, columns[i].name]))

apps/sim/app/workspace/[workspaceId]/tables/tables.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
ModalContent,
1111
ModalFooter,
1212
ModalHeader,
13+
toast,
1314
Upload,
1415
} from '@/components/emcn'
1516
import { Columns3, Rows3, Table as TableIcon } from '@/components/emcn/icons'
@@ -171,11 +172,12 @@ export function Tables() {
171172
})
172173

173174
if (csvFiles.length === 0) {
174-
logger.warn('No CSV/TSV files selected')
175+
toast.error('No CSV or TSV files selected')
175176
return
176177
}
177178

178179
setUploadProgress({ completed: 0, total: csvFiles.length })
180+
const failed: string[] = []
179181

180182
for (let i = 0; i < csvFiles.length; i++) {
181183
try {
@@ -189,11 +191,21 @@ export function Tables() {
189191
}
190192
}
191193
} catch (err) {
194+
failed.push(csvFiles[i].name)
192195
logger.error('Error uploading CSV:', err)
193196
}
194197
}
198+
199+
if (failed.length > 0) {
200+
toast.error(
201+
failed.length === 1
202+
? `Failed to import ${failed[0]}`
203+
: `Failed to import ${failed.length} file${failed.length > 1 ? 's' : ''}: ${failed.join(', ')}`
204+
)
205+
}
195206
} catch (err) {
196207
logger.error('Error uploading CSV:', err)
208+
toast.error('Failed to import CSV')
197209
} finally {
198210
setUploading(false)
199211
setUploadProgress({ completed: 0, total: 0 })

0 commit comments

Comments
 (0)