diff --git a/apps/studio/components/ui/SafeSqlInput.tsx b/apps/studio/components/ui/SafeSqlInput.tsx new file mode 100644 index 00000000000..1dbb6631051 --- /dev/null +++ b/apps/studio/components/ui/SafeSqlInput.tsx @@ -0,0 +1,15 @@ +import { rawSql, type SafeSqlFragment } from '@supabase/pg-meta' +import type { ChangeEvent, ComponentProps } from 'react' +import { Input } from 'ui-patterns/DataInputs/Input' + +type InputProps = ComponentProps + +export type SafeSqlInputProps = Omit & { + placeholder?: SafeSqlFragment + value: SafeSqlFragment + onChange?: (event: ChangeEvent, value: SafeSqlFragment) => void +} + +export const SafeSqlInput = ({ onChange, ...props }: SafeSqlInputProps) => ( + onChange?.(event, rawSql(event.target.value))} /> +) diff --git a/apps/studio/lib/postgres-types.ts b/apps/studio/lib/postgres-types.ts new file mode 100644 index 00000000000..50a5c01572a --- /dev/null +++ b/apps/studio/lib/postgres-types.ts @@ -0,0 +1,12 @@ +import type { PGColumn, PGTable, SafeSqlFragment } from '@supabase/pg-meta' + +export type SafePostgresColumn = PGColumn & { + check: SafeSqlFragment | null + // Present when sourced from pg-meta's SQL queries (e.g. `pgMeta.tables.retrieve`), absent + // from the legacy `/platform/pg-meta/{ref}/tables` REST endpoint. + format_schema?: string +} + +export type SafePostgresTable = Omit & { + columns?: SafePostgresColumn[] | undefined +} diff --git a/apps/studio/lib/sql.ts b/apps/studio/lib/sql.ts new file mode 100644 index 00000000000..45a76ac9778 --- /dev/null +++ b/apps/studio/lib/sql.ts @@ -0,0 +1,13 @@ +import type { SafeSqlFragment } from '@supabase/pg-meta' + +export function trimSafeSqlFragment(fragment: SafeSqlFragment): SafeSqlFragment +export function trimSafeSqlFragment(fragment: SafeSqlFragment | null): SafeSqlFragment | null +export function trimSafeSqlFragment( + fragment: SafeSqlFragment | undefined +): SafeSqlFragment | undefined +export function trimSafeSqlFragment( + fragment: SafeSqlFragment | null | undefined +): SafeSqlFragment | null | undefined { + if (fragment == null) return fragment + return fragment.trim() as SafeSqlFragment +} diff --git a/apps/studio/lib/type-helpers.ts b/apps/studio/lib/type-helpers.ts index 02b486eac21..a7310684875 100644 --- a/apps/studio/lib/type-helpers.ts +++ b/apps/studio/lib/type-helpers.ts @@ -2,8 +2,12 @@ export type PlainObject = Record = { [K in keyof T]: T[K] } & {} -export type DeepReadonly = T extends (infer R)[] - ? ReadonlyArray> - : T extends Object - ? { readonly [K in keyof T]: DeepReadonly } - : T +type Primitive = string | number | bigint | boolean | symbol | null | undefined + +export type DeepReadonly = T extends Primitive + ? T + : T extends (infer R)[] + ? ReadonlyArray> + : T extends object + ? { readonly [K in keyof T]: DeepReadonly } + : T