Skip to content

Commit 2e0de90

Browse files
committed
refactor(csv): extract neutralizeCsvFormula to shared util
1 parent 5d37621 commit 2e0de90

3 files changed

Lines changed: 9 additions & 16 deletions

File tree

apps/sim/app/api/logs/export/route.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { and, desc, eq, sql } from 'drizzle-orm'
55
import { type NextRequest, NextResponse } from 'next/server'
66
import { getSession } from '@/lib/auth'
77
import { MATERIALIZE_CONCURRENCY, mapWithConcurrency } from '@/lib/core/utils/concurrency'
8+
import { neutralizeCsvFormula } from '@/lib/core/utils/csv'
89
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
910
import { materializeExecutionData } from '@/lib/logs/execution/trace-store'
1011
import { buildFilterConditions, LogFilterParamsSchema } from '@/lib/logs/filters'
@@ -14,14 +15,6 @@ const logger = createLogger('LogsExportAPI')
1415

1516
export const revalidate = 0
1617

17-
/**
18-
* Prefixes a single quote to values starting with a spreadsheet formula trigger
19-
* (`=`, `+`, `-`, `@`, tab, CR), neutralizing CSV injection in Excel/Sheets.
20-
*/
21-
function neutralizeCsvFormula(value: string): string {
22-
return /^[=+\-@\t\r]/.test(value) ? `'${value}` : value
23-
}
24-
2518
function escapeCsv(value: any): string {
2619
if (value === null || value === undefined) return ''
2720
const str = neutralizeCsvFormula(String(value))

apps/sim/app/api/table/[tableId]/export/route.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { type NextRequest, NextResponse } from 'next/server'
33
import { tableExportFormatSchema, tableIdParamsSchema } from '@/lib/api/contracts/tables'
44
import { getValidationErrorMessage } from '@/lib/api/server'
55
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
6+
import { neutralizeCsvFormula } from '@/lib/core/utils/csv'
67
import { generateRequestId } from '@/lib/core/utils/request'
78
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
89
import { buildNameById, getColumnId, rowDataIdToName } from '@/lib/table/column-keys'
@@ -119,14 +120,6 @@ function sanitizeFilename(name: string): string {
119120
return cleaned || 'table'
120121
}
121122

122-
/**
123-
* Prefixes a single quote to values starting with a spreadsheet formula trigger
124-
* (`=`, `+`, `-`, `@`, tab, CR), neutralizing CSV injection in Excel/Sheets.
125-
*/
126-
function neutralizeCsvFormula(value: string): string {
127-
return /^[=+\-@\t\r]/.test(value) ? `'${value}` : value
128-
}
129-
130123
/**
131124
* Serializes a cell for CSV. Only string cells are formula-neutralized; numbers,
132125
* booleans, dates, and JSON objects can never form a trigger and pass through verbatim.

apps/sim/lib/core/utils/csv.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* Prefixes a single quote to values starting with a spreadsheet formula trigger
3+
* (`=`, `+`, `-`, `@`, tab, CR), neutralizing CSV injection in Excel/Sheets.
4+
*/
5+
export function neutralizeCsvFormula(value: string): string {
6+
return /^[=+\-@\t\r]/.test(value) ? `'${value}` : value
7+
}

0 commit comments

Comments
 (0)