Files
supabase/apps/studio/lib/sql-parameters.ts
Joshen Lim 7f5865872a Enforce noUnusedLocals and noUnusedParameters in tsconfig.json + fix all related issues (#45264)
## Context

Enforce `noUnusedLocals` and `noUnusedParameters` in tsconfig.json + fix
all related issues
2026-04-27 17:42:34 +08:00

115 lines
3.3 KiB
TypeScript

export interface Parameter {
name: string
value: string
defaultValue?: string
type?: string
possibleValues?: string[]
occurrences: number
}
// [Joshen TODO] We'll want tests for this to ensure that this runs properly
export const parseParameters = (sql: string | undefined) => {
if (!sql) return []
// Parse @set parameter defaults with optional type information
const setParamRegex = /@set\s+(\w+)(?::([^=]+))?\s*=\s*([^;\n]+)/g
const paramDefaults: Record<string, { value: string; type?: string; possibleValues?: string[] }> =
{}
let match
while ((match = setParamRegex.exec(sql)) !== null) {
const [_, paramName, paramType, paramValue] = match
if (!paramName || !paramValue?.trim()) continue
const typeInfo = paramType?.trim()
let type: string | undefined
let possibleValues: string[] | undefined
if (typeInfo) {
// Handle union types (value1 | value2 | value3)
if (typeInfo.includes('|')) {
possibleValues = typeInfo.split('|').map((v) => v.trim())
type = 'enum'
} else {
type = typeInfo.trim()
}
}
paramDefaults[paramName] = {
value: paramValue.trim(),
type,
possibleValues,
}
}
// Find all :parameter occurrences and count them
const paramRegex = /:(\w+)/g
const paramOccurrences: Record<string, number> = {}
const uniqueParams = new Set<string>()
while ((match = paramRegex.exec(sql)) !== null) {
const [_, paramName] = match
paramOccurrences[paramName] = (paramOccurrences[paramName] || 0) + 1
uniqueParams.add(paramName)
}
// Create parameter objects for unique parameters
return Array.from(uniqueParams).map((paramName) => ({
name: paramName,
value: paramDefaults[paramName]?.value || '',
defaultValue: paramDefaults[paramName]?.value,
type: paramDefaults[paramName]?.type,
possibleValues: paramDefaults[paramName]?.possibleValues,
occurrences: paramOccurrences[paramName],
}))
}
export const processParameterizedSql = (sql: string, parameters: Record<string, string>) => {
// Parse @set parameter defaults with type information from SQL
const setParamRegex = /@set\s+(\w+)(?::([^=]+))?\s*=\s*([^;\n]+)/g
const paramDefaults: Record<string, { value: string; type?: string; possibleValues?: string[] }> =
{}
let match
while ((match = setParamRegex.exec(sql)) !== null) {
const [_, paramName, paramType, paramValue] = match
if (!paramName || !paramValue?.trim()) continue
const typeInfo = paramType?.trim()
let type: string | undefined
let possibleValues: string[] | undefined
if (typeInfo) {
if (typeInfo.includes('|')) {
possibleValues = typeInfo.split('|').map((v) => v.trim())
type = 'enum'
} else {
type = typeInfo.trim()
}
}
paramDefaults[paramName] = {
value: paramValue.trim(),
type,
possibleValues,
}
}
// Remove @set lines from SQL
let processedSql = sql.replace(/@set\s+\w+(?:\s*:\s*[^=]+)?\s*=\s*[^;\n]+[\n;]*/g, '')
// Replace :parameters with values
const paramRegex = /:(\w+)/g
processedSql = processedSql.replace(paramRegex, (_match, paramName) => {
const value = parameters[paramName] ?? paramDefaults[paramName]?.value
if (value === undefined) {
throw new Error(`Missing value for parameter: ${paramName}`)
}
return value
})
return processedSql
}