import { optionalString, requireString, type JsonRecord } from './types.ts'
const TABLE_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/
const SCHEMA_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/
export function requireTable(value: unknown): string {
const table = requireString(value, 'table')
if (!TABLE_PATTERN.test(table)) {
throw new Error('table must be a simple identifier (letters, digits, underscore).')
}
return table
}
export function optionalSchema(value: unknown): string | undefined {
const schema = optionalString(value, 'schema')
if (!schema) return undefined
if (!SCHEMA_PATTERN.test(schema)) {
throw new Error('schema must be a simple identifier (letters, digits, underscore).')
}
return schema
}
export function restPath(table: string): string {
return `/rest/v1/${encodeURIComponent(table)}`
}
export function profileHeaders(schema?: string): Record<string, string> {
if (!schema) return {}
return {
'Accept-Profile': schema,
'Content-Profile': schema,
}
}
export function filterQuery(
filters?: Record<string, string>,
extra?: Record<string, string | number | boolean | undefined>,
): Record<string, string | number | boolean | undefined> {
return {
...filters,
...extra,
}
}
export function readFilters(value: unknown): Record<string, string> | undefined {
if (value === undefined || value === null) return undefined
if (typeof value !== 'object' || Array.isArray(value)) {
throw new Error('filters must be an object of PostgREST operators, like { id: "eq.1" }.')
}
const filters: Record<string, string> = {}
for (const [key, item] of Object.entries(value)) {
if (typeof item !== 'string' || item.trim().length === 0) {
throw new Error(`filters.${key} must be a non-empty PostgREST filter string.`)
}
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
throw new Error(`filters key "${key}" must be a column identifier.`)
}
filters[key] = item.trim()
}
return Object.keys(filters).length > 0 ? filters : undefined
}
export function readRows(value: unknown): Array<JsonRecord> {
if (!Array.isArray(value) || value.length === 0) {
throw new Error('rows must be a non-empty array of objects.')
}
return value.map((row, index) => {
if (row === null || typeof row !== 'object' || Array.isArray(row)) {
throw new Error(`rows[${index}] must be an object.`)
}
return row as JsonRecord
})
}
export function readPatch(value: unknown): JsonRecord {
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
throw new Error('values must be an object of columns to update.')
}
if (Object.keys(value).length === 0) {
throw new Error('values must include at least one column.')
}
return value as JsonRecord
}